summaryrefslogtreecommitdiff
path: root/storage/perfschema
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2019-12-10 15:35:00 +0100
committerSergei Golubchik <serg@mariadb.org>2020-03-10 19:24:22 +0100
commit0ea717f51a152afdb3791195c4a25ee0baa2faac (patch)
tree0eb10fc1413d1583ffdec2c18a66491d7befeec2 /storage/perfschema
parentdfe6e914e58472159f34a8a4c9288ff61eac479f (diff)
downloadmariadb-git-0ea717f51a152afdb3791195c4a25ee0baa2faac.tar.gz
P_S 5.7.28
Diffstat (limited to 'storage/perfschema')
-rw-r--r--storage/perfschema/CMakeLists.txt123
-rw-r--r--storage/perfschema/cursor_by_account.cc33
-rw-r--r--storage/perfschema/cursor_by_account.h4
-rw-r--r--storage/perfschema/cursor_by_host.cc35
-rw-r--r--storage/perfschema/cursor_by_host.h4
-rw-r--r--storage/perfschema/cursor_by_thread.cc32
-rw-r--r--storage/perfschema/cursor_by_thread.h4
-rw-r--r--storage/perfschema/cursor_by_thread_connect_attr.cc40
-rw-r--r--storage/perfschema/cursor_by_thread_connect_attr.h13
-rw-r--r--storage/perfschema/cursor_by_user.cc33
-rw-r--r--storage/perfschema/cursor_by_user.h4
-rw-r--r--storage/perfschema/gen_pfs_lex_token.cc358
-rw-r--r--storage/perfschema/ha_perfschema.cc67
-rw-r--r--storage/perfschema/ha_perfschema.h2
-rw-r--r--storage/perfschema/my_thread.h90
-rw-r--r--storage/perfschema/pfs.cc2864
-rw-r--r--storage/perfschema/pfs.h24
-rw-r--r--storage/perfschema/pfs_account.cc551
-rw-r--r--storage/perfschema/pfs_account.h31
-rw-r--r--storage/perfschema/pfs_atomic.h36
-rw-r--r--storage/perfschema/pfs_autosize.cc390
-rw-r--r--storage/perfschema/pfs_buffer_container.cc883
-rw-r--r--storage/perfschema/pfs_buffer_container.h1625
-rw-r--r--storage/perfschema/pfs_builtin_memory.cc382
-rw-r--r--storage/perfschema/pfs_builtin_memory.h143
-rw-r--r--storage/perfschema/pfs_column_types.h225
-rw-r--r--storage/perfschema/pfs_column_values.cc16
-rw-r--r--storage/perfschema/pfs_column_values.h11
-rw-r--r--storage/perfschema/pfs_con_slice.cc78
-rw-r--r--storage/perfschema/pfs_con_slice.h197
-rw-r--r--storage/perfschema/pfs_defaults.cc89
-rw-r--r--storage/perfschema/pfs_digest.cc59
-rw-r--r--storage/perfschema/pfs_digest.h3
-rw-r--r--storage/perfschema/pfs_engine_table.cc985
-rw-r--r--storage/perfschema/pfs_engine_table.h153
-rw-r--r--storage/perfschema/pfs_events.h14
-rw-r--r--storage/perfschema/pfs_events_stages.cc137
-rw-r--r--storage/perfschema/pfs_events_stages.h6
-rw-r--r--storage/perfschema/pfs_events_statements.cc206
-rw-r--r--storage/perfschema/pfs_events_statements.h24
-rw-r--r--storage/perfschema/pfs_events_transactions.cc267
-rw-r--r--storage/perfschema/pfs_events_transactions.h132
-rw-r--r--storage/perfschema/pfs_events_waits.cc220
-rw-r--r--storage/perfschema/pfs_events_waits.h41
-rw-r--r--storage/perfschema/pfs_global.cc118
-rw-r--r--storage/perfschema/pfs_global.h62
-rw-r--r--storage/perfschema/pfs_host.cc274
-rw-r--r--storage/perfschema/pfs_host.h22
-rw-r--r--storage/perfschema/pfs_instr.cc2219
-rw-r--r--storage/perfschema/pfs_instr.h313
-rw-r--r--storage/perfschema/pfs_instr_class.cc983
-rw-r--r--storage/perfschema/pfs_instr_class.h164
-rw-r--r--storage/perfschema/pfs_lock.h130
-rw-r--r--storage/perfschema/pfs_memory.cc98
-rw-r--r--storage/perfschema/pfs_memory.h38
-rw-r--r--storage/perfschema/pfs_prepared_stmt.cc149
-rw-r--r--storage/perfschema/pfs_prepared_stmt.h96
-rw-r--r--storage/perfschema/pfs_program.cc322
-rw-r--r--storage/perfschema/pfs_program.h103
-rw-r--r--storage/perfschema/pfs_server.cc295
-rw-r--r--storage/perfschema/pfs_server.h88
-rw-r--r--storage/perfschema/pfs_setup_actor.cc162
-rw-r--r--storage/perfschema/pfs_setup_actor.h28
-rw-r--r--storage/perfschema/pfs_setup_object.cc130
-rw-r--r--storage/perfschema/pfs_setup_object.h15
-rw-r--r--storage/perfschema/pfs_stat.h781
-rw-r--r--storage/perfschema/pfs_status.cc166
-rw-r--r--storage/perfschema/pfs_status.h51
-rw-r--r--storage/perfschema/pfs_timer.cc6
-rw-r--r--storage/perfschema/pfs_timer.h7
-rw-r--r--storage/perfschema/pfs_user.cc244
-rw-r--r--storage/perfschema/pfs_user.h22
-rw-r--r--storage/perfschema/pfs_variable.cc1348
-rw-r--r--storage/perfschema/pfs_variable.h718
-rw-r--r--storage/perfschema/pfs_visitor.cc923
-rw-r--r--storage/perfschema/pfs_visitor.h116
-rw-r--r--storage/perfschema/table_accounts.cc30
-rw-r--r--storage/perfschema/table_accounts.h2
-rw-r--r--storage/perfschema/table_all_instr.cc70
-rw-r--r--storage/perfschema/table_all_instr.h4
-rw-r--r--storage/perfschema/table_esgs_by_account_by_event_name.cc51
-rw-r--r--storage/perfschema/table_esgs_by_account_by_event_name.h8
-rw-r--r--storage/perfschema/table_esgs_by_host_by_event_name.cc50
-rw-r--r--storage/perfschema/table_esgs_by_host_by_event_name.h6
-rw-r--r--storage/perfschema/table_esgs_by_thread_by_event_name.cc49
-rw-r--r--storage/perfschema/table_esgs_by_thread_by_event_name.h6
-rw-r--r--storage/perfschema/table_esgs_by_user_by_event_name.cc53
-rw-r--r--storage/perfschema/table_esgs_by_user_by_event_name.h6
-rw-r--r--storage/perfschema/table_esgs_global_by_event_name.cc24
-rw-r--r--storage/perfschema/table_esgs_global_by_event_name.h3
-rw-r--r--storage/perfschema/table_esms_by_account_by_event_name.cc51
-rw-r--r--storage/perfschema/table_esms_by_account_by_event_name.h8
-rw-r--r--storage/perfschema/table_esms_by_digest.cc17
-rw-r--r--storage/perfschema/table_esms_by_digest.h3
-rw-r--r--storage/perfschema/table_esms_by_host_by_event_name.cc50
-rw-r--r--storage/perfschema/table_esms_by_host_by_event_name.h6
-rw-r--r--storage/perfschema/table_esms_by_program.cc245
-rw-r--r--storage/perfschema/table_esms_by_program.h113
-rw-r--r--storage/perfschema/table_esms_by_thread_by_event_name.cc49
-rw-r--r--storage/perfschema/table_esms_by_thread_by_event_name.h6
-rw-r--r--storage/perfschema/table_esms_by_user_by_event_name.cc53
-rw-r--r--storage/perfschema/table_esms_by_user_by_event_name.h6
-rw-r--r--storage/perfschema/table_esms_global_by_event_name.cc24
-rw-r--r--storage/perfschema/table_esms_global_by_event_name.h3
-rw-r--r--storage/perfschema/table_ets_by_account_by_event_name.cc225
-rw-r--r--storage/perfschema/table_ets_by_account_by_event_name.h134
-rw-r--r--storage/perfschema/table_ets_by_host_by_event_name.cc226
-rw-r--r--storage/perfschema/table_ets_by_host_by_event_name.h134
-rw-r--r--storage/perfschema/table_ets_by_thread_by_event_name.cc218
-rw-r--r--storage/perfschema/table_ets_by_thread_by_event_name.h138
-rw-r--r--storage/perfschema/table_ets_by_user_by_event_name.cc225
-rw-r--r--storage/perfschema/table_ets_by_user_by_event_name.h134
-rw-r--r--storage/perfschema/table_ets_global_by_event_name.cc200
-rw-r--r--storage/perfschema/table_ets_global_by_event_name.h105
-rw-r--r--storage/perfschema/table_events_stages.cc212
-rw-r--r--storage/perfschema/table_events_stages.h10
-rw-r--r--storage/perfschema/table_events_statements.cc299
-rw-r--r--storage/perfschema/table_events_statements.h19
-rw-r--r--storage/perfschema/table_events_transactions.cc718
-rw-r--r--storage/perfschema/table_events_transactions.h254
-rw-r--r--storage/perfschema/table_events_waits.cc543
-rw-r--r--storage/perfschema/table_events_waits.h19
-rw-r--r--storage/perfschema/table_events_waits_summary.cc17
-rw-r--r--storage/perfschema/table_events_waits_summary.h2
-rw-r--r--storage/perfschema/table_ews_by_account_by_event_name.cc45
-rw-r--r--storage/perfschema/table_ews_by_account_by_event_name.h8
-rw-r--r--storage/perfschema/table_ews_by_host_by_event_name.cc44
-rw-r--r--storage/perfschema/table_ews_by_host_by_event_name.h6
-rw-r--r--storage/perfschema/table_ews_by_thread_by_event_name.cc114
-rw-r--r--storage/perfschema/table_ews_by_thread_by_event_name.h6
-rw-r--r--storage/perfschema/table_ews_by_user_by_event_name.cc47
-rw-r--r--storage/perfschema/table_ews_by_user_by_event_name.h6
-rw-r--r--storage/perfschema/table_ews_global_by_event_name.cc62
-rw-r--r--storage/perfschema/table_ews_global_by_event_name.h4
-rw-r--r--storage/perfschema/table_file_instances.cc52
-rw-r--r--storage/perfschema/table_file_instances.h3
-rw-r--r--storage/perfschema/table_file_summary_by_event_name.cc25
-rw-r--r--storage/perfschema/table_file_summary_by_event_name.h3
-rw-r--r--storage/perfschema/table_file_summary_by_instance.cc54
-rw-r--r--storage/perfschema/table_file_summary_by_instance.h3
-rw-r--r--storage/perfschema/table_global_status.cc190
-rw-r--r--storage/perfschema/table_global_status.h118
-rw-r--r--storage/perfschema/table_global_variables.cc184
-rw-r--r--storage/perfschema/table_global_variables.h117
-rw-r--r--storage/perfschema/table_helper.cc502
-rw-r--r--storage/perfschema/table_helper.h244
-rw-r--r--storage/perfschema/table_host_cache.cc24
-rw-r--r--storage/perfschema/table_host_cache.h3
-rw-r--r--storage/perfschema/table_hosts.cc32
-rw-r--r--storage/perfschema/table_hosts.h2
-rw-r--r--storage/perfschema/table_md_locks.cc207
-rw-r--r--storage/perfschema/table_md_locks.h106
-rw-r--r--storage/perfschema/table_mems_by_account_by_event_name.cc221
-rw-r--r--storage/perfschema/table_mems_by_account_by_event_name.h129
-rw-r--r--storage/perfschema/table_mems_by_host_by_event_name.cc221
-rw-r--r--storage/perfschema/table_mems_by_host_by_event_name.h129
-rw-r--r--storage/perfschema/table_mems_by_thread_by_event_name.cc214
-rw-r--r--storage/perfschema/table_mems_by_thread_by_event_name.h129
-rw-r--r--storage/perfschema/table_mems_by_user_by_event_name.cc221
-rw-r--r--storage/perfschema/table_mems_by_user_by_event_name.h129
-rw-r--r--storage/perfschema/table_mems_global_by_event_name.cc241
-rw-r--r--storage/perfschema/table_mems_global_by_event_name.h132
-rw-r--r--storage/perfschema/table_os_global_by_type.cc136
-rw-r--r--storage/perfschema/table_os_global_by_type.h20
-rw-r--r--storage/perfschema/table_performance_timers.cc19
-rw-r--r--storage/perfschema/table_performance_timers.h3
-rw-r--r--storage/perfschema/table_prepared_stmt_instances.cc294
-rw-r--r--storage/perfschema/table_prepared_stmt_instances.h132
-rw-r--r--storage/perfschema/table_replication_applier_configuration.cc192
-rw-r--r--storage/perfschema/table_replication_applier_configuration.h107
-rw-r--r--storage/perfschema/table_replication_applier_status.cc219
-rw-r--r--storage/perfschema/table_replication_applier_status.h118
-rw-r--r--storage/perfschema/table_replication_applier_status_by_coordinator.cc246
-rw-r--r--storage/perfschema/table_replication_applier_status_by_coordinator.h124
-rw-r--r--storage/perfschema/table_replication_applier_status_by_worker.cc412
-rw-r--r--storage/perfschema/table_replication_applier_status_by_worker.h182
-rw-r--r--storage/perfschema/table_replication_connection_configuration.cc331
-rw-r--r--storage/perfschema/table_replication_connection_configuration.h152
-rw-r--r--storage/perfschema/table_replication_connection_status.cc440
-rw-r--r--storage/perfschema/table_replication_connection_status.h150
-rw-r--r--storage/perfschema/table_replication_group_member_stats.cc372
-rw-r--r--storage/perfschema/table_replication_group_member_stats.h116
-rw-r--r--storage/perfschema/table_replication_group_members.cc281
-rw-r--r--storage/perfschema/table_replication_group_members.h108
-rw-r--r--storage/perfschema/table_session_account_connect_attrs.cc12
-rw-r--r--storage/perfschema/table_session_account_connect_attrs.h2
-rw-r--r--storage/perfschema/table_session_connect.cc9
-rw-r--r--storage/perfschema/table_session_connect.h3
-rw-r--r--storage/perfschema/table_session_connect_attrs.cc10
-rw-r--r--storage/perfschema/table_session_connect_attrs.h2
-rw-r--r--storage/perfschema/table_session_status.cc185
-rw-r--r--storage/perfschema/table_session_status.h119
-rw-r--r--storage/perfschema/table_session_variables.cc187
-rw-r--r--storage/perfschema/table_session_variables.h117
-rw-r--r--storage/perfschema/table_setup_actors.cc91
-rw-r--r--storage/perfschema/table_setup_actors.h6
-rw-r--r--storage/perfschema/table_setup_consumers.cc69
-rw-r--r--storage/perfschema/table_setup_consumers.h9
-rw-r--r--storage/perfschema/table_setup_instruments.cc106
-rw-r--r--storage/perfschema/table_setup_instruments.h19
-rw-r--r--storage/perfschema/table_setup_objects.cc44
-rw-r--r--storage/perfschema/table_setup_objects.h2
-rw-r--r--storage/perfschema/table_setup_timers.cc33
-rw-r--r--storage/perfschema/table_setup_timers.h3
-rw-r--r--storage/perfschema/table_socket_instances.cc52
-rw-r--r--storage/perfschema/table_socket_instances.h3
-rw-r--r--storage/perfschema/table_socket_summary_by_event_name.cc21
-rw-r--r--storage/perfschema/table_socket_summary_by_event_name.h3
-rw-r--r--storage/perfschema/table_socket_summary_by_instance.cc52
-rw-r--r--storage/perfschema/table_socket_summary_by_instance.h3
-rw-r--r--storage/perfschema/table_status_by_account.cc246
-rw-r--r--storage/perfschema/table_status_by_account.h156
-rw-r--r--storage/perfschema/table_status_by_host.cc245
-rw-r--r--storage/perfschema/table_status_by_host.h154
-rw-r--r--storage/perfschema/table_status_by_thread.cc239
-rw-r--r--storage/perfschema/table_status_by_thread.h151
-rw-r--r--storage/perfschema/table_status_by_user.cc246
-rw-r--r--storage/perfschema/table_status_by_user.h153
-rw-r--r--storage/perfschema/table_sync_instances.cc117
-rw-r--r--storage/perfschema/table_sync_instances.h5
-rw-r--r--storage/perfschema/table_table_handles.cc214
-rw-r--r--storage/perfschema/table_table_handles.h108
-rw-r--r--storage/perfschema/table_threads.cc110
-rw-r--r--storage/perfschema/table_threads.h14
-rw-r--r--storage/perfschema/table_tiws_by_index_usage.cc108
-rw-r--r--storage/perfschema/table_tiws_by_index_usage.h10
-rw-r--r--storage/perfschema/table_tiws_by_table.cc56
-rw-r--r--storage/perfschema/table_tiws_by_table.h3
-rw-r--r--storage/perfschema/table_tlws_by_table.cc107
-rw-r--r--storage/perfschema/table_tlws_by_table.h3
-rw-r--r--storage/perfschema/table_users.cc34
-rw-r--r--storage/perfschema/table_users.h2
-rw-r--r--storage/perfschema/table_uvar_by_thread.cc329
-rw-r--r--storage/perfschema/table_uvar_by_thread.h193
-rw-r--r--storage/perfschema/table_variables_by_thread.cc229
-rw-r--r--storage/perfschema/table_variables_by_thread.h151
-rw-r--r--storage/perfschema/unittest/CMakeLists.txt3
-rw-r--r--storage/perfschema/unittest/pfs-t.cc383
-rw-r--r--storage/perfschema/unittest/pfs_account-oom-t.cc180
-rw-r--r--storage/perfschema/unittest/pfs_connect_attr-t.cc4
-rw-r--r--storage/perfschema/unittest/pfs_host-oom-t.cc80
-rw-r--r--storage/perfschema/unittest/pfs_instr-oom-t.cc858
-rw-r--r--storage/perfschema/unittest/pfs_instr-t.cc173
-rw-r--r--storage/perfschema/unittest/pfs_instr_class-oom-t.cc46
-rw-r--r--storage/perfschema/unittest/pfs_instr_class-t.cc73
-rw-r--r--storage/perfschema/unittest/pfs_misc-t.cc26
-rw-r--r--storage/perfschema/unittest/pfs_noop-t.cc242
-rw-r--r--storage/perfschema/unittest/pfs_server_stubs.cc14
-rw-r--r--storage/perfschema/unittest/pfs_timer-t.cc1
-rw-r--r--storage/perfschema/unittest/pfs_user-oom-t.cc77
-rw-r--r--storage/perfschema/unittest/stub_global_status_var.h31
-rw-r--r--storage/perfschema/unittest/stub_pfs_global.h19
-rw-r--r--storage/perfschema/unittest/stub_print_error.h16
253 files changed, 33775 insertions, 6780 deletions
diff --git a/storage/perfschema/CMakeLists.txt b/storage/perfschema/CMakeLists.txt
index e1839bc5b00..667d2d99b5d 100644
--- a/storage/perfschema/CMakeLists.txt
+++ b/storage/perfschema/CMakeLists.txt
@@ -28,6 +28,9 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}
${SSL_INCLUDE_DIRS})
ADD_DEFINITIONS(-DMYSQL_SERVER)
+IF (SSL_DEFINES)
+ ADD_DEFINITIONS(${SSL_DEFINES})
+ENDIF()
#
# Maintainer: keep this list sorted, to avoid merge collisions.
@@ -42,27 +45,35 @@ cursor_by_user.h
pfs.h
pfs_account.h
pfs_atomic.h
+pfs_buffer_container.h
+pfs_builtin_memory.h
pfs_column_types.h
pfs_column_values.h
pfs_con_slice.h
pfs_defaults.h
pfs_digest.h
+pfs_program.h
+pfs_prepared_stmt.h
pfs_engine_table.h
pfs_events.h
pfs_events_stages.h
pfs_events_statements.h
+pfs_events_transactions.h
pfs_events_waits.h
pfs_global.h
pfs_host.h
pfs_instr.h
pfs_instr_class.h
pfs_lock.h
+pfs_memory.h
pfs_server.h
pfs_setup_actor.h
pfs_setup_object.h
pfs_stat.h
+pfs_status.h
pfs_timer.h
pfs_user.h
+pfs_variable.h
pfs_visitor.h
table_accounts.h
table_all_instr.h
@@ -74,11 +85,19 @@ table_esgs_global_by_event_name.h
table_esms_by_account_by_event_name.h
table_esms_by_host_by_event_name.h
table_esms_by_digest.h
+table_esms_by_program.h
+table_prepared_stmt_instances.h
table_esms_by_thread_by_event_name.h
table_esms_by_user_by_event_name.h
table_esms_global_by_event_name.h
+table_ets_by_account_by_event_name.h
+table_ets_by_host_by_event_name.h
+table_ets_by_thread_by_event_name.h
+table_ets_by_user_by_event_name.h
+table_ets_global_by_event_name.h
table_events_stages.h
table_events_statements.h
+table_events_transactions.h
table_events_waits.h
table_events_waits_summary.h
table_ews_by_account_by_event_name.h
@@ -87,6 +106,12 @@ table_ews_by_thread_by_event_name.h
table_ews_by_user_by_event_name.h
table_ews_global_by_event_name.h
table_file_instances.h
+table_md_locks.h
+table_mems_global_by_event_name.h
+table_mems_by_account_by_event_name.h
+table_mems_by_host_by_event_name.h
+table_mems_by_thread_by_event_name.h
+table_mems_by_user_by_event_name.h
table_file_summary_by_instance.h
table_file_summary_by_event_name.h
table_socket_instances.h
@@ -103,15 +128,34 @@ table_setup_instruments.h
table_setup_objects.h
table_setup_timers.h
table_sync_instances.h
+table_status_by_account.h
+table_status_by_host.h
+table_status_by_thread.h
+table_status_by_user.h
+table_global_status.h
+table_session_status.h
+table_variables_by_thread.h
+table_global_variables.h
+table_session_variables.h
+table_table_handles.h
table_threads.h
table_tiws_by_index_usage.h
table_tiws_by_table.h
table_tlws_by_table.h
table_users.h
+table_uvar_by_thread.h
cursor_by_thread_connect_attr.h
table_session_connect.h
table_session_connect_attrs.h
table_session_account_connect_attrs.h
+table_replication_connection_configuration.h
+table_replication_group_members.h
+table_replication_connection_status.h
+table_replication_applier_configuration.h
+table_replication_applier_status.h
+table_replication_applier_status_by_coordinator.h
+table_replication_applier_status_by_worker.h
+table_replication_group_member_stats.h
cursor_by_account.cc
cursor_by_host.cc
cursor_by_thread.cc
@@ -120,23 +164,31 @@ ha_perfschema.cc
pfs.cc
pfs_account.cc
pfs_autosize.cc
+pfs_buffer_container.cc
+pfs_builtin_memory.cc
pfs_column_values.cc
pfs_con_slice.cc
pfs_defaults.cc
pfs_digest.cc
+pfs_program.cc
+pfs_prepared_stmt.cc
pfs_engine_table.cc
pfs_events_stages.cc
pfs_events_statements.cc
+pfs_events_transactions.cc
pfs_events_waits.cc
pfs_global.cc
pfs_host.cc
pfs_instr.cc
pfs_instr_class.cc
+pfs_memory.cc
pfs_server.cc
pfs_setup_actor.cc
pfs_setup_object.cc
+pfs_status.cc
pfs_timer.cc
pfs_user.cc
+pfs_variable.cc
pfs_visitor.cc
table_accounts.cc
table_all_instr.cc
@@ -148,11 +200,19 @@ table_esgs_global_by_event_name.cc
table_esms_by_account_by_event_name.cc
table_esms_by_host_by_event_name.cc
table_esms_by_digest.cc
+table_esms_by_program.cc
+table_prepared_stmt_instances.cc
table_esms_by_thread_by_event_name.cc
table_esms_by_user_by_event_name.cc
table_esms_global_by_event_name.cc
+table_ets_by_account_by_event_name.cc
+table_ets_by_host_by_event_name.cc
+table_ets_by_thread_by_event_name.cc
+table_ets_by_user_by_event_name.cc
+table_ets_global_by_event_name.cc
table_events_stages.cc
table_events_statements.cc
+table_events_transactions.cc
table_events_waits.cc
table_events_waits_summary.cc
table_ews_by_account_by_event_name.cc
@@ -161,6 +221,12 @@ table_ews_by_thread_by_event_name.cc
table_ews_by_user_by_event_name.cc
table_ews_global_by_event_name.cc
table_file_instances.cc
+table_md_locks.cc
+table_mems_global_by_event_name.cc
+table_mems_by_account_by_event_name.cc
+table_mems_by_host_by_event_name.cc
+table_mems_by_thread_by_event_name.cc
+table_mems_by_user_by_event_name.cc
table_file_summary_by_instance.cc
table_file_summary_by_event_name.cc
table_socket_instances.cc
@@ -177,15 +243,34 @@ table_setup_instruments.cc
table_setup_objects.cc
table_setup_timers.cc
table_sync_instances.cc
+table_status_by_account.cc
+table_status_by_host.cc
+table_status_by_thread.cc
+table_status_by_user.cc
+table_global_status.cc
+table_session_status.cc
+table_variables_by_thread.cc
+table_global_variables.cc
+table_session_variables.cc
+table_table_handles.cc
table_threads.cc
table_tiws_by_index_usage.cc
table_tiws_by_table.cc
table_tlws_by_table.cc
table_users.cc
+table_uvar_by_thread.cc
cursor_by_thread_connect_attr.cc
table_session_connect.cc
table_session_connect_attrs.cc
table_session_account_connect_attrs.cc
+table_replication_connection_configuration.cc
+#table_replication_group_members.cc
+#table_replication_connection_status.cc
+table_replication_applier_configuration.cc
+table_replication_applier_status.cc
+table_replication_applier_status_by_coordinator.cc
+#table_replication_applier_status_by_worker.cc
+#table_replication_group_member_stats.cc
)
MYSQL_ADD_PLUGIN(perfschema ${PERFSCHEMA_SOURCES} STORAGE_ENGINE DEFAULT STATIC_ONLY)
@@ -195,3 +280,41 @@ IF (TARGET perfschema)
ADD_SUBDIRECTORY(unittest)
ENDIF(WITH_UNIT_TESTS)
ENDIF(TARGET perfschema)
+
+# Only disable threads when building without *any* instrumentation,
+# as other instrumentations have a dependency on threads.
+OPTION(DISABLE_PSI_THREAD "Exclude the performance schema thread instrumentation" OFF)
+
+OPTION(DISABLE_PSI_MUTEX "Exclude the performance schema mutex instrumentation" OFF)
+OPTION(DISABLE_PSI_RWLOCK "Exclude the performance schema rwlock instrumentation" OFF)
+OPTION(DISABLE_PSI_COND "Exclude the performance schema condition instrumentation" OFF)
+OPTION(DISABLE_PSI_FILE "Exclude the performance schema file instrumentation" OFF)
+OPTION(DISABLE_PSI_TABLE "Exclude the performance schema table instrumentation" OFF)
+OPTION(DISABLE_PSI_SOCKET "Exclude the performance schema socket instrumentation" OFF)
+OPTION(DISABLE_PSI_STAGE "Exclude the performance schema stage instrumentation" OFF)
+OPTION(DISABLE_PSI_STATEMENT "Exclude the performance schema statement instrumentation" OFF)
+OPTION(DISABLE_PSI_SP "Exclude the performance schema stored procedure instrumentation" OFF)
+OPTION(DISABLE_PSI_PS "Exclude the performance schema prepared statements instances instrumentation" OFF)
+OPTION(DISABLE_PSI_IDLE "Exclude the performance schema idle instrumentation" OFF)
+OPTION(DISABLE_PSI_STATEMENT_DIGEST "Exclude the performance schema statement digest instrumentation" OFF)
+OPTION(DISABLE_PSI_METADATA "Exclude the performance schema metadata instrumentation" OFF)
+OPTION(DISABLE_PSI_MEMORY "Exclude the performance schema memory instrumentation" OFF)
+OPTION(DISABLE_PSI_TRANSACTION "Exclude the performance schema transaction instrumentation" OFF)
+
+MARK_AS_ADVANCED(DISABLE_PSI_THREAD)
+
+MARK_AS_ADVANCED(DISABLE_PSI_MUTEX)
+MARK_AS_ADVANCED(DISABLE_PSI_RWLOCK)
+MARK_AS_ADVANCED(DISABLE_PSI_COND)
+MARK_AS_ADVANCED(DISABLE_PSI_FILE)
+MARK_AS_ADVANCED(DISABLE_PSI_TABLE)
+MARK_AS_ADVANCED(DISABLE_PSI_SOCKET)
+MARK_AS_ADVANCED(DISABLE_PSI_STAGE)
+MARK_AS_ADVANCED(DISABLE_PSI_STATEMENT)
+MARK_AS_ADVANCED(DISABLE_PSI_SP)
+MARK_AS_ADVANCED(DISABLE_PSI_PS)
+MARK_AS_ADVANCED(DISABLE_PSI_IDLE)
+MARK_AS_ADVANCED(DISABLE_PSI_STATEMENT_DIGEST)
+MARK_AS_ADVANCED(DISABLE_PSI_METADATA)
+MARK_AS_ADVANCED(DISABLE_PSI_MEMORY)
+MARK_AS_ADVANCED(DISABLE_PSI_TRANSACTION)
diff --git a/storage/perfschema/cursor_by_account.cc b/storage/perfschema/cursor_by_account.cc
index f26318c42fc..1b208e00d65 100644
--- a/storage/perfschema/cursor_by_account.cc
+++ b/storage/perfschema/cursor_by_account.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, 2015, 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, version 2.0,
@@ -27,7 +27,13 @@
#include "my_global.h"
#include "cursor_by_account.h"
-#include "pfs_user.h"
+#include "pfs_buffer_container.h"
+
+ha_rows
+cursor_by_account::get_row_count(void)
+{
+ return global_account_container.get_row_count();
+}
cursor_by_account::cursor_by_account(const PFS_engine_table_share *share)
: PFS_engine_table(share, &m_pos),
@@ -44,17 +50,14 @@ int cursor_by_account::rnd_next(void)
{
PFS_account *pfs;
- for (m_pos.set_at(&m_next_pos);
- m_pos.m_index < account_max;
- m_pos.next())
+ m_pos.set_at(&m_next_pos);
+ PFS_account_iterator it= global_account_container.iterate(m_pos.m_index);
+ pfs= it.scan_next(& m_pos.m_index);
+ if (pfs != NULL)
{
- pfs= &account_array[m_pos.m_index];
- if (pfs->m_lock.is_populated())
- {
- make_row(pfs);
- m_next_pos.set_after(&m_pos);
- return 0;
- }
+ make_row(pfs);
+ m_next_pos.set_after(&m_pos);
+ return 0;
}
return HA_ERR_END_OF_FILE;
@@ -66,9 +69,9 @@ cursor_by_account::rnd_pos(const void *pos)
PFS_account *pfs;
set_position(pos);
- DBUG_ASSERT(m_pos.m_index < account_max);
- pfs= &account_array[m_pos.m_index];
- if (pfs->m_lock.is_populated())
+
+ pfs= global_account_container.get(m_pos.m_index);
+ if (pfs != NULL)
{
make_row(pfs);
return 0;
diff --git a/storage/perfschema/cursor_by_account.h b/storage/perfschema/cursor_by_account.h
index c14a563b712..d689cf6c524 100644
--- a/storage/perfschema/cursor_by_account.h
+++ b/storage/perfschema/cursor_by_account.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, 2015, 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, version 2.0,
@@ -41,6 +41,8 @@
class cursor_by_account : public PFS_engine_table
{
public:
+ static ha_rows get_row_count();
+
virtual int rnd_next();
virtual int rnd_pos(const void *pos);
virtual void reset_position(void);
diff --git a/storage/perfschema/cursor_by_host.cc b/storage/perfschema/cursor_by_host.cc
index c3397234e2e..6aa3423c0d1 100644
--- a/storage/perfschema/cursor_by_host.cc
+++ b/storage/perfschema/cursor_by_host.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, 2015, 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, version 2.0,
@@ -27,7 +27,13 @@
#include "my_global.h"
#include "cursor_by_host.h"
-#include "pfs_host.h"
+#include "pfs_buffer_container.h"
+
+ha_rows
+cursor_by_host::get_row_count(void)
+{
+ return global_host_container.get_row_count();
+}
cursor_by_host::cursor_by_host(const PFS_engine_table_share *share)
: PFS_engine_table(share, &m_pos),
@@ -42,19 +48,16 @@ void cursor_by_host::reset_position(void)
int cursor_by_host::rnd_next(void)
{
- PFS_host *host;
+ PFS_host *pfs;
- for (m_pos.set_at(&m_next_pos);
- m_pos.m_index < host_max;
- m_pos.next())
+ m_pos.set_at(&m_next_pos);
+ PFS_host_iterator it= global_host_container.iterate(m_pos.m_index);
+ pfs= it.scan_next(& m_pos.m_index);
+ if (pfs != NULL)
{
- host= & host_array[m_pos.m_index];
- if (host->m_lock.is_populated())
- {
- make_row(host);
- m_next_pos.set_after(&m_pos);
- return 0;
- }
+ make_row(pfs);
+ m_next_pos.set_after(&m_pos);
+ return 0;
}
return HA_ERR_END_OF_FILE;
@@ -66,9 +69,9 @@ cursor_by_host::rnd_pos(const void *pos)
PFS_host *pfs;
set_position(pos);
- DBUG_ASSERT(m_pos.m_index < host_max);
- pfs= &host_array[m_pos.m_index];
- if (pfs->m_lock.is_populated())
+
+ pfs= global_host_container.get(m_pos.m_index);
+ if (pfs != NULL)
{
make_row(pfs);
return 0;
diff --git a/storage/perfschema/cursor_by_host.h b/storage/perfschema/cursor_by_host.h
index ac68acf3945..8f256156b1f 100644
--- a/storage/perfschema/cursor_by_host.h
+++ b/storage/perfschema/cursor_by_host.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, 2015, 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, version 2.0,
@@ -41,6 +41,8 @@
class cursor_by_host : public PFS_engine_table
{
public:
+ static ha_rows get_row_count();
+
virtual int rnd_next();
virtual int rnd_pos(const void *pos);
virtual void reset_position(void);
diff --git a/storage/perfschema/cursor_by_thread.cc b/storage/perfschema/cursor_by_thread.cc
index afdc9010b1f..5d56794bf94 100644
--- a/storage/perfschema/cursor_by_thread.cc
+++ b/storage/perfschema/cursor_by_thread.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, 2015, 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, version 2.0,
@@ -28,6 +28,13 @@
#include "my_global.h"
#include "cursor_by_thread.h"
#include "pfs_instr.h"
+#include "pfs_buffer_container.h"
+
+ha_rows
+cursor_by_thread::get_row_count(void)
+{
+ return global_thread_container.get_row_count();
+}
cursor_by_thread::cursor_by_thread(const PFS_engine_table_share *share)
: PFS_engine_table(share, &m_pos),
@@ -44,17 +51,14 @@ int cursor_by_thread::rnd_next(void)
{
PFS_thread *pfs;
- for (m_pos.set_at(&m_next_pos);
- m_pos.m_index < thread_max;
- m_pos.next())
+ m_pos.set_at(&m_next_pos);
+ PFS_thread_iterator it= global_thread_container.iterate(m_pos.m_index);
+ pfs= it.scan_next(& m_pos.m_index);
+ if (pfs != NULL)
{
- pfs= &thread_array[m_pos.m_index];
- if (pfs->m_lock.is_populated())
- {
- make_row(pfs);
- m_next_pos.set_after(&m_pos);
- return 0;
- }
+ make_row(pfs);
+ m_next_pos.set_after(&m_pos);
+ return 0;
}
return HA_ERR_END_OF_FILE;
@@ -66,9 +70,9 @@ cursor_by_thread::rnd_pos(const void *pos)
PFS_thread *pfs;
set_position(pos);
- DBUG_ASSERT(m_pos.m_index < thread_max);
- pfs= &thread_array[m_pos.m_index];
- if (pfs->m_lock.is_populated())
+
+ pfs= global_thread_container.get(m_pos.m_index);
+ if (pfs != NULL)
{
make_row(pfs);
return 0;
diff --git a/storage/perfschema/cursor_by_thread.h b/storage/perfschema/cursor_by_thread.h
index db130088920..1fd803d906c 100644
--- a/storage/perfschema/cursor_by_thread.h
+++ b/storage/perfschema/cursor_by_thread.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, 2015, 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, version 2.0,
@@ -41,6 +41,8 @@
class cursor_by_thread : public PFS_engine_table
{
public:
+ static ha_rows get_row_count();
+
virtual int rnd_next();
virtual int rnd_pos(const void *pos);
virtual void reset_position(void);
diff --git a/storage/perfschema/cursor_by_thread_connect_attr.cc b/storage/perfschema/cursor_by_thread_connect_attr.cc
index 90a200b809a..b4462a8d748 100644
--- a/storage/perfschema/cursor_by_thread_connect_attr.cc
+++ b/storage/perfschema/cursor_by_thread_connect_attr.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -22,6 +22,20 @@
#include "my_global.h"
#include "cursor_by_thread_connect_attr.h"
+#include "pfs_buffer_container.h"
+
+ha_rows
+cursor_by_thread_connect_attr::get_row_count(void)
+{
+ /*
+ The real number of attributes per thread does not matter,
+ we only need to hint the optimizer there are many per thread,
+ so abusing session_connect_attrs_size_per_thread
+ (which is a number of bytes, not attributes)
+ */
+ return global_thread_container.get_row_count() *
+ session_connect_attrs_size_per_thread;
+}
cursor_by_thread_connect_attr::cursor_by_thread_connect_attr(
const PFS_engine_table_share *share) :
@@ -31,14 +45,14 @@ cursor_by_thread_connect_attr::cursor_by_thread_connect_attr(
int cursor_by_thread_connect_attr::rnd_next(void)
{
PFS_thread *thread;
+ bool has_more_thread= true;
for (m_pos.set_at(&m_next_pos);
- m_pos.has_more_thread();
+ has_more_thread;
m_pos.next_thread())
{
- thread= &thread_array[m_pos.m_index_1];
-
- if (thread->m_lock.is_populated())
+ thread= global_thread_container.get(m_pos.m_index_1, & has_more_thread);
+ if (thread != NULL)
{
make_row(thread, m_pos.m_index_2);
if (m_row_exists)
@@ -48,6 +62,7 @@ int cursor_by_thread_connect_attr::rnd_next(void)
}
}
}
+
return HA_ERR_END_OF_FILE;
}
@@ -57,15 +72,14 @@ 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;
+ thread= global_thread_container.get(m_pos.m_index_1);
+ if (thread != NULL)
+ {
+ make_row(thread, m_pos.m_index_2);
+ if (m_row_exists)
+ return 0;
+ }
return HA_ERR_RECORD_DELETED;
}
diff --git a/storage/perfschema/cursor_by_thread_connect_attr.h b/storage/perfschema/cursor_by_thread_connect_attr.h
index 69d1b5ec0c0..7aa31115b30 100644
--- a/storage/perfschema/cursor_by_thread_connect_attr.h
+++ b/storage/perfschema/cursor_by_thread_connect_attr.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2012, 2015, 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, version 2.0,
@@ -32,6 +32,10 @@
@{
*/
+/**
+ Position of a cursor on abstract table
+ PERFORMANCE_SCHEMA.SESSION_CONNECT_ATTRS.
+*/
struct pos_connect_attr_by_thread_by_attr
: public PFS_double_index
{
@@ -39,11 +43,6 @@ struct 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++;
@@ -61,6 +60,8 @@ struct pos_connect_attr_by_thread_by_attr
class cursor_by_thread_connect_attr : public PFS_engine_table
{
public:
+ static ha_rows get_row_count();
+
virtual int rnd_next();
virtual int rnd_pos(const void *pos);
virtual void reset_position(void);
diff --git a/storage/perfschema/cursor_by_user.cc b/storage/perfschema/cursor_by_user.cc
index 273d186b01c..7699bcf1fc8 100644
--- a/storage/perfschema/cursor_by_user.cc
+++ b/storage/perfschema/cursor_by_user.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, 2015, 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, version 2.0,
@@ -27,7 +27,13 @@
#include "my_global.h"
#include "cursor_by_user.h"
-#include "pfs_user.h"
+#include "pfs_buffer_container.h"
+
+ha_rows
+cursor_by_user::get_row_count(void)
+{
+ return global_user_container.get_row_count();
+}
cursor_by_user::cursor_by_user(const PFS_engine_table_share *share)
: PFS_engine_table(share, &m_pos),
@@ -44,17 +50,14 @@ int cursor_by_user::rnd_next(void)
{
PFS_user *pfs;
- for (m_pos.set_at(&m_next_pos);
- m_pos.m_index < user_max;
- m_pos.next())
+ m_pos.set_at(&m_next_pos);
+ PFS_user_iterator it= global_user_container.iterate(m_pos.m_index);
+ pfs= it.scan_next(& m_pos.m_index);
+ if (pfs != NULL)
{
- pfs= &user_array[m_pos.m_index];
- if (pfs->m_lock.is_populated())
- {
- make_row(pfs);
- m_next_pos.set_after(&m_pos);
- return 0;
- }
+ make_row(pfs);
+ m_next_pos.set_after(&m_pos);
+ return 0;
}
return HA_ERR_END_OF_FILE;
@@ -66,9 +69,9 @@ cursor_by_user::rnd_pos(const void *pos)
PFS_user *pfs;
set_position(pos);
- DBUG_ASSERT(m_pos.m_index < user_max);
- pfs= &user_array[m_pos.m_index];
- if (pfs->m_lock.is_populated())
+
+ pfs= global_user_container.get(m_pos.m_index);
+ if (pfs != NULL)
{
make_row(pfs);
return 0;
diff --git a/storage/perfschema/cursor_by_user.h b/storage/perfschema/cursor_by_user.h
index 06554ebb228..d31f886170c 100644
--- a/storage/perfschema/cursor_by_user.h
+++ b/storage/perfschema/cursor_by_user.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, 2015, 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, version 2.0,
@@ -41,6 +41,8 @@
class cursor_by_user : public PFS_engine_table
{
public:
+ static ha_rows get_row_count();
+
virtual int rnd_next();
virtual int rnd_pos(const void *pos);
virtual void reset_position(void);
diff --git a/storage/perfschema/gen_pfs_lex_token.cc b/storage/perfschema/gen_pfs_lex_token.cc
deleted file mode 100644
index 5a51a8aeb2f..00000000000
--- a/storage/perfschema/gen_pfs_lex_token.cc
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- Copyright (c) 2011, 2014, 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, version 2.0,
- as published by the Free Software Foundation.
-
- This program is also distributed with certain software (including
- but not limited to OpenSSL) that is licensed under separate terms,
- as designated in a particular file or component or in included license
- documentation. The authors of MySQL hereby grant you an additional
- permission to link the program and your derivative works with the
- separately licensed software that they have included with MySQL.
-
- 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, version 2.0, 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, Fifth Floor, Boston, MA 02110-1335 USA */
-
-#include <my_global.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-/* We only need the tokens here */
-#define YYSTYPE_IS_DECLARED
-#include <../sql/sql_yacc.h>
-#include <lex.h>
-
-#include <welcome_copyright_notice.h> /* ORACLE_WELCOME_COPYRIGHT_NOTICE */
-
-/*
- This is a tool used during build only,
- so MY_MAX_TOKEN does not need to be exact,
- only big enough to hold:
- - 256 character terminal tokens
- - YYNTOKENS named terminal tokens
- from bison.
- See also YYMAXUTOK.
-*/
-#define MY_MAX_TOKEN 1000
-/** Generated token. */
-struct gen_lex_token_string
-{
- const char *m_token_string;
- int m_token_length;
- bool m_append_space;
- bool m_start_expr;
-};
-
-gen_lex_token_string compiled_token_array[MY_MAX_TOKEN];
-int max_token_seen= 0;
-
-char char_tokens[256];
-
-int tok_pfs_generic_value= 0;
-int tok_pfs_generic_value_list= 0;
-int tok_pfs_row_single_value= 0;
-int tok_pfs_row_single_value_list= 0;
-int tok_pfs_row_multiple_value= 0;
-int tok_pfs_row_multiple_value_list= 0;
-int tok_pfs_unused= 0;
-
-void set_token(int tok, const char *str)
-{
- if (tok <= 0)
- {
- fprintf(stderr, "Bad token found\n");
- exit(1);
- }
-
- if (tok > max_token_seen)
- {
- max_token_seen= tok;
- }
-
- if (max_token_seen >= MY_MAX_TOKEN)
- {
- fprintf(stderr, "Added that many new keywords ? Increase MY_MAX_TOKEN\n");
- exit(1);
- }
-
- compiled_token_array[tok].m_token_string= str;
- compiled_token_array[tok].m_token_length= strlen(str);
- compiled_token_array[tok].m_append_space= true;
- compiled_token_array[tok].m_start_expr= false;
-}
-
-void set_start_expr_token(int tok)
-{
- compiled_token_array[tok].m_start_expr= true;
-}
-
-void compute_tokens()
-{
- int tok;
- unsigned int i;
- char *str;
-
- /*
- Default value.
- */
- for (tok= 0; tok < MY_MAX_TOKEN; tok++)
- {
- compiled_token_array[tok].m_token_string= "(unknown)";
- compiled_token_array[tok].m_token_length= 9;
- compiled_token_array[tok].m_append_space= true;
- compiled_token_array[tok].m_start_expr= false;
- }
-
- /*
- Tokens made of just one terminal character
- */
- for (tok=0; tok < 256; tok++)
- {
- str= & char_tokens[tok];
- str[0]= (char) tok;
- compiled_token_array[tok].m_token_string= str;
- compiled_token_array[tok].m_token_length= 1;
- compiled_token_array[tok].m_append_space= true;
- }
-
- max_token_seen= 255;
-
- /*
- String terminal tokens, used in sql_yacc.yy
- */
- set_token(NEG, "~");
- set_token(TABLE_REF_PRIORITY, "TABLE_REF_PRIORITY");
-
- /*
- Tokens hard coded in sql_lex.cc
- */
-
- set_token(WITH_CUBE_SYM, "WITH CUBE");
- set_token(WITH_ROLLUP_SYM, "WITH ROLLUP");
- set_token(NOT2_SYM, "!");
- set_token(OR2_SYM, "|");
- set_token(PARAM_MARKER, "?");
- set_token(SET_VAR, ":=");
- set_token(UNDERSCORE_CHARSET, "(_charset)");
- set_token(END_OF_INPUT, "");
-
- /*
- Values.
- These tokens are all normalized later,
- so this strings will never be displayed.
- */
- set_token(BIN_NUM, "(bin)");
- set_token(DECIMAL_NUM, "(decimal)");
- set_token(FLOAT_NUM, "(float)");
- set_token(HEX_NUM, "(hex)");
- set_token(LEX_HOSTNAME, "(hostname)");
- set_token(LONG_NUM, "(long)");
- set_token(NUM, "(num)");
- set_token(TEXT_STRING, "(text)");
- set_token(NCHAR_STRING, "(nchar)");
- set_token(ULONGLONG_NUM, "(ulonglong)");
-
- /*
- Identifiers.
- */
- set_token(IDENT, "(id)");
- set_token(IDENT_QUOTED, "(id_quoted)");
-
- /*
- Unused tokens
- */
- set_token(LOCATOR_SYM, "LOCATOR");
- set_token(SERVER_OPTIONS, "SERVER_OPTIONS");
- set_token(UDF_RETURNS_SYM, "UDF_RETURNS");
-
- /*
- See symbols[] in sql/lex.h
- */
- for (i= 0; i< sizeof(symbols)/sizeof(symbols[0]); i++)
- {
- set_token(symbols[i].tok, symbols[i].name);
- }
-
- /*
- See sql_functions[] in sql/lex.h
- */
- for (i= 0; i< sizeof(sql_functions)/sizeof(sql_functions[0]); i++)
- {
- set_token(sql_functions[i].tok, sql_functions[i].name);
- }
-
- /*
- Additional FAKE tokens,
- used internally to normalize a digest text.
- */
-
- max_token_seen++;
- tok_pfs_generic_value= max_token_seen;
- set_token(tok_pfs_generic_value, "?");
-
- max_token_seen++;
- tok_pfs_generic_value_list= max_token_seen;
- set_token(tok_pfs_generic_value_list, "?, ...");
-
- max_token_seen++;
- tok_pfs_row_single_value= max_token_seen;
- set_token(tok_pfs_row_single_value, "(?)");
-
- max_token_seen++;
- tok_pfs_row_single_value_list= max_token_seen;
- set_token(tok_pfs_row_single_value_list, "(?) /* , ... */");
-
- max_token_seen++;
- tok_pfs_row_multiple_value= max_token_seen;
- set_token(tok_pfs_row_multiple_value, "(...)");
-
- max_token_seen++;
- tok_pfs_row_multiple_value_list= max_token_seen;
- set_token(tok_pfs_row_multiple_value_list, "(...) /* , ... */");
-
- max_token_seen++;
- tok_pfs_unused= max_token_seen;
- set_token(tok_pfs_unused, "UNUSED");
-
- /*
- Fix whitespace for some special tokens.
- */
-
- /*
- The lexer parses "@@variable" as '@', '@', 'variable',
- returning a token for '@' alone.
-
- This is incorrect, '@' is not really a token,
- because the syntax "@ @ variable" (with spaces) is not accepted:
- The lexer keeps some internal state after the '@' fake token.
-
- To work around this, digest text are printed as "@@variable".
- */
- compiled_token_array[(int) '@'].m_append_space= false;
-
- /*
- Define additional properties for tokens.
-
- List all the token that are followed by an expression.
- This is needed to differentiate unary from binary
- '+' and '-' operators, because we want to:
- - reduce <unary +> <NUM> to <?>,
- - preserve <...> <binary +> <NUM> as is.
- */
- set_start_expr_token('(');
- set_start_expr_token(',');
- set_start_expr_token(EVERY_SYM);
- set_start_expr_token(AT_SYM);
- set_start_expr_token(STARTS_SYM);
- set_start_expr_token(ENDS_SYM);
- set_start_expr_token(DEFAULT);
- set_start_expr_token(RETURN_SYM);
- set_start_expr_token(IF_SYM);
- set_start_expr_token(ELSEIF_SYM);
- set_start_expr_token(CASE_SYM);
- set_start_expr_token(WHEN_SYM);
- set_start_expr_token(WHILE_SYM);
- set_start_expr_token(UNTIL_SYM);
- set_start_expr_token(SELECT_SYM);
-
- set_start_expr_token(OR_SYM);
- set_start_expr_token(OR2_SYM);
- set_start_expr_token(XOR);
- set_start_expr_token(AND_SYM);
- set_start_expr_token(AND_AND_SYM);
- set_start_expr_token(NOT_SYM);
- set_start_expr_token(BETWEEN_SYM);
- set_start_expr_token(LIKE);
- set_start_expr_token(REGEXP);
-
- set_start_expr_token('|');
- set_start_expr_token('&');
- set_start_expr_token(SHIFT_LEFT);
- set_start_expr_token(SHIFT_RIGHT);
- set_start_expr_token('+');
- set_start_expr_token('-');
- set_start_expr_token(INTERVAL_SYM);
- set_start_expr_token('*');
- set_start_expr_token('/');
- set_start_expr_token('%');
- set_start_expr_token(DIV_SYM);
- set_start_expr_token(MOD_SYM);
- set_start_expr_token('^');
-}
-
-void print_tokens()
-{
- int tok;
-
- printf("lex_token_string lex_token_array[]=\n");
- printf("{\n");
- printf("/* PART 1: character tokens. */\n");
-
- for (tok= 0; tok<256; tok++)
- {
- printf("/* %03d */ { \"\\x%02x\", 1, %s, %s},\n",
- tok,
- tok,
- compiled_token_array[tok].m_append_space ? "true" : "false",
- compiled_token_array[tok].m_start_expr ? "true" : "false");
- }
-
- printf("/* PART 2: named tokens. */\n");
-
- for (tok= 256; tok<= max_token_seen; tok++)
- {
- printf("/* %03d */ { \"%s\", %d, %s, %s},\n",
- tok,
- compiled_token_array[tok].m_token_string,
- compiled_token_array[tok].m_token_length,
- compiled_token_array[tok].m_append_space ? "true" : "false",
- compiled_token_array[tok].m_start_expr ? "true" : "false");
- }
-
- printf("/* DUMMY */ { \"\", 0, false, false}\n");
- printf("};\n");
-
- printf("/* PFS specific tokens. */\n");
- printf("#define TOK_PFS_GENERIC_VALUE %d\n", tok_pfs_generic_value);
- printf("#define TOK_PFS_GENERIC_VALUE_LIST %d\n", tok_pfs_generic_value_list);
- printf("#define TOK_PFS_ROW_SINGLE_VALUE %d\n", tok_pfs_row_single_value);
- printf("#define TOK_PFS_ROW_SINGLE_VALUE_LIST %d\n", tok_pfs_row_single_value_list);
- printf("#define TOK_PFS_ROW_MULTIPLE_VALUE %d\n", tok_pfs_row_multiple_value);
- printf("#define TOK_PFS_ROW_MULTIPLE_VALUE_LIST %d\n", tok_pfs_row_multiple_value_list);
- printf("#define TOK_PFS_UNUSED %d\n", tok_pfs_unused);
-}
-
-int main(int argc,char **argv)
-{
- puts("/*");
- puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2011"));
- puts("*/");
-
- printf("/*\n");
- printf(" This file is generated, do not edit.\n");
- printf(" See file storage/perfschema/gen_pfs_lex_token.cc.\n");
- printf("*/\n");
- printf("struct lex_token_string\n");
- printf("{\n");
- printf(" const char *m_token_string;\n");
- printf(" int m_token_length;\n");
- printf(" bool m_append_space;\n");
- printf(" bool m_start_expr;\n");
- printf("};\n");
- printf("typedef struct lex_token_string lex_token_string;\n");
-
- compute_tokens();
- print_tokens();
-
- return 0;
-}
-
diff --git a/storage/perfschema/ha_perfschema.cc b/storage/perfschema/ha_perfschema.cc
index 0972d0dae21..2261b4feff1 100644
--- a/storage/perfschema/ha_perfschema.cc
+++ b/storage/perfschema/ha_perfschema.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2016, 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, version 2.0,
@@ -36,10 +36,14 @@
#include "pfs_account.h"
#include "pfs_host.h"
#include "pfs_user.h"
-#include "pfs_account.h"
+#include "pfs_program.h"
+#include "pfs_prepared_stmt.h"
+#include "pfs_buffer_container.h"
handlerton *pfs_hton= NULL;
+#define PFS_ENABLED() (pfs_initialized && (pfs_enabled || m_table_share->m_perpetual))
+
static handler* pfs_create_handler(handlerton *hton,
TABLE_SHARE *table,
MEM_ROOT *mem_root)
@@ -131,6 +135,15 @@ static int pfs_done_func(void *p)
DBUG_RETURN(0);
}
+static int show_func_mutex_instances_lost(THD *thd, SHOW_VAR *var, char *buff)
+{
+ var->type= SHOW_LONG;
+ var->value= buff;
+ long *value= reinterpret_cast<long*>(buff);
+ *value= global_mutex_container.get_lost_counter();
+ return 0;
+}
+
static struct st_mysql_show_var pfs_status_vars[]=
{
{"Performance_schema_mutex_classes_lost",
@@ -145,34 +158,42 @@ static struct st_mysql_show_var pfs_status_vars[]=
(char*) &file_class_lost, SHOW_LONG_NOFLUSH},
{"Performance_schema_socket_classes_lost",
(char*) &socket_class_lost, SHOW_LONG_NOFLUSH},
+ {"Performance_schema_memory_classes_lost",
+ (char*) &memory_class_lost, SHOW_LONG_NOFLUSH},
{"Performance_schema_mutex_instances_lost",
- (char*) &mutex_lost, SHOW_LONG},
+ (char*) &show_func_mutex_instances_lost, SHOW_FUNC},
{"Performance_schema_rwlock_instances_lost",
- (char*) &rwlock_lost, SHOW_LONG},
+ (char*) &global_rwlock_container.m_lost, SHOW_LONG},
{"Performance_schema_cond_instances_lost",
- (char*) &cond_lost, SHOW_LONG},
+ (char*) &global_cond_container.m_lost, SHOW_LONG},
{"Performance_schema_thread_instances_lost",
- (char*) &thread_lost, SHOW_LONG},
+ (char*) &global_thread_container.m_lost, SHOW_LONG},
{"Performance_schema_file_instances_lost",
- (char*) &file_lost, SHOW_LONG},
+ (char*) &global_file_container.m_lost, SHOW_LONG},
{"Performance_schema_file_handles_lost",
(char*) &file_handle_lost, SHOW_LONG},
{"Performance_schema_socket_instances_lost",
- (char*) &socket_lost, SHOW_LONG},
+ (char*) &global_socket_container.m_lost, SHOW_LONG},
{"Performance_schema_locker_lost",
(char*) &locker_lost, SHOW_LONG},
/* table shares, can be flushed */
{"Performance_schema_table_instances_lost",
- (char*) &table_share_lost, SHOW_LONG},
+ (char*) &global_table_share_container.m_lost, SHOW_LONG},
/* table handles, can be flushed */
{"Performance_schema_table_handles_lost",
- (char*) &table_lost, SHOW_LONG},
+ (char*) &global_table_container.m_lost, SHOW_LONG},
+ /* table lock stats, can be flushed */
+ {"Performance_schema_table_lock_stat_lost",
+ (char*) &global_table_share_lock_container.m_lost, SHOW_LONG},
+ /* table index stats, can be flushed */
+ {"Performance_schema_index_stat_lost",
+ (char*) &global_table_share_index_container.m_lost, SHOW_LONG},
{"Performance_schema_hosts_lost",
- (char*) &host_lost, SHOW_LONG},
+ (char*) &global_host_container.m_lost, SHOW_LONG},
{"Performance_schema_users_lost",
- (char*) &user_lost, SHOW_LONG},
+ (char*) &global_user_container.m_lost, SHOW_LONG},
{"Performance_schema_accounts_lost",
- (char*) &account_lost, SHOW_LONG},
+ (char*) &global_account_container.m_lost, SHOW_LONG},
{"Performance_schema_stage_classes_lost",
(char*) &stage_class_lost, SHOW_LONG},
{"Performance_schema_statement_classes_lost",
@@ -181,6 +202,14 @@ static struct st_mysql_show_var pfs_status_vars[]=
(char*) &digest_lost, SHOW_LONG},
{"Performance_schema_session_connect_attrs_lost",
(char*) &session_connect_attrs_lost, SHOW_LONG},
+ {"Performance_schema_program_lost",
+ (char*) &global_program_container.m_lost, SHOW_LONG},
+ {"Performance_schema_nested_statement_lost",
+ (char*) &nested_statement_lost, SHOW_LONG},
+ {"Performance_schema_prepared_statements_lost",
+ (char*) &global_prepared_stmt_container.m_lost, SHOW_LONG},
+ {"Performance_schema_metadata_lock_lost",
+ (char*) &global_mdl_container.m_lost, SHOW_LONG},
{NullS, NullS, SHOW_LONG}
};
@@ -262,7 +291,7 @@ int ha_perfschema::write_row(const uchar *buf)
int result;
DBUG_ENTER("ha_perfschema::write_row");
- if (!pfs_initialized)
+ if (!PFS_ENABLED())
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
DBUG_ASSERT(m_table_share);
@@ -284,7 +313,7 @@ void ha_perfschema::use_hidden_primary_key(void)
int ha_perfschema::update_row(const uchar *old_data, const uchar *new_data)
{
DBUG_ENTER("ha_perfschema::update_row");
- if (!pfs_initialized)
+ if (!PFS_ENABLED())
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
if (is_executed_by_slave())
@@ -298,7 +327,7 @@ int ha_perfschema::update_row(const uchar *old_data, const uchar *new_data)
int ha_perfschema::delete_row(const uchar *buf)
{
DBUG_ENTER("ha_perfschema::delete_row");
- if (!pfs_initialized)
+ if (!PFS_ENABLED())
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
DBUG_ASSERT(m_table);
@@ -339,7 +368,7 @@ int ha_perfschema::rnd_end(void)
int ha_perfschema::rnd_next(uchar *buf)
{
DBUG_ENTER("ha_perfschema::rnd_next");
- if (!pfs_initialized)
+ if (!PFS_ENABLED())
{
table->status= STATUS_NOT_FOUND;
DBUG_RETURN(HA_ERR_END_OF_FILE);
@@ -370,7 +399,7 @@ 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)
+ if (!PFS_ENABLED())
{
table->status= STATUS_NOT_FOUND;
DBUG_RETURN(HA_ERR_END_OF_FILE);
@@ -400,7 +429,7 @@ int ha_perfschema::delete_all_rows(void)
int result;
DBUG_ENTER("ha_perfschema::delete_all_rows");
- if (!pfs_initialized)
+ if (!PFS_ENABLED())
DBUG_RETURN(0);
if (is_executed_by_slave())
diff --git a/storage/perfschema/ha_perfschema.h b/storage/perfschema/ha_perfschema.h
index 18ac035831d..36ea124056d 100644
--- a/storage/perfschema/ha_perfschema.h
+++ b/storage/perfschema/ha_perfschema.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
diff --git a/storage/perfschema/my_thread.h b/storage/perfschema/my_thread.h
new file mode 100644
index 00000000000..28f8ae07ab8
--- /dev/null
+++ b/storage/perfschema/my_thread.h
@@ -0,0 +1,90 @@
+#ifndef STORAGE_PERFSCHEMA_MY_THREAD_INCLUDED
+#define STORAGE_PERFSCHEMA_MY_THREAD_INCLUDED
+
+#include <my_pthread.h>
+#include <m_string.h>
+#include "rpl_gtid.h"
+
+typedef pthread_key_t thread_local_key_t;
+typedef pthread_t my_thread_handle;
+typedef pthread_attr_t my_thread_attr_t;
+typedef uint32 my_thread_os_id_t;
+
+static inline int my_create_thread_local_key(thread_local_key_t *key, void (*destructor)(void*))
+{ return pthread_key_create(key, destructor); }
+
+static inline int my_delete_thread_local_key(thread_local_key_t key)
+{ return pthread_key_delete(key); }
+
+static inline void *my_get_thread_local(thread_local_key_t key)
+{ return pthread_getspecific(key); }
+
+static inline int my_set_thread_local(thread_local_key_t key, const void *ptr)
+{ return pthread_setspecific(key, ptr); }
+
+static inline int my_thread_create(my_thread_handle *thread,
+ const my_thread_attr_t *attr, void *(*start_routine)(void *), void *arg)
+{ return pthread_create(thread, attr, start_routine, arg); }
+
+static inline my_thread_os_id_t my_thread_os_id()
+{
+#ifdef __NR_gettid
+ return (uint32)syscall(__NR_gettid);
+#else
+ return 0;
+#endif
+}
+
+enum enum_sp_type
+{
+ SP_TYPE_FUNCTION= 1,
+ SP_TYPE_PROCEDURE,
+ SP_TYPE_TRIGGER,
+ SP_TYPE_EVENT
+};
+
+#define CHANNEL_NAME_LENGTH MAX_CONNECTION_NAME
+
+enum enum_mysql_show_scope
+{
+ SHOW_SCOPE_UNDEF,
+ SHOW_SCOPE_GLOBAL,
+ SHOW_SCOPE_SESSION,
+ SHOW_SCOPE_ALL
+};
+typedef enum enum_mysql_show_scope SHOW_SCOPE;
+
+#define SHOW_VAR_MAX_NAME_LEN NAME_LEN
+
+static inline char *my_stpnmov(char *dst, const char *src, size_t n)
+{ return strnmov(dst, src, n); }
+
+class Gtid_specification: public rpl_gtid
+{
+public:
+ size_t to_string(char *buf)
+ {
+ return my_snprintf(buf, GTID_MAX_STR_LENGTH, "%u-%u-%llu",
+ domain_id, server_id, seq_no);
+ }
+};
+
+static inline size_t bin_to_hex_str(char *to, size_t to_len,
+ const char *from, size_t from_len)
+{
+ if (to_len < from_len * 2 + 1)
+ return 0 ;
+ for (size_t i=0; i < from_len; i++, from++)
+ {
+ *to++=_dig_vec_upper[((unsigned char) *from) >> 4];
+ *to++=_dig_vec_upper[((unsigned char) *from) & 0xF];
+ }
+ *to= '\0';
+ return from_len * 2 + 1;
+}
+
+enum enum_psi_status { PENDING = 0, GRANTED,
+ PRE_ACQUIRE_NOTIFY, POST_RELEASE_NOTIFY };
+
+PSI_thread* thd_get_psi(THD *thd);
+#endif
diff --git a/storage/perfschema/pfs.cc b/storage/perfschema/pfs.cc
index 2f1081b3836..23b9feab6ed 100644
--- a/storage/perfschema/pfs.cc
+++ b/storage/perfschema/pfs.cc
@@ -26,6 +26,19 @@
*/
#include "my_global.h"
#include "thr_lock.h"
+
+/* Make sure exported prototypes match the implementation. */
+#include "pfs_file_provider.h"
+#include "pfs_idle_provider.h"
+#include "pfs_memory_provider.h"
+#include "pfs_metadata_provider.h"
+#include "pfs_socket_provider.h"
+#include "pfs_stage_provider.h"
+#include "pfs_statement_provider.h"
+#include "pfs_table_provider.h"
+#include "pfs_thread_provider.h"
+#include "pfs_transaction_provider.h"
+
#include "mysql/psi/psi.h"
#include "mysql/psi/mysql_thread.h"
#include "my_pthread.h"
@@ -42,11 +55,48 @@
#include "pfs_events_waits.h"
#include "pfs_events_stages.h"
#include "pfs_events_statements.h"
+#include "pfs_events_transactions.h"
#include "pfs_setup_actor.h"
#include "pfs_setup_object.h"
#include "sql_error.h"
#include "sp_head.h"
+#include "mdl.h" /* mdl_key_init */
#include "pfs_digest.h"
+#include "pfs_program.h"
+#include "pfs_prepared_stmt.h"
+
+using std::min;
+
+/*
+ This is a development tool to investigate memory statistics,
+ do not use in production.
+*/
+#undef PFS_PARANOID
+
+#ifdef PFS_PARANOID
+static void report_memory_accounting_error(
+ const char *api_name,
+ PFS_thread *new_thread,
+ size_t size,
+ PFS_memory_class *klass,
+ PFS_thread *old_thread)
+{
+ pfs_print_error("%s "
+ "thread <%d> of class <%s> "
+ "not owner of <%d> bytes in class <%s> "
+ "allocated by thread <%d> of class <%s>\n",
+ api_name,
+ new_thread->m_thread_internal_id,
+ new_thread->m_class->m_name,
+ size, klass->m_name,
+ old_thread->m_thread_internal_id,
+ old_thread->m_class->m_name);
+
+ DBUG_ASSERT(strcmp(new_thread->m_class->m_name, "thread/sql/event_worker") != 0);
+ DBUG_ASSERT(strcmp(new_thread->m_class->m_name, "thread/sql/event_scheduler") != 0);
+ DBUG_ASSERT(strcmp(new_thread->m_class->m_name, "thread/sql/one_connection") != 0);
+}
+#endif /* PFS_PARANOID */
/**
@page PAGE_PERFORMANCE_SCHEMA The Performance Schema main page
@@ -393,14 +443,14 @@ static inline int mysql_mutex_lock(
struct PSI_mutex_locker *locker= NULL;
............... (a)
- locker= PSI_server->start_mutex_wait(&state, that->p_psi,
- PSI_MUTEX_LOCK, locker, src_file, src_line);
+ locker= PSI_MUTEX_CALL(start_mutex_wait)(&state, that->p_psi, PSI_MUTEX_LOCK,
+ locker, src_file, src_line);
............... (b)
result= pthread_mutex_lock(&that->m_mutex);
............... (c)
- PSI_server->end_mutex_wait(locker, result);
+ PSI_MUTEX_CALL(end_mutex_wait)(locker, result);
return result;
}
@@ -420,6 +470,62 @@ static inline int mysql_mutex_lock(...)
return result;
}
@endverbatim
+
+ When the performance schema instrumentation is compiled in,
+ and when the code compiled is internal to the server implementation,
+ PSI_MUTEX_CALL expands directly to functions calls in the performance schema,
+ to make (a) and (c) calls as efficient as possible.
+
+@verbatim
+static inline int mysql_mutex_lock(...)
+{
+ int result;
+ struct PSI_mutex_locker_state state;
+ struct PSI_mutex_locker *locker= NULL;
+
+ ............... (a)
+ locker= pfs_start_mutex_wait_v1(&state, that->p_psi, PSI_MUTEX_LOCK,
+ locker, src_file, src_line);
+
+ ............... (b)
+ result= pthread_mutex_lock(&that->m_mutex);
+
+ ............... (c)
+ pfs_end_mutex_wait_v1(locker, result);
+
+ return result;
+}
+@endverbatim
+
+ When the performance schema instrumentation is compiled in,
+ and when the code compiled is external to the server implementation
+ (typically, a dynamic plugin),
+ PSI_MUTEX_CALL expands to dynamic calls to the underlying implementation,
+ using the PSI_server entry point.
+ This makes (a) and (c) slower, as a function pointer is used instead of a static call,
+ but also independent of the implementation, for binary compatibility.
+
+@verbatim
+static inline int mysql_mutex_lock(...)
+{
+ int result;
+ struct PSI_mutex_locker_state state;
+ struct PSI_mutex_locker *locker= NULL;
+
+ ............... (a)
+ locker= PSI_server->start_mutex_wait(&state, that->p_psi, PSI_MUTEX_LOCK,
+ locker, src_file, src_line);
+
+ ............... (b)
+ result= pthread_mutex_lock(&that->m_mutex);
+
+ ............... (c)
+ PSI_server->end_mutex_wait(locker, result);
+
+ return result;
+}
+@endverbatim
+
*/
/**
@@ -1102,6 +1208,134 @@ static inline int mysql_mutex_lock(...)
@c table_events_statements_common::make_row()
- [I] EVENTS_STATEMENTS_SUMMARY_BY_DIGEST
@c table_esms_by_digest::make_row()
+
+@section IMPL_TRANSACTION Implementation for transactions consumers
+
+ For transactions, the tables that contains individual event data are:
+ - EVENTS_TRANSACTIONS_CURRENT
+ - EVENTS_TRANSACTIONS_HISTORY
+ - EVENTS_TRANSACTIONS_HISTORY_LONG
+
+ For transactions, the tables that contains aggregated data are:
+ - EVENTS_TRANSACTIONS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME
+ - EVENTS_TRANSACTIONS_SUMMARY_BY_HOST_BY_EVENT_NAME
+ - EVENTS_TRANSACTIONS_SUMMARY_BY_THREAD_BY_EVENT_NAME
+ - EVENTS_TRANSACTIONS_SUMMARY_BY_USER_BY_EVENT_NAME
+ - EVENTS_TRANSACTIONS_SUMMARY_GLOBAL_BY_EVENT_NAME
+
+@verbatim
+ transaction_locker(T, TX)
+ |
+ | [1]
+ |
+1a |-> pfs_thread(T).event_name(TX) =====>> [A], [B], [C], [D], [E]
+ | |
+ | | [2]
+ | |
+ | 2a |-> pfs_account(U, H).event_name(TX) =====>> [B], [C], [D], [E]
+ | . |
+ | . | [3-RESET]
+ | . |
+ | 2b .....+-> pfs_user(U).event_name(TX) =====>> [C]
+ | . |
+ | 2c .....+-> pfs_host(H).event_name(TX) =====>> [D], [E]
+ | . . |
+ | . . | [4-RESET]
+ | 2d . . |
+1b |----+----+----+-> pfs_transaction_class(TX) =====>> [E]
+ |
+1c |-> pfs_thread(T).transaction_current(TX) =====>> [F]
+ |
+1d |-> pfs_thread(T).transaction_history(TX) =====>> [G]
+ |
+1e |-> transaction_history_long(TX) =====>> [H]
+
+@endverbatim
+
+ Implemented as:
+ - [1] @c start_transaction_v1(), end_transaction_v1()
+ (1a, 1b) is an aggregation by EVENT_NAME,
+ (1c, 1d, 1e) is an aggregation by TIME,
+ all of these are orthogonal,
+ and implemented in end_transaction_v1().
+ - [2] @c delete_thread_v1(), @c aggregate_thread_transactions()
+ - [3] @c PFS_account::aggregate_transactions()
+ - [4] @c PFS_host::aggregate_transactions()
+
+ - [A] EVENTS_TRANSACTIONS_SUMMARY_BY_THREAD_BY_EVENT_NAME,
+ @c table_ets_by_thread_by_event_name::make_row()
+ - [B] EVENTS_TRANSACTIONS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME,
+ @c table_ets_by_account_by_event_name::make_row()
+ - [C] EVENTS_TRANSACTIONS_SUMMARY_BY_USER_BY_EVENT_NAME,
+ @c table_ets_by_user_by_event_name::make_row()
+ - [D] EVENTS_TRANSACTIONS_SUMMARY_BY_HOST_BY_EVENT_NAME,
+ @c table_ets_by_host_by_event_name::make_row()
+ - [E] EVENTS_TRANSACTIONS_SUMMARY_GLOBAL_BY_EVENT_NAME,
+ @c table_ets_global_by_event_name::make_row()
+ - [F] EVENTS_TRANSACTIONS_CURRENT,
+ @c table_events_transactions_current::rnd_next(),
+ @c table_events_transactions_common::make_row()
+ - [G] EVENTS_TRANSACTIONS_HISTORY,
+ @c table_events_transactions_history::rnd_next(),
+ @c table_events_transactions_common::make_row()
+ - [H] EVENTS_TRANSACTIONS_HISTORY_LONG,
+ @c table_events_transactions_history_long::rnd_next(),
+ @c table_events_transactions_common::make_row()
+
+@section IMPL_MEMORY Implementation for memory instruments
+
+ For memory, there are no tables that contains individual event data.
+
+ For memory, the tables that contains aggregated data are:
+ - MEMORY_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME
+ - MEMORY_SUMMARY_BY_HOST_BY_EVENT_NAME
+ - MEMORY_SUMMARY_BY_THREAD_BY_EVENT_NAME
+ - MEMORY_SUMMARY_BY_USER_BY_EVENT_NAME
+ - MEMORY_SUMMARY_GLOBAL_BY_EVENT_NAME
+
+@verbatim
+ memory_event(T, S)
+ |
+ | [1]
+ |
+1a |-> pfs_thread(T).event_name(S) =====>> [A], [B], [C], [D], [E]
+ | |
+ | | [2]
+ | |
+1+ | 2a |-> pfs_account(U, H).event_name(S) =====>> [B], [C], [D], [E]
+ | . |
+ | . | [3-RESET]
+ | . |
+1+ | 2b .....+-> pfs_user(U).event_name(S) =====>> [C]
+ | . |
+1+ | 2c .....+-> pfs_host(H).event_name(S) =====>> [D], [E]
+ | . . |
+ | . . | [4-RESET]
+ | 2d . . |
+1b |----+----+----+-> global.event_name(S) =====>> [E]
+
+@endverbatim
+
+ Implemented as:
+ - [1] @c pfs_memory_alloc_v1(),
+ @c pfs_memory_realloc_v1(),
+ @c pfs_memory_free_v1().
+ - [1+] are overflows that can happen during [1a],
+ implemented with @c carry_memory_stat_delta()
+ - [2] @c delete_thread_v1(), @c aggregate_thread_memory()
+ - [3] @c PFS_account::aggregate_memory()
+ - [4] @c PFS_host::aggregate_memory()
+ - [A] EVENTS_STATEMENTS_SUMMARY_BY_THREAD_BY_EVENT_NAME,
+ @c table_mems_by_thread_by_event_name::make_row()
+ - [B] EVENTS_STATEMENTS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME,
+ @c table_mems_by_account_by_event_name::make_row()
+ - [C] EVENTS_STATEMENTS_SUMMARY_BY_USER_BY_EVENT_NAME,
+ @c table_mems_by_user_by_event_name::make_row()
+ - [D] EVENTS_STATEMENTS_SUMMARY_BY_HOST_BY_EVENT_NAME,
+ @c table_mems_by_host_by_event_name::make_row()
+ - [E] EVENTS_STATEMENTS_SUMMARY_GLOBAL_BY_EVENT_NAME,
+ @c table_mems_global_by_event_name::make_row()
+
*/
/**
@@ -1117,9 +1351,35 @@ static inline int mysql_mutex_lock(...)
@ingroup Performance_schema_implementation
*/
-pthread_key(PFS_thread*, THR_PFS);
+thread_local_key_t THR_PFS;
+thread_local_key_t THR_PFS_VG; // global_variables
+thread_local_key_t THR_PFS_SV; // session_variables
+thread_local_key_t THR_PFS_VBT; // variables_by_thread
+thread_local_key_t THR_PFS_SG; // global_status
+thread_local_key_t THR_PFS_SS; // session_status
+thread_local_key_t THR_PFS_SBT; // status_by_thread
+thread_local_key_t THR_PFS_SBU; // status_by_user
+thread_local_key_t THR_PFS_SBH; // status_by_host
+thread_local_key_t THR_PFS_SBA; // status_by_account
+
bool THR_PFS_initialized= false;
+static inline PFS_thread*
+my_thread_get_THR_PFS()
+{
+ DBUG_ASSERT(THR_PFS_initialized);
+ PFS_thread *thread= static_cast<PFS_thread*>(my_get_thread_local(THR_PFS));
+ DBUG_ASSERT(thread == NULL || sanitize_thread(thread) != NULL);
+ return thread;
+}
+
+static inline void
+my_thread_set_THR_PFS(PFS_thread *pfs)
+{
+ DBUG_ASSERT(THR_PFS_initialized);
+ my_set_thread_local(THR_PFS, pfs);
+}
+
/**
Conversion map from PSI_mutex_operation to enum_operation_type.
Indexed by enum PSI_mutex_operation.
@@ -1139,7 +1399,14 @@ static enum_operation_type rwlock_operation_map[]=
OPERATION_TYPE_READLOCK,
OPERATION_TYPE_WRITELOCK,
OPERATION_TYPE_TRYREADLOCK,
- OPERATION_TYPE_TRYWRITELOCK
+ OPERATION_TYPE_TRYWRITELOCK,
+
+ OPERATION_TYPE_SHAREDLOCK,
+ OPERATION_TYPE_SHAREDEXCLUSIVELOCK,
+ OPERATION_TYPE_EXCLUSIVELOCK,
+ OPERATION_TYPE_TRYSHAREDLOCK,
+ OPERATION_TYPE_TRYSHAREDEXCLUSIVELOCK,
+ OPERATION_TYPE_TRYEXCLUSIVELOCK,
};
/**
@@ -1201,7 +1468,6 @@ static enum_operation_type table_lock_operation_map[]=
OPERATION_TYPE_TL_READ_NO_INSERTS, /* PFS_TL_READ_NO_INSERT */
OPERATION_TYPE_TL_WRITE_ALLOW_WRITE, /* PFS_TL_WRITE_ALLOW_WRITE */
OPERATION_TYPE_TL_WRITE_CONCURRENT_INSERT, /* PFS_TL_WRITE_CONCURRENT_INSERT */
- OPERATION_TYPE_TL_WRITE_DELAYED, /* PFS_TL_WRITE_DELAYED */
OPERATION_TYPE_TL_WRITE_LOW_PRIORITY, /* PFS_TL_WRITE_LOW_PRIORITY */
OPERATION_TYPE_TL_WRITE_NORMAL, /* PFS_TL_WRITE */
OPERATION_TYPE_TL_READ_EXTERNAL, /* PFS_TL_READ_EXTERNAL */
@@ -1244,7 +1510,7 @@ static enum_operation_type socket_operation_map[]=
@return 0 for success, non zero for errors
*/
static int build_prefix(const LEX_CSTRING *prefix, const char *category,
- char *output, int *output_length)
+ char *output, size_t *output_length)
{
size_t len= strlen(category);
char *out_ptr= output;
@@ -1268,52 +1534,56 @@ static int build_prefix(const LEX_CSTRING *prefix, const char *category,
/* output = prefix + category + '/' */
memcpy(out_ptr, prefix->str, prefix_length);
out_ptr+= prefix_length;
- memcpy(out_ptr, category, len);
- out_ptr+= len;
- *out_ptr= '/';
- out_ptr++;
- *output_length= (int)(out_ptr - output);
+ if (len > 0)
+ {
+ memcpy(out_ptr, category, len);
+ out_ptr+= len;
+ *out_ptr= '/';
+ out_ptr++;
+ }
+ *output_length= int(out_ptr - output);
return 0;
}
-#define REGISTER_BODY_V1(KEY_T, PREFIX, REGISTER_FUNC) \
- KEY_T key; \
- char formatted_name[PFS_MAX_INFO_NAME_LENGTH]; \
- int prefix_length; \
- int len; \
- int full_length; \
- \
- DBUG_ASSERT(category != NULL); \
- DBUG_ASSERT(info != NULL); \
- if (unlikely(build_prefix(&PREFIX, category, \
- formatted_name, &prefix_length))) \
- { \
- for (; count>0; count--, info++) \
- *(info->m_key)= 0; \
- return ; \
- } \
- \
- for (; count>0; count--, info++) \
- { \
- DBUG_ASSERT(info->m_key != NULL); \
- DBUG_ASSERT(info->m_name != NULL); \
- len= (int)strlen(info->m_name); \
- full_length= prefix_length + len; \
- if (likely(full_length <= PFS_MAX_INFO_NAME_LENGTH)) \
- { \
- memcpy(formatted_name + prefix_length, info->m_name, len); \
- key= REGISTER_FUNC(formatted_name, full_length, info->m_flags); \
- } \
- else \
- { \
- pfs_print_error("REGISTER_BODY_V1: name too long <%s> <%s>\n", \
- category, info->m_name); \
- key= 0; \
- } \
- \
- *(info->m_key)= key; \
- } \
+#define REGISTER_BODY_V1(KEY_T, PREFIX, REGISTER_FUNC) \
+ KEY_T key; \
+ char formatted_name[PFS_MAX_INFO_NAME_LENGTH]; \
+ size_t prefix_length; \
+ size_t len; \
+ size_t full_length; \
+ \
+ DBUG_ASSERT(category != NULL); \
+ DBUG_ASSERT(info != NULL); \
+ if (unlikely(build_prefix(&PREFIX, category, \
+ formatted_name, &prefix_length)) || \
+ ! pfs_initialized) \
+ { \
+ for (; count>0; count--, info++) \
+ *(info->m_key)= 0; \
+ return ; \
+ } \
+ \
+ for (; count>0; count--, info++) \
+ { \
+ DBUG_ASSERT(info->m_key != NULL); \
+ DBUG_ASSERT(info->m_name != NULL); \
+ len= strlen(info->m_name); \
+ full_length= prefix_length + len; \
+ if (likely(full_length <= PFS_MAX_INFO_NAME_LENGTH)) \
+ { \
+ memcpy(formatted_name + prefix_length, info->m_name, len); \
+ key= REGISTER_FUNC(formatted_name, (uint)full_length, info->m_flags); \
+ } \
+ else \
+ { \
+ pfs_print_error("REGISTER_BODY_V1: name too long <%s> <%s>\n", \
+ category, info->m_name); \
+ key= 0; \
+ } \
+ \
+ *(info->m_key)= key; \
+ } \
return;
/* Use C linkage for the interface functions. */
@@ -1324,9 +1594,9 @@ C_MODE_START
Implementation of the mutex instrumentation interface.
@sa PSI_v1::register_mutex.
*/
-static void register_mutex_v1(const char *category,
- PSI_mutex_info_v1 *info,
- int count)
+void pfs_register_mutex_v1(const char *category,
+ PSI_mutex_info_v1 *info,
+ int count)
{
REGISTER_BODY_V1(PSI_mutex_key,
mutex_instrument_prefix,
@@ -1337,22 +1607,80 @@ static void register_mutex_v1(const char *category,
Implementation of the rwlock instrumentation interface.
@sa PSI_v1::register_rwlock.
*/
-static void register_rwlock_v1(const char *category,
- PSI_rwlock_info_v1 *info,
- int count)
+void pfs_register_rwlock_v1(const char *category,
+ PSI_rwlock_info_v1 *info,
+ int count)
{
- REGISTER_BODY_V1(PSI_rwlock_key,
- rwlock_instrument_prefix,
- register_rwlock_class)
+ PSI_rwlock_key key;
+ char rw_formatted_name[PFS_MAX_INFO_NAME_LENGTH];
+ char sx_formatted_name[PFS_MAX_INFO_NAME_LENGTH];
+ size_t rw_prefix_length;
+ size_t sx_prefix_length;
+ size_t len;
+ size_t full_length;
+
+ DBUG_ASSERT(category != NULL);
+ DBUG_ASSERT(info != NULL);
+ if (build_prefix(&rwlock_instrument_prefix, category,
+ rw_formatted_name, &rw_prefix_length) ||
+ build_prefix(&sxlock_instrument_prefix, category,
+ sx_formatted_name, &sx_prefix_length) ||
+ ! pfs_initialized)
+ {
+ for (; count>0; count--, info++)
+ *(info->m_key)= 0;
+ return ;
+ }
+
+ for (; count>0; count--, info++)
+ {
+ DBUG_ASSERT(info->m_key != NULL);
+ DBUG_ASSERT(info->m_name != NULL);
+ len= strlen(info->m_name);
+
+ if (info->m_flags & PSI_RWLOCK_FLAG_SX)
+ {
+ full_length= sx_prefix_length + len;
+ if (likely(full_length <= PFS_MAX_INFO_NAME_LENGTH))
+ {
+ memcpy(sx_formatted_name + sx_prefix_length, info->m_name, len);
+ key= register_rwlock_class(sx_formatted_name, (uint)full_length, info->m_flags);
+ }
+ else
+ {
+ pfs_print_error("REGISTER_BODY_V1: (sx) name too long <%s> <%s>\n",
+ category, info->m_name);
+ key= 0;
+ }
+ }
+ else
+ {
+ full_length= rw_prefix_length + len;
+ if (likely(full_length <= PFS_MAX_INFO_NAME_LENGTH))
+ {
+ memcpy(rw_formatted_name + rw_prefix_length, info->m_name, len);
+ key= register_rwlock_class(rw_formatted_name, (uint)full_length, info->m_flags);
+ }
+ else
+ {
+ pfs_print_error("REGISTER_BODY_V1: (rw) name too long <%s> <%s>\n",
+ category, info->m_name);
+ key= 0;
+ }
+ }
+
+ *(info->m_key)= key;
+ }
+ return;
}
/**
Implementation of the cond instrumentation interface.
@sa PSI_v1::register_cond.
*/
-static void register_cond_v1(const char *category,
- PSI_cond_info_v1 *info,
- int count)
+void pfs_register_cond_v1(const char *category,
+ PSI_cond_info_v1 *info,
+ int count)
{
REGISTER_BODY_V1(PSI_cond_key,
cond_instrument_prefix,
@@ -1363,9 +1691,9 @@ static void register_cond_v1(const char *category,
Implementation of the thread instrumentation interface.
@sa PSI_v1::register_thread.
*/
-static void register_thread_v1(const char *category,
- PSI_thread_info_v1 *info,
- int count)
+void pfs_register_thread_v1(const char *category,
+ PSI_thread_info_v1 *info,
+ int count)
{
REGISTER_BODY_V1(PSI_thread_key,
thread_instrument_prefix,
@@ -1376,29 +1704,30 @@ static void register_thread_v1(const char *category,
Implementation of the file instrumentation interface.
@sa PSI_v1::register_file.
*/
-static void register_file_v1(const char *category,
- PSI_file_info_v1 *info,
- int count)
+void pfs_register_file_v1(const char *category,
+ PSI_file_info_v1 *info,
+ int count)
{
REGISTER_BODY_V1(PSI_file_key,
file_instrument_prefix,
register_file_class)
}
-static void register_stage_v1(const char *category,
- PSI_stage_info_v1 **info_array,
- int count)
+void pfs_register_stage_v1(const char *category,
+ PSI_stage_info_v1 **info_array,
+ int count)
{
char formatted_name[PFS_MAX_INFO_NAME_LENGTH];
- int prefix_length;
- int len;
- int full_length;
+ size_t prefix_length;
+ size_t len;
+ size_t full_length;
PSI_stage_info_v1 *info;
DBUG_ASSERT(category != NULL);
DBUG_ASSERT(info_array != NULL);
if (unlikely(build_prefix(&stage_instrument_prefix, category,
- formatted_name, &prefix_length)))
+ formatted_name, &prefix_length)) ||
+ ! pfs_initialized)
{
for (; count>0; count--, info_array++)
(*info_array)->m_key= 0;
@@ -1416,8 +1745,8 @@ static void register_stage_v1(const char *category,
{
memcpy(formatted_name + prefix_length, info->m_name, len);
info->m_key= register_stage_class(formatted_name,
- prefix_length,
- full_length,
+ (uint)prefix_length,
+ (uint)full_length,
info->m_flags);
}
else
@@ -1430,19 +1759,20 @@ static void register_stage_v1(const char *category,
return;
}
-static void register_statement_v1(const char *category,
- PSI_statement_info_v1 *info,
- int count)
+void pfs_register_statement_v1(const char *category,
+ PSI_statement_info_v1 *info,
+ int count)
{
char formatted_name[PFS_MAX_INFO_NAME_LENGTH];
- int prefix_length;
- int len;
- int full_length;
+ size_t prefix_length;
+ size_t len;
+ size_t full_length;
DBUG_ASSERT(category != NULL);
DBUG_ASSERT(info != NULL);
if (unlikely(build_prefix(&statement_instrument_prefix,
- category, formatted_name, &prefix_length)))
+ category, formatted_name, &prefix_length)) ||
+ ! pfs_initialized)
{
for (; count>0; count--, info++)
info->m_key= 0;
@@ -1459,7 +1789,7 @@ static void register_statement_v1(const char *category,
if (likely(full_length <= PFS_MAX_INFO_NAME_LENGTH))
{
memcpy(formatted_name + prefix_length, info->m_name, len);
- info->m_key= register_statement_class(formatted_name, full_length, info->m_flags);
+ info->m_key= register_statement_class(formatted_name, (uint)full_length, info->m_flags);
}
else
{
@@ -1471,9 +1801,9 @@ static void register_statement_v1(const char *category,
return;
}
-static void register_socket_v1(const char *category,
- PSI_socket_info_v1 *info,
- int count)
+void pfs_register_socket_v1(const char *category,
+ PSI_socket_info_v1 *info,
+ int count)
{
REGISTER_BODY_V1(PSI_socket_key,
socket_instrument_prefix,
@@ -1486,8 +1816,6 @@ static void register_socket_v1(const char *category,
klass= find_##T##_class(KEY); \
if (unlikely(klass == NULL)) \
return NULL; \
- if (! klass->m_enabled) \
- return NULL; \
pfs= create_##T(klass, ID); \
return reinterpret_cast<PSI_##T *> (pfs)
@@ -1495,8 +1823,8 @@ static void register_socket_v1(const char *category,
Implementation of the mutex instrumentation interface.
@sa PSI_v1::init_mutex.
*/
-static PSI_mutex*
-init_mutex_v1(PSI_mutex_key key, const void *identity)
+PSI_mutex*
+pfs_init_mutex_v1(PSI_mutex_key key, const void *identity)
{
INIT_BODY_V1(mutex, key, identity);
}
@@ -1505,7 +1833,7 @@ init_mutex_v1(PSI_mutex_key key, const void *identity)
Implementation of the mutex instrumentation interface.
@sa PSI_v1::destroy_mutex.
*/
-static void destroy_mutex_v1(PSI_mutex* mutex)
+void pfs_destroy_mutex_v1(PSI_mutex* mutex)
{
PFS_mutex *pfs= reinterpret_cast<PFS_mutex*> (mutex);
@@ -1518,8 +1846,8 @@ static void destroy_mutex_v1(PSI_mutex* mutex)
Implementation of the rwlock instrumentation interface.
@sa PSI_v1::init_rwlock.
*/
-static PSI_rwlock*
-init_rwlock_v1(PSI_rwlock_key key, const void *identity)
+PSI_rwlock*
+pfs_init_rwlock_v1(PSI_rwlock_key key, const void *identity)
{
INIT_BODY_V1(rwlock, key, identity);
}
@@ -1528,7 +1856,7 @@ init_rwlock_v1(PSI_rwlock_key key, const void *identity)
Implementation of the rwlock instrumentation interface.
@sa PSI_v1::destroy_rwlock.
*/
-static void destroy_rwlock_v1(PSI_rwlock* rwlock)
+void pfs_destroy_rwlock_v1(PSI_rwlock* rwlock)
{
PFS_rwlock *pfs= reinterpret_cast<PFS_rwlock*> (rwlock);
@@ -1541,8 +1869,8 @@ static void destroy_rwlock_v1(PSI_rwlock* rwlock)
Implementation of the cond instrumentation interface.
@sa PSI_v1::init_cond.
*/
-static PSI_cond*
-init_cond_v1(PSI_cond_key key, const void *identity)
+PSI_cond*
+pfs_init_cond_v1(PSI_cond_key key, const void *identity)
{
INIT_BODY_V1(cond, key, identity);
}
@@ -1551,7 +1879,7 @@ init_cond_v1(PSI_cond_key key, const void *identity)
Implementation of the cond instrumentation interface.
@sa PSI_v1::destroy_cond.
*/
-static void destroy_cond_v1(PSI_cond* cond)
+void pfs_destroy_cond_v1(PSI_cond* cond)
{
PFS_cond *pfs= reinterpret_cast<PFS_cond*> (cond);
@@ -1564,14 +1892,14 @@ static void destroy_cond_v1(PSI_cond* cond)
Implementation of the table instrumentation interface.
@sa PSI_v1::get_table_share.
*/
-static PSI_table_share*
-get_table_share_v1(my_bool temporary, TABLE_SHARE *share)
+PSI_table_share*
+pfs_get_table_share_v1(my_bool temporary, TABLE_SHARE *share)
{
/* Ignore temporary tables and views. */
if (temporary || share->is_view)
return NULL;
/* An instrumented thread is required, for LF_PINS. */
- PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+ PFS_thread *pfs_thread= my_thread_get_THR_PFS();
if (unlikely(pfs_thread == NULL))
return NULL;
PFS_table_share* pfs_share;
@@ -1583,7 +1911,7 @@ get_table_share_v1(my_bool temporary, TABLE_SHARE *share)
Implementation of the table instrumentation interface.
@sa PSI_v1::release_table_share.
*/
-static void release_table_share_v1(PSI_table_share* share)
+void pfs_release_table_share_v1(PSI_table_share* share)
{
PFS_table_share* pfs= reinterpret_cast<PFS_table_share*> (share);
@@ -1597,15 +1925,15 @@ static void release_table_share_v1(PSI_table_share* share)
Implementation of the table instrumentation interface.
@sa PSI_v1::drop_table_share.
*/
-static void
-drop_table_share_v1(my_bool temporary,
- const char *schema_name, int schema_name_length,
- const char *table_name, int table_name_length)
+void
+pfs_drop_table_share_v1(my_bool temporary,
+ const char *schema_name, int schema_name_length,
+ const char *table_name, int table_name_length)
{
/* Ignore temporary tables. */
if (temporary)
return;
- PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+ PFS_thread *pfs_thread= my_thread_get_THR_PFS();
if (unlikely(pfs_thread == NULL))
return;
/* TODO: temporary tables */
@@ -1617,8 +1945,8 @@ drop_table_share_v1(my_bool temporary,
Implementation of the table instrumentation interface.
@sa PSI_v1::open_table.
*/
-static PSI_table*
-open_table_v1(PSI_table_share *share, const void *identity)
+PSI_table*
+pfs_open_table_v1(PSI_table_share *share, const void *identity)
{
PFS_table_share *pfs_table_share= reinterpret_cast<PFS_table_share*> (share);
@@ -1641,7 +1969,8 @@ open_table_v1(PSI_table_share *share, const void *identity)
if (! global_table_io_class.m_enabled && ! global_table_lock_class.m_enabled)
return NULL;
- PFS_thread *thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+ PFS_thread *thread= my_thread_get_THR_PFS();
+
if (unlikely(thread == NULL))
return NULL;
@@ -1653,12 +1982,13 @@ open_table_v1(PSI_table_share *share, const void *identity)
Implementation of the table instrumentation interface.
@sa PSI_v1::unbind_table.
*/
-static void unbind_table_v1(PSI_table *table)
+void pfs_unbind_table_v1(PSI_table *table)
{
PFS_table *pfs= reinterpret_cast<PFS_table*> (table);
if (likely(pfs != NULL))
{
pfs->m_thread_owner= NULL;
+ pfs->m_owner_event_id= 0;
}
}
@@ -1666,43 +1996,42 @@ static void unbind_table_v1(PSI_table *table)
Implementation of the table instrumentation interface.
@sa PSI_v1::rebind_table.
*/
-static PSI_table *
-rebind_table_v1(PSI_table_share *share, const void *identity, PSI_table *table)
+PSI_table *
+pfs_rebind_table_v1(PSI_table_share *share, const void *identity, PSI_table *table)
{
PFS_table *pfs= reinterpret_cast<PFS_table*> (table);
if (likely(pfs != NULL))
{
- PFS_thread *thread;
DBUG_ASSERT(pfs->m_thread_owner == NULL);
- if (psi_unlikely(! flag_global_instrumentation))
+ if (unlikely(! pfs->m_share->m_enabled))
{
destroy_table(pfs);
return NULL;
}
- /* The table handle was already instrumented, reuse it for this thread. */
- thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
-
- if (unlikely(! pfs->m_share->m_enabled))
+ if (unlikely(! global_table_io_class.m_enabled && ! global_table_lock_class.m_enabled))
{
destroy_table(pfs);
return NULL;
}
- if (unlikely(! global_table_io_class.m_enabled && ! global_table_lock_class.m_enabled))
+ if (psi_unlikely(! flag_global_instrumentation))
{
destroy_table(pfs);
return NULL;
}
+ /* The table handle was already instrumented, reuse it for this thread. */
+ PFS_thread *thread= my_thread_get_THR_PFS();
pfs->m_thread_owner= thread;
+ if (thread != NULL)
+ pfs->m_owner_event_id= thread->m_event_id;
+ else
+ pfs->m_owner_event_id= 0;
return table;
}
- if (psi_unlikely(! flag_global_instrumentation))
- return NULL;
-
/* See open_table_v1() */
PFS_table_share *pfs_table_share= reinterpret_cast<PFS_table_share*> (share);
@@ -1716,7 +2045,10 @@ rebind_table_v1(PSI_table_share *share, const void *identity, PSI_table *table)
if (! global_table_io_class.m_enabled && ! global_table_lock_class.m_enabled)
return NULL;
- PFS_thread *thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+ if (! flag_global_instrumentation)
+ return NULL;
+
+ PFS_thread *thread= my_thread_get_THR_PFS();
if (unlikely(thread == NULL))
return NULL;
@@ -1728,31 +2060,29 @@ rebind_table_v1(PSI_table_share *share, const void *identity, PSI_table *table)
Implementation of the table instrumentation interface.
@sa PSI_v1::close_table.
*/
-static void close_table_v1(PSI_table *table)
+void pfs_close_table_v1(TABLE_SHARE *server_share, PSI_table *table)
{
PFS_table *pfs= reinterpret_cast<PFS_table*> (table);
if (unlikely(pfs == NULL))
return;
- pfs->aggregate();
+ pfs->aggregate(server_share);
destroy_table(pfs);
}
-static PSI_socket*
-init_socket_v1(PSI_socket_key key, const my_socket *fd,
- const struct sockaddr *addr, socklen_t addr_len)
+PSI_socket*
+pfs_init_socket_v1(PSI_socket_key key, const my_socket *fd,
+ const struct sockaddr *addr, socklen_t addr_len)
{
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)
+void pfs_destroy_socket_v1(PSI_socket *socket)
{
PFS_socket *pfs= reinterpret_cast<PFS_socket*> (socket);
@@ -1765,7 +2095,7 @@ static void destroy_socket_v1(PSI_socket *socket)
Implementation of the file instrumentation interface.
@sa PSI_v1::create_file.
*/
-static void create_file_v1(PSI_file_key key, const char *name, File file)
+void pfs_create_file_v1(PSI_file_key key, const char *name, File file)
{
if (psi_unlikely(! flag_global_instrumentation))
return;
@@ -1779,7 +2109,7 @@ static void create_file_v1(PSI_file_key key, const char *name, File file)
return;
/* A thread is needed for LF_PINS */
- PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+ PFS_thread *pfs_thread= my_thread_get_THR_PFS();
if (unlikely(pfs_thread == NULL))
return;
@@ -1821,7 +2151,7 @@ struct PFS_spawn_thread_arg
void *m_user_arg;
};
-void* pfs_spawn_thread(void *arg)
+extern "C" void* pfs_spawn_thread(void *arg)
{
PFS_spawn_thread_arg *typed_arg= (PFS_spawn_thread_arg*) arg;
void *user_arg;
@@ -1836,6 +2166,7 @@ void* pfs_spawn_thread(void *arg)
pfs= create_thread(klass, typed_arg->m_child_identity, 0);
if (likely(pfs != NULL))
{
+ pfs->m_thread_os_id= my_thread_os_id();
clear_thread_account(pfs);
pfs->m_parent_thread_internal_id= typed_arg->m_thread_internal_id;
@@ -1853,7 +2184,7 @@ void* pfs_spawn_thread(void *arg)
{
pfs= NULL;
}
- my_pthread_setspecific_ptr(THR_PFS, pfs);
+ my_thread_set_THR_PFS(pfs);
/*
Secondly, free the memory allocated in spawn_thread_v1().
@@ -1875,15 +2206,16 @@ void* pfs_spawn_thread(void *arg)
Implementation of the thread instrumentation interface.
@sa PSI_v1::spawn_thread.
*/
-static int spawn_thread_v1(PSI_thread_key key,
- pthread_t *thread, const pthread_attr_t *attr,
- void *(*start_routine)(void*), void *arg)
+int pfs_spawn_thread_v1(PSI_thread_key key,
+ my_thread_handle *thread, const my_thread_attr_t *attr,
+ void *(*start_routine)(void*), void *arg)
{
PFS_spawn_thread_arg *psi_arg;
PFS_thread *parent;
/* psi_arg can not be global, and can not be a local variable. */
- psi_arg= (PFS_spawn_thread_arg*) my_malloc(sizeof(PFS_spawn_thread_arg),
+ psi_arg= (PFS_spawn_thread_arg*) my_malloc(PSI_NOT_INSTRUMENTED,
+ sizeof(PFS_spawn_thread_arg),
MYF(MY_WME));
if (unlikely(psi_arg == NULL))
return EAGAIN;
@@ -1893,7 +2225,7 @@ static int spawn_thread_v1(PSI_thread_key key,
psi_arg->m_user_start_routine= start_routine;
psi_arg->m_user_arg= arg;
- parent= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+ parent= my_thread_get_THR_PFS();
if (parent != NULL)
{
/*
@@ -1916,7 +2248,7 @@ static int spawn_thread_v1(PSI_thread_key key,
psi_arg->m_hostname_length= 0;
}
- int result= pthread_create(thread, attr, pfs_spawn_thread, psi_arg);
+ int result= my_thread_create(thread, attr, pfs_spawn_thread, psi_arg);
if (unlikely(result != 0))
my_free(psi_arg);
return result;
@@ -1926,8 +2258,8 @@ static int spawn_thread_v1(PSI_thread_key key,
Implementation of the thread instrumentation interface.
@sa PSI_v1::new_thread.
*/
-static PSI_thread*
-new_thread_v1(PSI_thread_key key, const void *identity, ulonglong processlist_id)
+PSI_thread*
+pfs_new_thread_v1(PSI_thread_key key, const void *identity, ulonglong processlist_id)
{
PFS_thread *pfs;
@@ -1944,7 +2276,7 @@ new_thread_v1(PSI_thread_key key, const void *identity, ulonglong processlist_id
Implementation of the thread instrumentation interface.
@sa PSI_v1::set_thread_id.
*/
-static void set_thread_id_v1(PSI_thread *thread, ulonglong processlist_id)
+void pfs_set_thread_id_v1(PSI_thread *thread, ulonglong processlist_id)
{
PFS_thread *pfs= reinterpret_cast<PFS_thread*> (thread);
if (unlikely(pfs == NULL))
@@ -1954,12 +2286,36 @@ static void set_thread_id_v1(PSI_thread *thread, ulonglong processlist_id)
/**
Implementation of the thread instrumentation interface.
+ @sa PSI_v1::set_thread_THD.
+*/
+void pfs_set_thread_THD_v1(PSI_thread *thread, THD *thd)
+{
+ PFS_thread *pfs= reinterpret_cast<PFS_thread*> (thread);
+ if (unlikely(pfs == NULL))
+ return;
+ pfs->m_thd= thd;
+}
+
+/**
+ Implementation of the thread instrumentation interface.
+ @sa PSI_v1::set_thread_os_thread_id.
+*/
+void pfs_set_thread_os_id_v1(PSI_thread *thread)
+{
+ PFS_thread *pfs= reinterpret_cast<PFS_thread*> (thread);
+ if (unlikely(pfs == NULL))
+ return;
+ pfs->m_thread_os_id= my_thread_os_id();
+}
+
+/**
+ Implementation of the thread instrumentation interface.
@sa PSI_v1::get_thread_id.
*/
-static PSI_thread*
-get_thread_v1(void)
+PSI_thread*
+pfs_get_thread_v1(void)
{
- PFS_thread *pfs= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+ PFS_thread *pfs= my_thread_get_THR_PFS();
return reinterpret_cast<PSI_thread*> (pfs);
}
@@ -1967,9 +2323,10 @@ get_thread_v1(void)
Implementation of the thread instrumentation interface.
@sa PSI_v1::set_thread_user.
*/
-static void set_thread_user_v1(const char *user, int user_len)
+void pfs_set_thread_user_v1(const char *user, int user_len)
{
- PFS_thread *pfs= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+ pfs_dirty_state dirty_state;
+ PFS_thread *pfs= my_thread_get_THR_PFS();
DBUG_ASSERT((user != NULL) || (user_len == 0));
DBUG_ASSERT(user_len >= 0);
@@ -1980,7 +2337,7 @@ static void set_thread_user_v1(const char *user, int user_len)
aggregate_thread(pfs, pfs->m_account, pfs->m_user, pfs->m_host);
- pfs->m_session_lock.allocated_to_dirty();
+ pfs->m_session_lock.allocated_to_dirty(& dirty_state);
clear_thread_account(pfs);
@@ -1990,37 +2347,44 @@ static void set_thread_user_v1(const char *user, int user_len)
set_thread_account(pfs);
- bool enabled= true;
- if (flag_thread_instrumentation)
+ bool enabled;
+ bool history;
+ if (pfs->m_account != NULL)
+ {
+ enabled= pfs->m_account->m_enabled;
+ history= pfs->m_account->m_history;
+ }
+ else
{
if ((pfs->m_username_length > 0) && (pfs->m_hostname_length > 0))
{
- /*
- TODO: performance improvement.
- Once performance_schema.USERS is exposed,
- we can use PFS_user::m_enabled instead of looking up
- SETUP_ACTORS every time.
- */
lookup_setup_actor(pfs,
pfs->m_username, pfs->m_username_length,
pfs->m_hostname, pfs->m_hostname_length,
- &enabled);
+ &enabled, &history);
+ }
+ else
+ {
+ /* There is no setting for background threads */
+ enabled= true;
+ history= true;
}
}
+ pfs->set_enabled(enabled);
+ pfs->set_history(history);
- pfs->m_enabled= enabled;
-
- pfs->m_session_lock.dirty_to_allocated();
+ pfs->m_session_lock.dirty_to_allocated(& dirty_state);
}
/**
Implementation of the thread instrumentation interface.
@sa PSI_v1::set_thread_account.
*/
-static void set_thread_account_v1(const char *user, int user_len,
- const char *host, int host_len)
+void pfs_set_thread_account_v1(const char *user, int user_len,
+ const char *host, int host_len)
{
- PFS_thread *pfs= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+ pfs_dirty_state dirty_state;
+ PFS_thread *pfs= my_thread_get_THR_PFS();
DBUG_ASSERT((user != NULL) || (user_len == 0));
DBUG_ASSERT(user_len >= 0);
@@ -2033,7 +2397,7 @@ static void set_thread_account_v1(const char *user, int user_len,
if (unlikely(pfs == NULL))
return;
- pfs->m_session_lock.allocated_to_dirty();
+ pfs->m_session_lock.allocated_to_dirty(& dirty_state);
clear_thread_account(pfs);
@@ -2047,35 +2411,42 @@ static void set_thread_account_v1(const char *user, int user_len,
set_thread_account(pfs);
- bool enabled= true;
- if (flag_thread_instrumentation)
+ bool enabled;
+ bool history;
+ if (pfs->m_account != NULL)
+ {
+ enabled= pfs->m_account->m_enabled;
+ history= pfs->m_account->m_history;
+ }
+ else
{
if ((pfs->m_username_length > 0) && (pfs->m_hostname_length > 0))
{
- /*
- TODO: performance improvement.
- Once performance_schema.USERS is exposed,
- we can use PFS_user::m_enabled instead of looking up
- SETUP_ACTORS every time.
- */
lookup_setup_actor(pfs,
pfs->m_username, pfs->m_username_length,
pfs->m_hostname, pfs->m_hostname_length,
- &enabled);
+ &enabled, &history);
+ }
+ else
+ {
+ /* There is no setting for background threads */
+ enabled= true;
+ history= true;
}
}
- pfs->m_enabled= enabled;
+ pfs->set_enabled(enabled);
+ pfs->set_history(history);
- pfs->m_session_lock.dirty_to_allocated();
+ pfs->m_session_lock.dirty_to_allocated(& dirty_state);
}
/**
Implementation of the thread instrumentation interface.
@sa PSI_v1::set_thread_db.
*/
-static void set_thread_db_v1(const char* db, int db_len)
+void pfs_set_thread_db_v1(const char* db, int db_len)
{
- PFS_thread *pfs= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+ PFS_thread *pfs= my_thread_get_THR_PFS();
DBUG_ASSERT((db != NULL) || (db_len == 0));
DBUG_ASSERT(db_len >= 0);
@@ -2083,11 +2454,12 @@ static void set_thread_db_v1(const char* db, int db_len)
if (likely(pfs != NULL))
{
- pfs->m_stmt_lock.allocated_to_dirty();
+ pfs_dirty_state dirty_state;
+ pfs->m_stmt_lock.allocated_to_dirty(& dirty_state);
if (db_len > 0)
memcpy(pfs->m_dbname, db, db_len);
pfs->m_dbname_length= db_len;
- pfs->m_stmt_lock.dirty_to_allocated();
+ pfs->m_stmt_lock.dirty_to_allocated(& dirty_state);
}
}
@@ -2095,9 +2467,9 @@ static void set_thread_db_v1(const char* db, int db_len)
Implementation of the thread instrumentation interface.
@sa PSI_v1::set_thread_command.
*/
-static void set_thread_command_v1(int command)
+void pfs_set_thread_command_v1(int command)
{
- PFS_thread *pfs= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+ PFS_thread *pfs= my_thread_get_THR_PFS();
DBUG_ASSERT(command >= 0);
DBUG_ASSERT(command <= (int) COM_END);
@@ -2109,12 +2481,27 @@ static void set_thread_command_v1(int command)
}
/**
+Implementation of the thread instrumentation interface.
+@sa PSI_v1::set_thread_connection_type.
+*/
+void pfs_set_connection_type_v1(opaque_vio_type conn_type)
+{
+ PFS_thread *pfs= my_thread_get_THR_PFS();
+
+ if (likely(pfs != NULL))
+ {
+ pfs->m_connection_type= static_cast<enum_vio_type> (conn_type);
+ }
+}
+
+
+/**
Implementation of the thread instrumentation interface.
@sa PSI_v1::set_thread_start_time.
*/
-static void set_thread_start_time_v1(time_t start_time)
+void pfs_set_thread_start_time_v1(time_t start_time)
{
- PFS_thread *pfs= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+ PFS_thread *pfs= my_thread_get_THR_PFS();
if (likely(pfs != NULL))
{
@@ -2126,7 +2513,7 @@ static void set_thread_start_time_v1(time_t start_time)
Implementation of the thread instrumentation interface.
@sa PSI_v1::set_thread_state.
*/
-static void set_thread_state_v1(const char* state)
+void pfs_set_thread_state_v1(const char* state)
{
/* DEPRECATED. */
}
@@ -2135,9 +2522,10 @@ static void set_thread_state_v1(const char* state)
Implementation of the thread instrumentation interface.
@sa PSI_v1::set_thread_info.
*/
-static void set_thread_info_v1(const char* info, uint info_len)
+void pfs_set_thread_info_v1(const char* info, uint info_len)
{
- PFS_thread *pfs= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+ pfs_dirty_state dirty_state;
+ PFS_thread *pfs= my_thread_get_THR_PFS();
DBUG_ASSERT((info != NULL) || (info_len == 0));
@@ -2148,16 +2536,16 @@ static void set_thread_info_v1(const char* info, uint info_len)
if (info_len > sizeof(pfs->m_processlist_info))
info_len= sizeof(pfs->m_processlist_info);
- pfs->m_stmt_lock.allocated_to_dirty();
+ pfs->m_stmt_lock.allocated_to_dirty(& dirty_state);
memcpy(pfs->m_processlist_info, info, info_len);
pfs->m_processlist_info_length= info_len;
- pfs->m_stmt_lock.dirty_to_allocated();
+ pfs->m_stmt_lock.dirty_to_allocated(& dirty_state);
}
else
{
- pfs->m_stmt_lock.allocated_to_dirty();
+ pfs->m_stmt_lock.allocated_to_dirty(& dirty_state);
pfs->m_processlist_info_length= 0;
- pfs->m_stmt_lock.dirty_to_allocated();
+ pfs->m_stmt_lock.dirty_to_allocated(& dirty_state);
}
}
}
@@ -2166,23 +2554,23 @@ static void set_thread_info_v1(const char* info, uint info_len)
Implementation of the thread instrumentation interface.
@sa PSI_v1::set_thread.
*/
-static void set_thread_v1(PSI_thread* thread)
+void pfs_set_thread_v1(PSI_thread* thread)
{
PFS_thread *pfs= reinterpret_cast<PFS_thread*> (thread);
- my_pthread_setspecific_ptr(THR_PFS, pfs);
+ my_thread_set_THR_PFS(pfs);
}
/**
Implementation of the thread instrumentation interface.
@sa PSI_v1::delete_current_thread.
*/
-static void delete_current_thread_v1(void)
+void pfs_delete_current_thread_v1(void)
{
- PFS_thread *thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+ PFS_thread *thread= my_thread_get_THR_PFS();
if (thread != NULL)
{
aggregate_thread(thread, thread->m_account, thread->m_user, thread->m_host);
- my_pthread_setspecific_ptr(THR_PFS, NULL);
+ my_thread_set_THR_PFS(NULL);
destroy_thread(thread);
}
}
@@ -2191,7 +2579,7 @@ static void delete_current_thread_v1(void)
Implementation of the thread instrumentation interface.
@sa PSI_v1::delete_thread.
*/
-static void delete_thread_v1(PSI_thread *thread)
+void pfs_delete_thread_v1(PSI_thread *thread)
{
PFS_thread *pfs= reinterpret_cast<PFS_thread*> (thread);
@@ -2206,10 +2594,10 @@ static void delete_thread_v1(PSI_thread *thread)
Implementation of the mutex instrumentation interface.
@sa PSI_v1::start_mutex_wait.
*/
-static PSI_mutex_locker*
-start_mutex_wait_v1(PSI_mutex_locker_state *state,
- PSI_mutex *mutex, PSI_mutex_operation op,
- const char *src_file, uint src_line)
+PSI_mutex_locker*
+pfs_start_mutex_wait_v1(PSI_mutex_locker_state *state,
+ PSI_mutex *mutex, PSI_mutex_operation op,
+ const char *src_file, uint src_line)
{
PFS_mutex *pfs_mutex= reinterpret_cast<PFS_mutex*> (mutex);
DBUG_ASSERT((int) op >= 0);
@@ -2227,7 +2615,7 @@ start_mutex_wait_v1(PSI_mutex_locker_state *state,
if (flag_thread_instrumentation)
{
- PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+ PFS_thread *pfs_thread= my_thread_get_THR_PFS();
if (unlikely(pfs_thread == NULL))
return NULL;
if (! pfs_thread->m_enabled)
@@ -2259,7 +2647,7 @@ start_mutex_wait_v1(PSI_mutex_locker_state *state,
wait->m_nesting_event_id= parent_event->m_event_id;
wait->m_nesting_event_type= parent_event->m_event_type;
- wait->m_thread= pfs_thread;
+ wait->m_thread_internal_id= pfs_thread->m_thread_internal_id;
wait->m_class= pfs_mutex->m_class;
wait->m_timer_start= timer_start;
wait->m_timer_end= 0;
@@ -2304,11 +2692,11 @@ start_mutex_wait_v1(PSI_mutex_locker_state *state,
@sa PSI_v1::start_rwlock_rdwait
@sa PSI_v1::start_rwlock_wrwait
*/
-static PSI_rwlock_locker*
-start_rwlock_wait_v1(PSI_rwlock_locker_state *state,
- PSI_rwlock *rwlock,
- PSI_rwlock_operation op,
- const char *src_file, uint src_line)
+PSI_rwlock_locker*
+pfs_start_rwlock_wait_v1(PSI_rwlock_locker_state *state,
+ PSI_rwlock *rwlock,
+ PSI_rwlock_operation op,
+ const char *src_file, uint src_line)
{
PFS_rwlock *pfs_rwlock= reinterpret_cast<PFS_rwlock*> (rwlock);
DBUG_ASSERT(static_cast<int> (op) >= 0);
@@ -2317,6 +2705,26 @@ start_rwlock_wait_v1(PSI_rwlock_locker_state *state,
DBUG_ASSERT(pfs_rwlock != NULL);
DBUG_ASSERT(pfs_rwlock->m_class != NULL);
+ /* Operations supported for READ WRITE LOCK */
+
+ DBUG_ASSERT( pfs_rwlock->m_class->is_shared_exclusive()
+ || (op == PSI_RWLOCK_READLOCK)
+ || (op == PSI_RWLOCK_WRITELOCK)
+ || (op == PSI_RWLOCK_TRYREADLOCK)
+ || (op == PSI_RWLOCK_TRYWRITELOCK)
+ );
+
+ /* Operations supported for SHARED EXCLUSIVE LOCK */
+
+ DBUG_ASSERT( ! pfs_rwlock->m_class->is_shared_exclusive()
+ || (op == PSI_RWLOCK_SHAREDLOCK)
+ || (op == PSI_RWLOCK_SHAREDEXCLUSIVELOCK)
+ || (op == PSI_RWLOCK_EXCLUSIVELOCK)
+ || (op == PSI_RWLOCK_TRYSHAREDLOCK)
+ || (op == PSI_RWLOCK_TRYSHAREDEXCLUSIVELOCK)
+ || (op == PSI_RWLOCK_TRYEXCLUSIVELOCK)
+ );
+
if (! pfs_rwlock->m_enabled)
return NULL;
@@ -2325,7 +2733,7 @@ start_rwlock_wait_v1(PSI_rwlock_locker_state *state,
if (flag_thread_instrumentation)
{
- PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+ PFS_thread *pfs_thread= my_thread_get_THR_PFS();
if (unlikely(pfs_thread == NULL))
return NULL;
if (! pfs_thread->m_enabled)
@@ -2357,7 +2765,7 @@ start_rwlock_wait_v1(PSI_rwlock_locker_state *state,
wait->m_nesting_event_id= parent_event->m_event_id;
wait->m_nesting_event_type= parent_event->m_event_type;
- wait->m_thread= pfs_thread;
+ wait->m_thread_internal_id= pfs_thread->m_thread_internal_id;
wait->m_class= pfs_rwlock->m_class;
wait->m_timer_start= timer_start;
wait->m_timer_end= 0;
@@ -2394,18 +2802,49 @@ start_rwlock_wait_v1(PSI_rwlock_locker_state *state,
state->m_flags= flags;
state->m_rwlock= rwlock;
+ state->m_operation= op;
return reinterpret_cast<PSI_rwlock_locker*> (state);
}
+PSI_rwlock_locker*
+pfs_start_rwlock_rdwait_v1(PSI_rwlock_locker_state *state,
+ PSI_rwlock *rwlock,
+ PSI_rwlock_operation op,
+ const char *src_file, uint src_line)
+{
+ DBUG_ASSERT((op == PSI_RWLOCK_READLOCK) ||
+ (op == PSI_RWLOCK_TRYREADLOCK) ||
+ (op == PSI_RWLOCK_SHAREDLOCK) ||
+ (op == PSI_RWLOCK_TRYSHAREDLOCK));
+
+ return pfs_start_rwlock_wait_v1(state, rwlock, op, src_file, src_line);
+}
+
+PSI_rwlock_locker*
+pfs_start_rwlock_wrwait_v1(PSI_rwlock_locker_state *state,
+ PSI_rwlock *rwlock,
+ PSI_rwlock_operation op,
+ const char *src_file, uint src_line)
+{
+ DBUG_ASSERT((op == PSI_RWLOCK_WRITELOCK) ||
+ (op == PSI_RWLOCK_TRYWRITELOCK) ||
+ (op == PSI_RWLOCK_SHAREDEXCLUSIVELOCK) ||
+ (op == PSI_RWLOCK_TRYSHAREDEXCLUSIVELOCK) ||
+ (op == PSI_RWLOCK_EXCLUSIVELOCK) ||
+ (op == PSI_RWLOCK_TRYEXCLUSIVELOCK));
+
+ return pfs_start_rwlock_wait_v1(state, rwlock, op, src_file, src_line);
+}
+
/**
Implementation of the cond instrumentation interface.
@sa PSI_v1::start_cond_wait.
*/
-static PSI_cond_locker*
-start_cond_wait_v1(PSI_cond_locker_state *state,
- PSI_cond *cond, PSI_mutex *mutex,
- PSI_cond_operation op,
- const char *src_file, uint src_line)
+PSI_cond_locker*
+pfs_start_cond_wait_v1(PSI_cond_locker_state *state,
+ PSI_cond *cond, PSI_mutex *mutex,
+ PSI_cond_operation op,
+ const char *src_file, uint src_line)
{
/*
Note about the unused PSI_mutex *mutex parameter:
@@ -2433,7 +2872,7 @@ start_cond_wait_v1(PSI_cond_locker_state *state,
if (flag_thread_instrumentation)
{
- PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+ PFS_thread *pfs_thread= my_thread_get_THR_PFS();
if (unlikely(pfs_thread == NULL))
return NULL;
if (! pfs_thread->m_enabled)
@@ -2465,7 +2904,7 @@ start_cond_wait_v1(PSI_cond_locker_state *state,
wait->m_nesting_event_id= parent_event->m_event_id;
wait->m_nesting_event_type= parent_event->m_event_type;
- wait->m_thread= pfs_thread;
+ wait->m_thread_internal_id= pfs_thread->m_thread_internal_id;
wait->m_class= pfs_cond->m_class;
wait->m_timer_start= timer_start;
wait->m_timer_end= 0;
@@ -2523,8 +2962,6 @@ static inline PFS_TL_LOCK_TYPE lock_flags_to_lock_type(uint flags)
return PFS_TL_WRITE_ALLOW_WRITE;
case TL_WRITE_CONCURRENT_INSERT:
return PFS_TL_WRITE_CONCURRENT_INSERT;
- case TL_WRITE_DELAYED:
- return PFS_TL_WRITE_DELAYED;
case TL_WRITE_LOW_PRIORITY:
return PFS_TL_WRITE_LOW_PRIORITY;
case TL_WRITE:
@@ -2553,12 +2990,12 @@ static inline PFS_TL_LOCK_TYPE external_lock_flags_to_lock_type(uint flags)
Implementation of the table instrumentation interface.
@sa PSI_v1::start_table_io_wait_v1
*/
-static PSI_table_locker*
-start_table_io_wait_v1(PSI_table_locker_state *state,
- PSI_table *table,
- PSI_table_io_operation op,
- uint index,
- const char *src_file, uint src_line)
+PSI_table_locker*
+pfs_start_table_io_wait_v1(PSI_table_locker_state *state,
+ PSI_table *table,
+ PSI_table_io_operation op,
+ uint index,
+ const char *src_file, uint src_line)
{
DBUG_ASSERT(static_cast<int> (op) >= 0);
DBUG_ASSERT(static_cast<uint> (op) < array_elements(table_io_operation_map));
@@ -2570,7 +3007,7 @@ start_table_io_wait_v1(PSI_table_locker_state *state,
if (! pfs_table->m_io_enabled)
return NULL;
- PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+ PFS_thread *pfs_thread= my_thread_get_THR_PFS();
uint flags;
ulonglong timer_start= 0;
@@ -2609,7 +3046,7 @@ start_table_io_wait_v1(PSI_table_locker_state *state,
wait->m_nesting_event_type= parent_event->m_event_type;
PFS_table_share *share= pfs_table->m_share;
- wait->m_thread= pfs_thread;
+ wait->m_thread_internal_id= pfs_thread->m_thread_internal_id;
wait->m_class= &global_table_io_class;
wait->m_timer_start= timer_start;
wait->m_timer_end= 0;
@@ -2655,12 +3092,12 @@ start_table_io_wait_v1(PSI_table_locker_state *state,
Implementation of the table instrumentation interface.
@sa PSI_v1::start_table_lock_wait.
*/
-static PSI_table_locker*
-start_table_lock_wait_v1(PSI_table_locker_state *state,
- PSI_table *table,
- PSI_table_lock_operation op,
- ulong op_flags,
- const char *src_file, uint src_line)
+PSI_table_locker*
+pfs_start_table_lock_wait_v1(PSI_table_locker_state *state,
+ PSI_table *table,
+ PSI_table_lock_operation op,
+ ulong op_flags,
+ const char *src_file, uint src_line)
{
DBUG_ASSERT(state != NULL);
DBUG_ASSERT((op == PSI_TABLE_LOCK) || (op == PSI_TABLE_EXTERNAL_LOCK));
@@ -2673,7 +3110,7 @@ start_table_lock_wait_v1(PSI_table_locker_state *state,
if (! pfs_table->m_lock_enabled)
return NULL;
- PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+ PFS_thread *pfs_thread= my_thread_get_THR_PFS();
PFS_TL_LOCK_TYPE lock_type;
@@ -2681,6 +3118,7 @@ start_table_lock_wait_v1(PSI_table_locker_state *state,
{
case PSI_TABLE_LOCK:
lock_type= lock_flags_to_lock_type(op_flags);
+ pfs_table->m_internal_lock= lock_type;
break;
case PSI_TABLE_EXTERNAL_LOCK:
/*
@@ -2688,8 +3126,12 @@ start_table_lock_wait_v1(PSI_table_locker_state *state,
there is no handler::external_unlock().
*/
if (op_flags == F_UNLCK)
+ {
+ pfs_table->m_external_lock= PFS_TL_NONE;
return NULL;
+ }
lock_type= external_lock_flags_to_lock_type(op_flags);
+ pfs_table->m_external_lock= lock_type;
break;
default:
lock_type= PFS_TL_READ;
@@ -2735,7 +3177,7 @@ start_table_lock_wait_v1(PSI_table_locker_state *state,
wait->m_nesting_event_type= parent_event->m_event_type;
PFS_table_share *share= pfs_table->m_share;
- wait->m_thread= pfs_thread;
+ wait->m_thread_internal_id= pfs_thread->m_thread_internal_id;
wait->m_class= &global_table_lock_class;
wait->m_timer_start= timer_start;
wait->m_timer_end= 0;
@@ -2780,11 +3222,11 @@ start_table_lock_wait_v1(PSI_table_locker_state *state,
Implementation of the file instrumentation interface.
@sa PSI_v1::get_thread_file_name_locker.
*/
-static PSI_file_locker*
-get_thread_file_name_locker_v1(PSI_file_locker_state *state,
- PSI_file_key key,
- PSI_file_operation op,
- const char *name, const void *identity)
+PSI_file_locker*
+pfs_get_thread_file_name_locker_v1(PSI_file_locker_state *state,
+ PSI_file_key key,
+ PSI_file_operation op,
+ const char *name, const void *identity)
{
DBUG_ASSERT(static_cast<int> (op) >= 0);
DBUG_ASSERT(static_cast<uint> (op) < array_elements(file_operation_map));
@@ -2799,7 +3241,7 @@ get_thread_file_name_locker_v1(PSI_file_locker_state *state,
return NULL;
/* Needed for the LF_HASH */
- PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+ PFS_thread *pfs_thread= my_thread_get_THR_PFS();
if (unlikely(pfs_thread == NULL))
return NULL;
@@ -2831,7 +3273,7 @@ get_thread_file_name_locker_v1(PSI_file_locker_state *state,
wait->m_nesting_event_id= parent_event->m_event_id;
wait->m_nesting_event_type= parent_event->m_event_type;
- wait->m_thread= pfs_thread;
+ wait->m_thread_internal_id= pfs_thread->m_thread_internal_id;
wait->m_class= klass;
wait->m_timer_start= 0;
wait->m_timer_end= 0;
@@ -2858,9 +3300,9 @@ get_thread_file_name_locker_v1(PSI_file_locker_state *state,
Implementation of the file instrumentation interface.
@sa PSI_v1::get_thread_file_stream_locker.
*/
-static PSI_file_locker*
-get_thread_file_stream_locker_v1(PSI_file_locker_state *state,
- PSI_file *file, PSI_file_operation op)
+PSI_file_locker*
+pfs_get_thread_file_stream_locker_v1(PSI_file_locker_state *state,
+ PSI_file *file, PSI_file_operation op)
{
PFS_file *pfs_file= reinterpret_cast<PFS_file*> (file);
DBUG_ASSERT(static_cast<int> (op) >= 0);
@@ -2875,16 +3317,20 @@ get_thread_file_stream_locker_v1(PSI_file_locker_state *state,
if (! pfs_file->m_enabled)
return NULL;
+ /* Needed for the LF_HASH */
+ PFS_thread *pfs_thread= my_thread_get_THR_PFS();
+ if (unlikely(pfs_thread == NULL))
+ return NULL;
+
uint flags;
+ /* Always populated */
+ state->m_thread= reinterpret_cast<PSI_thread *> (pfs_thread);
+
if (flag_thread_instrumentation)
{
- PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
- if (unlikely(pfs_thread == NULL))
- return NULL;
if (! pfs_thread->m_enabled)
return NULL;
- state->m_thread= reinterpret_cast<PSI_thread *> (pfs_thread);
flags= STATE_FLAG_THREAD;
if (pfs_file->m_timed)
@@ -2907,7 +3353,7 @@ get_thread_file_stream_locker_v1(PSI_file_locker_state *state,
wait->m_nesting_event_id= parent_event->m_event_id;
wait->m_nesting_event_type= parent_event->m_event_type;
- wait->m_thread= pfs_thread;
+ wait->m_thread_internal_id= pfs_thread->m_thread_internal_id;
wait->m_class= klass;
wait->m_timer_start= 0;
wait->m_timer_end= 0;
@@ -2924,7 +3370,6 @@ get_thread_file_stream_locker_v1(PSI_file_locker_state *state,
}
else
{
- state->m_thread= NULL;
if (pfs_file->m_timed)
{
flags= STATE_FLAG_TIMED;
@@ -2948,9 +3393,9 @@ get_thread_file_stream_locker_v1(PSI_file_locker_state *state,
Implementation of the file instrumentation interface.
@sa PSI_v1::get_thread_file_descriptor_locker.
*/
-static PSI_file_locker*
-get_thread_file_descriptor_locker_v1(PSI_file_locker_state *state,
- File file, PSI_file_operation op)
+PSI_file_locker*
+pfs_get_thread_file_descriptor_locker_v1(PSI_file_locker_state *state,
+ File file, PSI_file_operation op)
{
int index= static_cast<int> (file);
DBUG_ASSERT(static_cast<int> (op) >= 0);
@@ -2981,16 +3426,20 @@ get_thread_file_descriptor_locker_v1(PSI_file_locker_state *state,
DBUG_ASSERT(pfs_file->m_class != NULL);
PFS_file_class *klass= pfs_file->m_class;
+ /* Needed for the LF_HASH */
+ PFS_thread *pfs_thread= my_thread_get_THR_PFS();
+ if (unlikely(pfs_thread == NULL))
+ return NULL;
+
uint flags;
+ /* Always populated */
+ state->m_thread= reinterpret_cast<PSI_thread *> (pfs_thread);
+
if (flag_thread_instrumentation)
{
- PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
- if (unlikely(pfs_thread == NULL))
- return NULL;
if (! pfs_thread->m_enabled)
return NULL;
- state->m_thread= reinterpret_cast<PSI_thread *> (pfs_thread);
flags= STATE_FLAG_THREAD;
if (pfs_file->m_timed)
@@ -3013,7 +3462,7 @@ get_thread_file_descriptor_locker_v1(PSI_file_locker_state *state,
wait->m_nesting_event_id= parent_event->m_event_id;
wait->m_nesting_event_type= parent_event->m_event_type;
- wait->m_thread= pfs_thread;
+ wait->m_thread_internal_id= pfs_thread->m_thread_internal_id;
wait->m_class= klass;
wait->m_timer_start= 0;
wait->m_timer_end= 0;
@@ -3030,7 +3479,6 @@ get_thread_file_descriptor_locker_v1(PSI_file_locker_state *state,
}
else
{
- state->m_thread= NULL;
if (pfs_file->m_timed)
{
flags= STATE_FLAG_TIMED;
@@ -3052,12 +3500,12 @@ get_thread_file_descriptor_locker_v1(PSI_file_locker_state *state,
/** Socket locker */
-static PSI_socket_locker*
-start_socket_wait_v1(PSI_socket_locker_state *state,
- PSI_socket *socket,
- PSI_socket_operation op,
- size_t count,
- const char *src_file, uint src_line)
+PSI_socket_locker*
+pfs_start_socket_wait_v1(PSI_socket_locker_state *state,
+ PSI_socket *socket,
+ PSI_socket_operation op,
+ size_t count,
+ const char *src_file, uint src_line)
{
DBUG_ASSERT(static_cast<int> (op) >= 0);
DBUG_ASSERT(static_cast<uint> (op) < array_elements(socket_operation_map));
@@ -3080,7 +3528,7 @@ start_socket_wait_v1(PSI_socket_locker_state *state,
as different threads may use concurrently the same socket,
for example during a KILL.
*/
- PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+ PFS_thread *pfs_thread= my_thread_get_THR_PFS();
if (unlikely(pfs_thread == NULL))
return NULL;
@@ -3114,7 +3562,7 @@ start_socket_wait_v1(PSI_socket_locker_state *state,
wait->m_event_type= EVENT_TYPE_WAIT;
wait->m_nesting_event_id= parent_event->m_event_id;
wait->m_nesting_event_type= parent_event->m_event_type;
- wait->m_thread= pfs_thread;
+ wait->m_thread_internal_id= pfs_thread->m_thread_internal_id;
wait->m_class= pfs_socket->m_class;
wait->m_timer_start= timer_start;
wait->m_timer_end= 0;
@@ -3177,7 +3625,7 @@ start_socket_wait_v1(PSI_socket_locker_state *state,
Implementation of the mutex instrumentation interface.
@sa PSI_v1::unlock_mutex.
*/
-static void unlock_mutex_v1(PSI_mutex *mutex)
+void pfs_unlock_mutex_v1(PSI_mutex *mutex)
{
PFS_mutex *pfs_mutex= reinterpret_cast<PFS_mutex*> (mutex);
@@ -3214,7 +3662,7 @@ static void unlock_mutex_v1(PSI_mutex *mutex)
Implementation of the rwlock instrumentation interface.
@sa PSI_v1::unlock_rwlock.
*/
-static void unlock_rwlock_v1(PSI_rwlock *rwlock)
+void pfs_unlock_rwlock_v1(PSI_rwlock *rwlock)
{
PFS_rwlock *pfs_rwlock= reinterpret_cast<PFS_rwlock*> (rwlock);
DBUG_ASSERT(pfs_rwlock != NULL);
@@ -3292,34 +3740,38 @@ static void unlock_rwlock_v1(PSI_rwlock *rwlock)
Implementation of the cond instrumentation interface.
@sa PSI_v1::signal_cond.
*/
-static void signal_cond_v1(PSI_cond* cond)
+void pfs_signal_cond_v1(PSI_cond* cond)
{
+#ifdef PFS_LATER
PFS_cond *pfs_cond= reinterpret_cast<PFS_cond*> (cond);
DBUG_ASSERT(pfs_cond != NULL);
pfs_cond->m_cond_stat.m_signal_count++;
+#endif
}
/**
Implementation of the cond instrumentation interface.
@sa PSI_v1::broadcast_cond.
*/
-static void broadcast_cond_v1(PSI_cond* cond)
+void pfs_broadcast_cond_v1(PSI_cond* cond)
{
+#ifdef PFS_LATER
PFS_cond *pfs_cond= reinterpret_cast<PFS_cond*> (cond);
DBUG_ASSERT(pfs_cond != NULL);
pfs_cond->m_cond_stat.m_broadcast_count++;
+#endif
}
/**
Implementation of the idle instrumentation interface.
@sa PSI_v1::start_idle_wait.
*/
-static PSI_idle_locker*
-start_idle_wait_v1(PSI_idle_locker_state* state, const char *src_file, uint src_line)
+PSI_idle_locker*
+pfs_start_idle_wait_v1(PSI_idle_locker_state* state, const char *src_file, uint src_line)
{
DBUG_ASSERT(state != NULL);
@@ -3334,7 +3786,7 @@ start_idle_wait_v1(PSI_idle_locker_state* state, const char *src_file, uint src_
if (flag_thread_instrumentation)
{
- PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+ PFS_thread *pfs_thread= my_thread_get_THR_PFS();
if (unlikely(pfs_thread == NULL))
return NULL;
if (!pfs_thread->m_enabled)
@@ -3372,7 +3824,7 @@ start_idle_wait_v1(PSI_idle_locker_state* state, const char *src_file, uint src_
wait->m_nesting_event_id= 0;
/* no need to set wait->m_nesting_event_type */
- wait->m_thread= pfs_thread;
+ wait->m_thread_internal_id= pfs_thread->m_thread_internal_id;
wait->m_class= &global_idle_class;
wait->m_timer_start= timer_start;
wait->m_timer_end= 0;
@@ -3404,7 +3856,7 @@ start_idle_wait_v1(PSI_idle_locker_state* state, const char *src_file, uint src_
Implementation of the mutex instrumentation interface.
@sa PSI_v1::end_idle_wait.
*/
-static void end_idle_wait_v1(PSI_idle_locker* locker)
+void pfs_end_idle_wait_v1(PSI_idle_locker* locker)
{
PSI_idle_locker_state *state= reinterpret_cast<PSI_idle_locker_state*> (locker);
DBUG_ASSERT(state != NULL);
@@ -3423,7 +3875,7 @@ 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;
+ event_name_array= thread->write_instr_class_waits_stats();
if (flags & STATE_FLAG_TIMED)
{
@@ -3443,9 +3895,9 @@ static void end_idle_wait_v1(PSI_idle_locker* locker)
wait->m_timer_end= timer_end;
wait->m_end_event_id= thread->m_event_id;
- if (flag_events_waits_history)
+ if (thread->m_flag_events_waits_history)
insert_events_waits_history(thread, wait);
- if (flag_events_waits_history_long)
+ if (thread->m_flag_events_waits_history_long)
insert_events_waits_history_long(wait);
thread->m_events_waits_current--;
@@ -3469,7 +3921,7 @@ static void end_idle_wait_v1(PSI_idle_locker* locker)
Implementation of the mutex instrumentation interface.
@sa PSI_v1::end_mutex_wait.
*/
-static void end_mutex_wait_v1(PSI_mutex_locker* locker, int rc)
+void pfs_end_mutex_wait_v1(PSI_mutex_locker* locker, int rc)
{
PSI_mutex_locker_state *state= reinterpret_cast<PSI_mutex_locker_state*> (locker);
DBUG_ASSERT(state != NULL);
@@ -3505,9 +3957,12 @@ static void end_mutex_wait_v1(PSI_mutex_locker* locker, int rc)
if (flags & STATE_FLAG_THREAD)
{
PFS_single_stat *event_name_array;
- event_name_array= thread->m_instr_class_waits_stats;
+ event_name_array= thread->write_instr_class_waits_stats();
uint index= mutex->m_class->m_event_name_index;
+ DBUG_ASSERT(index <= wait_class_max);
+ DBUG_ASSERT(sanitize_thread(thread) != NULL);
+
if (flags & STATE_FLAG_TIMED)
{
/* Aggregate to EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME (timed) */
@@ -3526,9 +3981,9 @@ static void end_mutex_wait_v1(PSI_mutex_locker* locker, int rc)
wait->m_timer_end= timer_end;
wait->m_end_event_id= thread->m_event_id;
- if (flag_events_waits_history)
+ if (thread->m_flag_events_waits_history)
insert_events_waits_history(thread, wait);
- if (flag_events_waits_history_long)
+ if (thread->m_flag_events_waits_history_long)
insert_events_waits_history_long(wait);
thread->m_events_waits_current--;
@@ -3541,7 +3996,7 @@ static void end_mutex_wait_v1(PSI_mutex_locker* locker, int rc)
Implementation of the rwlock instrumentation interface.
@sa PSI_v1::end_rwlock_rdwait.
*/
-static void end_rwlock_rdwait_v1(PSI_rwlock_locker* locker, int rc)
+void pfs_end_rwlock_rdwait_v1(PSI_rwlock_locker* locker, int rc)
{
PSI_rwlock_locker_state *state= reinterpret_cast<PSI_rwlock_locker_state*> (locker);
DBUG_ASSERT(state != NULL);
@@ -3586,7 +4041,7 @@ static void end_rwlock_rdwait_v1(PSI_rwlock_locker* locker, int rc)
DBUG_ASSERT(thread != NULL);
PFS_single_stat *event_name_array;
- event_name_array= thread->m_instr_class_waits_stats;
+ event_name_array= thread->write_instr_class_waits_stats();
uint index= rwlock->m_class->m_event_name_index;
if (state->m_flags & STATE_FLAG_TIMED)
@@ -3607,9 +4062,9 @@ static void end_rwlock_rdwait_v1(PSI_rwlock_locker* locker, int rc)
wait->m_timer_end= timer_end;
wait->m_end_event_id= thread->m_event_id;
- if (flag_events_waits_history)
+ if (thread->m_flag_events_waits_history)
insert_events_waits_history(thread, wait);
- if (flag_events_waits_history_long)
+ if (thread->m_flag_events_waits_history_long)
insert_events_waits_history_long(wait);
thread->m_events_waits_current--;
@@ -3622,7 +4077,7 @@ static void end_rwlock_rdwait_v1(PSI_rwlock_locker* locker, int rc)
Implementation of the rwlock instrumentation interface.
@sa PSI_v1::end_rwlock_wrwait.
*/
-static void end_rwlock_wrwait_v1(PSI_rwlock_locker* locker, int rc)
+void pfs_end_rwlock_wrwait_v1(PSI_rwlock_locker* locker, int rc)
{
PSI_rwlock_locker_state *state= reinterpret_cast<PSI_rwlock_locker_state*> (locker);
DBUG_ASSERT(state != NULL);
@@ -3652,15 +4107,20 @@ static void end_rwlock_wrwait_v1(PSI_rwlock_locker* locker, int rc)
/* Thread safe : we are protected by the instrumented rwlock */
rwlock->m_writer= thread;
rwlock->m_last_written= timer_end;
- /* Reset the readers stats, they could be off */
- rwlock->m_readers= 0;
- rwlock->m_last_read= 0;
+
+ if ((state->m_operation != PSI_RWLOCK_SHAREDEXCLUSIVELOCK) &&
+ (state->m_operation != PSI_RWLOCK_TRYSHAREDEXCLUSIVELOCK))
+ {
+ /* Reset the readers stats, they could be off */
+ rwlock->m_readers= 0;
+ rwlock->m_last_read= 0;
+ }
}
if (state->m_flags & STATE_FLAG_THREAD)
{
PFS_single_stat *event_name_array;
- event_name_array= thread->m_instr_class_waits_stats;
+ event_name_array= thread->write_instr_class_waits_stats();
uint index= rwlock->m_class->m_event_name_index;
if (state->m_flags & STATE_FLAG_TIMED)
@@ -3681,9 +4141,9 @@ static void end_rwlock_wrwait_v1(PSI_rwlock_locker* locker, int rc)
wait->m_timer_end= timer_end;
wait->m_end_event_id= thread->m_event_id;
- if (flag_events_waits_history)
+ if (thread->m_flag_events_waits_history)
insert_events_waits_history(thread, wait);
- if (flag_events_waits_history_long)
+ if (thread->m_flag_events_waits_history_long)
insert_events_waits_history_long(wait);
thread->m_events_waits_current--;
@@ -3696,7 +4156,7 @@ static void end_rwlock_wrwait_v1(PSI_rwlock_locker* locker, int rc)
Implementation of the cond instrumentation interface.
@sa PSI_v1::end_cond_wait.
*/
-static void end_cond_wait_v1(PSI_cond_locker* locker, int rc)
+void pfs_end_cond_wait_v1(PSI_cond_locker* locker, int rc)
{
PSI_cond_locker_state *state= reinterpret_cast<PSI_cond_locker_state*> (locker);
DBUG_ASSERT(state != NULL);
@@ -3726,7 +4186,7 @@ static void end_cond_wait_v1(PSI_cond_locker* locker, int rc)
DBUG_ASSERT(thread != NULL);
PFS_single_stat *event_name_array;
- event_name_array= thread->m_instr_class_waits_stats;
+ event_name_array= thread->write_instr_class_waits_stats();
uint index= cond->m_class->m_event_name_index;
if (state->m_flags & STATE_FLAG_TIMED)
@@ -3747,9 +4207,9 @@ static void end_cond_wait_v1(PSI_cond_locker* locker, int rc)
wait->m_timer_end= timer_end;
wait->m_end_event_id= thread->m_event_id;
- if (flag_events_waits_history)
+ if (thread->m_flag_events_waits_history)
insert_events_waits_history(thread, wait);
- if (flag_events_waits_history_long)
+ if (thread->m_flag_events_waits_history_long)
insert_events_waits_history_long(wait);
thread->m_events_waits_current--;
@@ -3762,7 +4222,7 @@ static void end_cond_wait_v1(PSI_cond_locker* locker, int rc)
Implementation of the table instrumentation interface.
@sa PSI_v1::end_table_io_wait.
*/
-static void end_table_io_wait_v1(PSI_table_locker* locker)
+void pfs_end_table_io_wait_v1(PSI_table_locker* locker, ulonglong numrows)
{
PSI_table_locker_state *state= reinterpret_cast<PSI_table_locker_state*> (locker);
DBUG_ASSERT(state != NULL);
@@ -3808,11 +4268,11 @@ static void end_table_io_wait_v1(PSI_table_locker* locker)
{
timer_end= state->m_timer();
wait_time= timer_end - state->m_timer_start;
- stat->aggregate_value(wait_time);
+ stat->aggregate_many_value(wait_time, numrows);
}
else
{
- stat->aggregate_counted();
+ stat->aggregate_counted(numrows);
}
if (flags & STATE_FLAG_THREAD)
@@ -3821,7 +4281,7 @@ static void end_table_io_wait_v1(PSI_table_locker* locker)
DBUG_ASSERT(thread != NULL);
PFS_single_stat *event_name_array;
- event_name_array= thread->m_instr_class_waits_stats;
+ event_name_array= thread->write_instr_class_waits_stats();
/*
Aggregate to EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME
@@ -3829,11 +4289,11 @@ static void end_table_io_wait_v1(PSI_table_locker* locker)
*/
if (flags & STATE_FLAG_TIMED)
{
- event_name_array[GLOBAL_TABLE_IO_EVENT_INDEX].aggregate_value(wait_time);
+ event_name_array[GLOBAL_TABLE_IO_EVENT_INDEX].aggregate_many_value(wait_time, numrows);
}
else
{
- event_name_array[GLOBAL_TABLE_IO_EVENT_INDEX].aggregate_counted();
+ event_name_array[GLOBAL_TABLE_IO_EVENT_INDEX].aggregate_counted(numrows);
}
if (flags & STATE_FLAG_EVENT)
@@ -3843,9 +4303,10 @@ static void end_table_io_wait_v1(PSI_table_locker* locker)
wait->m_timer_end= timer_end;
wait->m_end_event_id= thread->m_event_id;
- if (flag_events_waits_history)
+ wait->m_number_of_bytes= static_cast<size_t>(numrows);
+ if (thread->m_flag_events_waits_history)
insert_events_waits_history(thread, wait);
- if (flag_events_waits_history_long)
+ if (thread->m_flag_events_waits_history_long)
insert_events_waits_history_long(wait);
thread->m_events_waits_current--;
@@ -3860,7 +4321,7 @@ static void end_table_io_wait_v1(PSI_table_locker* locker)
Implementation of the table instrumentation interface.
@sa PSI_v1::end_table_lock_wait.
*/
-static void end_table_lock_wait_v1(PSI_table_locker* locker)
+void pfs_end_table_lock_wait_v1(PSI_table_locker* locker)
{
PSI_table_locker_state *state= reinterpret_cast<PSI_table_locker_state*> (locker);
DBUG_ASSERT(state != NULL);
@@ -3892,7 +4353,7 @@ static void end_table_lock_wait_v1(PSI_table_locker* locker)
DBUG_ASSERT(thread != NULL);
PFS_single_stat *event_name_array;
- event_name_array= thread->m_instr_class_waits_stats;
+ event_name_array= thread->write_instr_class_waits_stats();
/*
Aggregate to EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME
@@ -3914,9 +4375,9 @@ static void end_table_lock_wait_v1(PSI_table_locker* locker)
wait->m_timer_end= timer_end;
wait->m_end_event_id= thread->m_event_id;
- if (flag_events_waits_history)
+ if (thread->m_flag_events_waits_history)
insert_events_waits_history(thread, wait);
- if (flag_events_waits_history_long)
+ if (thread->m_flag_events_waits_history_long)
insert_events_waits_history_long(wait);
thread->m_events_waits_current--;
@@ -3927,23 +4388,23 @@ static void end_table_lock_wait_v1(PSI_table_locker* locker)
table->m_has_lock_stats= true;
}
-static void start_file_wait_v1(PSI_file_locker *locker,
- size_t count,
- const char *src_file,
- uint src_line);
+void pfs_start_file_wait_v1(PSI_file_locker *locker,
+ size_t count,
+ const char *src_file,
+ uint src_line);
-static void end_file_wait_v1(PSI_file_locker *locker,
- size_t count);
+void pfs_end_file_wait_v1(PSI_file_locker *locker,
+ size_t count);
/**
Implementation of the file instrumentation interface.
@sa PSI_v1::start_file_open_wait.
*/
-static void start_file_open_wait_v1(PSI_file_locker *locker,
- const char *src_file,
- uint src_line)
+void pfs_start_file_open_wait_v1(PSI_file_locker *locker,
+ const char *src_file,
+ uint src_line)
{
- start_file_wait_v1(locker, 0, src_file, src_line);
+ pfs_start_file_wait_v1(locker, 0, src_file, src_line);
return;
}
@@ -3952,8 +4413,9 @@ static void start_file_open_wait_v1(PSI_file_locker *locker,
Implementation of the file instrumentation interface.
@sa PSI_v1::end_file_open_wait.
*/
-static PSI_file* end_file_open_wait_v1(PSI_file_locker *locker,
- void *result)
+PSI_file*
+pfs_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);
@@ -3981,7 +4443,7 @@ static PSI_file* end_file_open_wait_v1(PSI_file_locker *locker,
break;
}
- end_file_wait_v1(locker, 0);
+ pfs_end_file_wait_v1(locker, 0);
return state->m_file;
}
@@ -3990,7 +4452,7 @@ static PSI_file* end_file_open_wait_v1(PSI_file_locker *locker,
Implementation of the file instrumentation interface.
@sa PSI_v1::end_file_open_wait_and_bind_to_descriptor.
*/
-static void end_file_open_wait_and_bind_to_descriptor_v1
+void pfs_end_file_open_wait_and_bind_to_descriptor_v1
(PSI_file_locker *locker, File file)
{
PFS_file *pfs_file= NULL;
@@ -4008,7 +4470,7 @@ static void end_file_open_wait_and_bind_to_descriptor_v1
state->m_file= reinterpret_cast<PSI_file*> (pfs_file);
}
- end_file_wait_v1(locker, 0);
+ pfs_end_file_wait_v1(locker, 0);
if (likely(index >= 0))
{
@@ -4025,12 +4487,35 @@ static void end_file_open_wait_and_bind_to_descriptor_v1
/**
Implementation of the file instrumentation interface.
+ @sa PSI_v1::end_temp_file_open_wait_and_bind_to_descriptor.
+*/
+void pfs_end_temp_file_open_wait_and_bind_to_descriptor_v1
+ (PSI_file_locker *locker, File file, const char *filename)
+{
+ DBUG_ASSERT(filename != NULL);
+ PSI_file_locker_state *state= reinterpret_cast<PSI_file_locker_state*> (locker);
+ DBUG_ASSERT(state != NULL);
+
+ /* Set filename that was generated during creation of temporary file. */
+ state->m_name= filename;
+ pfs_end_file_open_wait_and_bind_to_descriptor_v1(locker, file);
+
+ PFS_file *pfs_file= reinterpret_cast<PFS_file *> (state->m_file);
+ if (pfs_file != NULL)
+ {
+ pfs_file->m_temporary= true;
+ }
+}
+
+
+/**
+ Implementation of the file instrumentation interface.
@sa PSI_v1::start_file_wait.
*/
-static void start_file_wait_v1(PSI_file_locker *locker,
- size_t count,
- const char *src_file,
- uint src_line)
+void pfs_start_file_wait_v1(PSI_file_locker *locker,
+ size_t count,
+ const char *src_file,
+ uint src_line)
{
ulonglong timer_start= 0;
PSI_file_locker_state *state= reinterpret_cast<PSI_file_locker_state*> (locker);
@@ -4060,8 +4545,8 @@ static void start_file_wait_v1(PSI_file_locker *locker,
Implementation of the file instrumentation interface.
@sa PSI_v1::end_file_wait.
*/
-static void end_file_wait_v1(PSI_file_locker *locker,
- size_t byte_count)
+void pfs_end_file_wait_v1(PSI_file_locker *locker,
+ size_t byte_count)
{
PSI_file_locker_state *state= reinterpret_cast<PSI_file_locker_state*> (locker);
DBUG_ASSERT(state != NULL);
@@ -4139,7 +4624,7 @@ static void end_file_wait_v1(PSI_file_locker *locker,
DBUG_ASSERT(thread != NULL);
PFS_single_stat *event_name_array;
- event_name_array= thread->m_instr_class_waits_stats;
+ event_name_array= thread->write_instr_class_waits_stats();
uint index= klass->m_event_name_index;
if (flags & STATE_FLAG_TIMED)
@@ -4165,9 +4650,9 @@ static void end_file_wait_v1(PSI_file_locker *locker,
wait->m_weak_file= file;
wait->m_weak_version= (file ? file->get_version() : 0);
- if (flag_events_waits_history)
+ if (thread->m_flag_events_waits_history)
insert_events_waits_history(thread, wait);
- if (flag_events_waits_history_long)
+ if (thread->m_flag_events_waits_history_long)
insert_events_waits_history_long(wait);
thread->m_events_waits_current--;
@@ -4180,9 +4665,9 @@ static void end_file_wait_v1(PSI_file_locker *locker,
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)
+void pfs_start_file_close_wait_v1(PSI_file_locker *locker,
+ const char *src_file,
+ uint src_line)
{
PFS_thread *thread;
const char *name;
@@ -4208,7 +4693,7 @@ static void start_file_close_wait_v1(PSI_file_locker *locker,
break;
}
- start_file_wait_v1(locker, 0, src_file, src_line);
+ pfs_start_file_wait_v1(locker, 0, src_file, src_line);
return;
}
@@ -4217,12 +4702,12 @@ static void start_file_close_wait_v1(PSI_file_locker *locker,
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)
+void pfs_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);
+ pfs_end_file_wait_v1(locker, 0);
if (rc == 0)
{
@@ -4233,6 +4718,17 @@ static void end_file_close_wait_v1(PSI_file_locker *locker, int rc)
switch(state->m_operation)
{
case PSI_FILE_CLOSE:
+ if (file != NULL)
+ {
+ if (file->m_temporary)
+ {
+ DBUG_ASSERT(file->m_file_stat.m_open_count <= 1);
+ destroy_file(thread, file);
+ }
+ else
+ release_file(file);
+ }
+ break;
case PSI_FILE_STREAM_CLOSE:
if (file != NULL)
release_file(file);
@@ -4249,22 +4745,50 @@ static void end_file_close_wait_v1(PSI_file_locker *locker, int rc)
return;
}
-static void start_stage_v1(PSI_stage_key key, const char *src_file, int src_line)
+/**
+ Implementation of the file instrumentation interface.
+ @sa PSI_v1::end_file_rename_wait.
+*/
+void pfs_end_file_rename_wait_v1(PSI_file_locker *locker, const char *old_name,
+ const char *new_name, int rc)
+{
+ PSI_file_locker_state *state= reinterpret_cast<PSI_file_locker_state*> (locker);
+ DBUG_ASSERT(state != NULL);
+ DBUG_ASSERT(state->m_operation == PSI_FILE_RENAME);
+
+ if (rc == 0)
+ {
+ PFS_thread *thread= reinterpret_cast<PFS_thread *> (state->m_thread);
+
+ uint old_len= (uint)strlen(old_name);
+ uint new_len= (uint)strlen(new_name);
+
+ find_and_rename_file(thread, old_name, old_len, new_name, new_len);
+ }
+
+ pfs_end_file_wait_v1(locker, 0);
+ return;
+}
+
+PSI_stage_progress*
+pfs_start_stage_v1(PSI_stage_key key, const char *src_file, int src_line)
{
ulonglong timer_value= 0;
- PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+ PFS_thread *pfs_thread= my_thread_get_THR_PFS();
if (unlikely(pfs_thread == NULL))
- return;
+ return NULL;
/* Always update column threads.processlist_state. */
pfs_thread->m_stage= key;
+ /* Default value when the stage is not instrumented for progress */
+ pfs_thread->m_stage_progress= NULL;
if (psi_unlikely(! flag_global_instrumentation))
- return;
+ return NULL;
if (flag_thread_instrumentation && ! pfs_thread->m_enabled)
- return;
+ return NULL;
PFS_events_stages *pfs= & pfs_thread->m_stage_current;
PFS_events_waits *child_wait= & pfs_thread->m_events_waits_stack[0];
@@ -4274,7 +4798,7 @@ static void start_stage_v1(PSI_stage_key key, const char *src_file, int src_line
if (old_class != NULL)
{
PFS_stage_stat *event_name_array;
- event_name_array= pfs_thread->m_instr_class_stages_stats;
+ event_name_array= pfs_thread->write_instr_class_stages_stats();
uint index= old_class->m_event_name_index;
/* Finish old event */
@@ -4296,9 +4820,9 @@ static void start_stage_v1(PSI_stage_key key, const char *src_file, int src_line
if (flag_events_stages_current)
{
pfs->m_end_event_id= pfs_thread->m_event_id;
- if (flag_events_stages_history)
+ if (pfs_thread->m_flag_events_stages_history)
insert_events_stages_history(pfs_thread, pfs);
- if (flag_events_stages_history_long)
+ if (pfs_thread->m_flag_events_stages_history_long)
insert_events_stages_history_long(pfs);
}
@@ -4315,10 +4839,10 @@ static void start_stage_v1(PSI_stage_key key, const char *src_file, int src_line
PFS_stage_class *new_klass= find_stage_class(key);
if (unlikely(new_klass == NULL))
- return;
+ return NULL;
if (! new_klass->m_enabled)
- return;
+ return NULL;
pfs->m_class= new_klass;
if (new_klass->m_timed)
@@ -4337,8 +4861,7 @@ static void start_stage_v1(PSI_stage_key key, const char *src_file, int src_line
if (flag_events_stages_current)
{
- /* m_thread_internal_id is immutable and already set */
- DBUG_ASSERT(pfs->m_thread_internal_id == pfs_thread->m_thread_internal_id);
+ pfs->m_thread_internal_id= pfs_thread->m_thread_internal_id;
pfs->m_event_id= pfs_thread->m_event_id++;
pfs->m_end_event_id= 0;
pfs->m_source_file= src_file;
@@ -4348,17 +4871,37 @@ static void start_stage_v1(PSI_stage_key key, const char *src_file, int src_line
child_wait->m_event_id= pfs->m_event_id;
child_wait->m_event_type= EVENT_TYPE_STAGE;
}
+
+ if (new_klass->is_progress())
+ {
+ pfs_thread->m_stage_progress= & pfs->m_progress;
+ pfs->m_progress.m_work_completed= 0;
+ pfs->m_progress.m_work_estimated= 0;
+ }
+
+ return pfs_thread->m_stage_progress;
}
-static void end_stage_v1()
+PSI_stage_progress*
+pfs_get_current_stage_progress_v1()
+{
+ PFS_thread *pfs_thread= my_thread_get_THR_PFS();
+ if (unlikely(pfs_thread == NULL))
+ return NULL;
+
+ return pfs_thread->m_stage_progress;
+}
+
+void pfs_end_stage_v1()
{
ulonglong timer_value= 0;
- PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+ PFS_thread *pfs_thread= my_thread_get_THR_PFS();
if (unlikely(pfs_thread == NULL))
return;
pfs_thread->m_stage= 0;
+ pfs_thread->m_stage_progress= NULL;
if (psi_unlikely(! flag_global_instrumentation))
return;
@@ -4372,7 +4915,7 @@ static void end_stage_v1()
if (old_class != NULL)
{
PFS_stage_stat *event_name_array;
- event_name_array= pfs_thread->m_instr_class_stages_stats;
+ event_name_array= pfs_thread->write_instr_class_stages_stats();
uint index= old_class->m_event_name_index;
/* Finish old event */
@@ -4394,9 +4937,9 @@ static void end_stage_v1()
if (flag_events_stages_current)
{
pfs->m_end_event_id= pfs_thread->m_event_id;
- if (flag_events_stages_history)
+ if (pfs_thread->m_flag_events_stages_history)
insert_events_stages_history(pfs_thread, pfs);
- if (flag_events_stages_history_long)
+ if (pfs_thread->m_flag_events_stages_history_long)
insert_events_stages_history_long(pfs);
}
@@ -4411,10 +4954,10 @@ static void end_stage_v1()
}
}
-static PSI_statement_locker*
-get_thread_statement_locker_v1(PSI_statement_locker_state *state,
- PSI_statement_key key,
- const void *charset)
+PSI_statement_locker*
+pfs_get_thread_statement_locker_v1(PSI_statement_locker_state *state,
+ PSI_statement_key key,
+ const void *charset, PSI_sp_share *sp_share)
{
DBUG_ASSERT(state != NULL);
DBUG_ASSERT(charset != NULL);
@@ -4431,7 +4974,7 @@ get_thread_statement_locker_v1(PSI_statement_locker_state *state,
if (flag_thread_instrumentation)
{
- PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+ PFS_thread *pfs_thread= my_thread_get_THR_PFS();
if (unlikely(pfs_thread == NULL))
return NULL;
if (! pfs_thread->m_enabled)
@@ -4448,14 +4991,16 @@ get_thread_statement_locker_v1(PSI_statement_locker_state *state,
if (pfs_thread->m_events_statements_count >= statement_stack_max)
{
+ nested_statement_lost++;
return NULL;
}
- pfs_thread->m_stmt_lock.allocated_to_dirty();
+ pfs_dirty_state dirty_state;
+ pfs_thread->m_stmt_lock.allocated_to_dirty(& dirty_state);
PFS_events_statements *pfs= & pfs_thread->m_statement_stack[pfs_thread->m_events_statements_count];
- /* m_thread_internal_id is immutable and already set */
- DBUG_ASSERT(pfs->m_thread_internal_id == pfs_thread->m_thread_internal_id);
+ pfs->m_thread_internal_id= pfs_thread->m_thread_internal_id;
pfs->m_event_id= event_id;
+ pfs->m_event_type= EVENT_TYPE_STATEMENT;
pfs->m_end_event_id= 0;
pfs->m_class= klass;
pfs->m_timer_start= 0;
@@ -4497,18 +5042,68 @@ get_thread_statement_locker_v1(PSI_statement_locker_state *state,
/* New waits will have this statement as parent, if no stage is instrumented */
PFS_events_waits *child_wait= & pfs_thread->m_events_waits_stack[0];
- child_wait->m_nesting_event_id= event_id;
- child_wait->m_nesting_event_type= EVENT_TYPE_STATEMENT;
+ child_wait->m_event_id= event_id;
+ child_wait->m_event_type= EVENT_TYPE_STATEMENT;
+
+ PFS_events_statements *parent_statement= NULL;
+ PFS_events_transactions *parent_transaction= &pfs_thread->m_transaction_current;
+ ulonglong parent_event= 0;
+ enum_event_type parent_type= EVENT_TYPE_STATEMENT;
+ uint parent_level= 0;
+
+ if (pfs_thread->m_events_statements_count > 0)
+ {
+ parent_statement= pfs - 1;
+ parent_event= parent_statement->m_event_id;
+ parent_type= parent_statement->m_event_type;
+ parent_level= parent_statement->m_nesting_event_level + 1;
+ }
+
+ if (parent_transaction->m_state == TRANS_STATE_ACTIVE &&
+ parent_transaction->m_event_id > parent_event)
+ {
+ parent_event= parent_transaction->m_event_id;
+ parent_type= parent_transaction->m_event_type;
+ }
+
+ pfs->m_nesting_event_id= parent_event;
+ pfs->m_nesting_event_type= parent_type;
+ pfs->m_nesting_event_level= parent_level;
+
+ /* Set parent Stored Procedure information for this statement. */
+ if(sp_share)
+ {
+ PFS_program *parent_sp= reinterpret_cast<PFS_program*>(sp_share);
+ pfs->m_sp_type= parent_sp->m_type;
+ memcpy(pfs->m_schema_name, parent_sp->m_schema_name,
+ parent_sp->m_schema_name_length);
+ pfs->m_schema_name_length= parent_sp->m_schema_name_length;
+ memcpy(pfs->m_object_name, parent_sp->m_object_name,
+ parent_sp->m_object_name_length);
+ pfs->m_object_name_length= parent_sp->m_object_name_length;
+ }
+ else
+ {
+ pfs->m_sp_type= NO_OBJECT_TYPE;
+ pfs->m_schema_name_length= 0;
+ pfs->m_object_name_length= 0;
+ }
state->m_statement= pfs;
flags|= STATE_FLAG_EVENT;
pfs_thread->m_events_statements_count++;
- pfs_thread->m_stmt_lock.dirty_to_allocated();
+ pfs_thread->m_stmt_lock.dirty_to_allocated(& dirty_state);
+ }
+ else
+ {
+ state->m_statement= NULL;
}
}
else
{
+ state->m_statement= NULL;
+
if (klass->m_timed)
flags= STATE_FLAG_TIMED;
else
@@ -4542,16 +5137,18 @@ get_thread_statement_locker_v1(PSI_statement_locker_state *state,
state->m_no_good_index_used= 0;
state->m_digest= NULL;
+ state->m_cs_number= ((CHARSET_INFO *)charset)->number;
state->m_schema_name_length= 0;
- state->m_cs_number= ((CHARSET_INFO *)charset)->number;
+ state->m_parent_sp_share= sp_share;
+ state->m_parent_prepared_stmt= NULL;
return reinterpret_cast<PSI_statement_locker*> (state);
}
-static PSI_statement_locker*
-refine_statement_v1(PSI_statement_locker *locker,
- PSI_statement_key key)
+PSI_statement_locker*
+pfs_refine_statement_v1(PSI_statement_locker *locker,
+ PSI_statement_key key)
{
PSI_statement_locker_state *state= reinterpret_cast<PSI_statement_locker_state*> (locker);
if (state == NULL)
@@ -4597,9 +5194,9 @@ refine_statement_v1(PSI_statement_locker *locker,
return reinterpret_cast<PSI_statement_locker*> (state);
}
-static void start_statement_v1(PSI_statement_locker *locker,
- const char *db, uint db_len,
- const char *src_file, uint src_line)
+void pfs_start_statement_v1(PSI_statement_locker *locker,
+ const char *db, uint db_len,
+ const char *src_file, uint src_line)
{
PSI_statement_locker_state *state= reinterpret_cast<PSI_statement_locker_state*> (locker);
DBUG_ASSERT(state != NULL);
@@ -4636,8 +5233,8 @@ static void start_statement_v1(PSI_statement_locker *locker,
}
}
-static void set_statement_text_v1(PSI_statement_locker *locker,
- const char *text, uint text_len)
+void pfs_set_statement_text_v1(PSI_statement_locker *locker,
+ const char *text, uint text_len)
{
PSI_statement_locker_state *state= reinterpret_cast<PSI_statement_locker_state*> (locker);
DBUG_ASSERT(state != NULL);
@@ -4649,9 +5246,9 @@ static void set_statement_text_v1(PSI_statement_locker *locker,
{
PFS_events_statements *pfs= reinterpret_cast<PFS_events_statements*> (state->m_statement);
DBUG_ASSERT(pfs != NULL);
- if (text_len > sizeof (pfs->m_sqltext))
+ if (text_len > pfs_max_sqltext)
{
- text_len= sizeof(pfs->m_sqltext);
+ text_len= (uint)pfs_max_sqltext;
pfs->m_sqltext_truncated= true;
}
if (text_len)
@@ -4697,101 +5294,101 @@ static void set_statement_text_v1(PSI_statement_locker *locker,
} \
return;
-static void set_statement_lock_time_v1(PSI_statement_locker *locker,
- ulonglong count)
+void pfs_set_statement_lock_time_v1(PSI_statement_locker *locker,
+ ulonglong count)
{
SET_STATEMENT_ATTR_BODY(locker, m_lock_time, count);
}
-static void set_statement_rows_sent_v1(PSI_statement_locker *locker,
- ulonglong count)
+void pfs_set_statement_rows_sent_v1(PSI_statement_locker *locker,
+ ulonglong count)
{
SET_STATEMENT_ATTR_BODY(locker, m_rows_sent, count);
}
-static void set_statement_rows_examined_v1(PSI_statement_locker *locker,
- ulonglong count)
+void pfs_set_statement_rows_examined_v1(PSI_statement_locker *locker,
+ ulonglong count)
{
SET_STATEMENT_ATTR_BODY(locker, m_rows_examined, count);
}
-static void inc_statement_created_tmp_disk_tables_v1(PSI_statement_locker *locker,
- ulong count)
+void pfs_inc_statement_created_tmp_disk_tables_v1(PSI_statement_locker *locker,
+ ulong count)
{
INC_STATEMENT_ATTR_BODY(locker, m_created_tmp_disk_tables, count);
}
-static void inc_statement_created_tmp_tables_v1(PSI_statement_locker *locker,
- ulong count)
+void pfs_inc_statement_created_tmp_tables_v1(PSI_statement_locker *locker,
+ ulong count)
{
INC_STATEMENT_ATTR_BODY(locker, m_created_tmp_tables, count);
}
-static void inc_statement_select_full_join_v1(PSI_statement_locker *locker,
- ulong count)
+void pfs_inc_statement_select_full_join_v1(PSI_statement_locker *locker,
+ ulong count)
{
INC_STATEMENT_ATTR_BODY(locker, m_select_full_join, count);
}
-static void inc_statement_select_full_range_join_v1(PSI_statement_locker *locker,
- ulong count)
+void pfs_inc_statement_select_full_range_join_v1(PSI_statement_locker *locker,
+ ulong count)
{
INC_STATEMENT_ATTR_BODY(locker, m_select_full_range_join, count);
}
-static void inc_statement_select_range_v1(PSI_statement_locker *locker,
- ulong count)
+void pfs_inc_statement_select_range_v1(PSI_statement_locker *locker,
+ ulong count)
{
INC_STATEMENT_ATTR_BODY(locker, m_select_range, count);
}
-static void inc_statement_select_range_check_v1(PSI_statement_locker *locker,
- ulong count)
+void pfs_inc_statement_select_range_check_v1(PSI_statement_locker *locker,
+ ulong count)
{
INC_STATEMENT_ATTR_BODY(locker, m_select_range_check, count);
}
-static void inc_statement_select_scan_v1(PSI_statement_locker *locker,
- ulong count)
+void pfs_inc_statement_select_scan_v1(PSI_statement_locker *locker,
+ ulong count)
{
INC_STATEMENT_ATTR_BODY(locker, m_select_scan, count);
}
-static void inc_statement_sort_merge_passes_v1(PSI_statement_locker *locker,
- ulong count)
+void pfs_inc_statement_sort_merge_passes_v1(PSI_statement_locker *locker,
+ ulong count)
{
INC_STATEMENT_ATTR_BODY(locker, m_sort_merge_passes, count);
}
-static void inc_statement_sort_range_v1(PSI_statement_locker *locker,
- ulong count)
+void pfs_inc_statement_sort_range_v1(PSI_statement_locker *locker,
+ ulong count)
{
INC_STATEMENT_ATTR_BODY(locker, m_sort_range, count);
}
-static void inc_statement_sort_rows_v1(PSI_statement_locker *locker,
- ulong count)
+void pfs_inc_statement_sort_rows_v1(PSI_statement_locker *locker,
+ ulong count)
{
INC_STATEMENT_ATTR_BODY(locker, m_sort_rows, count);
}
-static void inc_statement_sort_scan_v1(PSI_statement_locker *locker,
- ulong count)
+void pfs_inc_statement_sort_scan_v1(PSI_statement_locker *locker,
+ ulong count)
{
INC_STATEMENT_ATTR_BODY(locker, m_sort_scan, count);
}
-static void set_statement_no_index_used_v1(PSI_statement_locker *locker)
+void pfs_set_statement_no_index_used_v1(PSI_statement_locker *locker)
{
SET_STATEMENT_ATTR_BODY(locker, m_no_index_used, 1);
}
-static void set_statement_no_good_index_used_v1(PSI_statement_locker *locker)
+void pfs_set_statement_no_good_index_used_v1(PSI_statement_locker *locker)
{
SET_STATEMENT_ATTR_BODY(locker, m_no_good_index_used, 1);
}
-static void end_statement_v1(PSI_statement_locker *locker, void *stmt_da)
+void pfs_end_statement_v1(PSI_statement_locker *locker, void *stmt_da)
{
PSI_statement_locker_state *state= reinterpret_cast<PSI_statement_locker_state*> (locker);
Diagnostics_area *da= reinterpret_cast<Diagnostics_area*> (stmt_da);
@@ -4823,12 +5420,14 @@ static void end_statement_v1(PSI_statement_locker *locker, void *stmt_da)
*/
const sql_digest_storage *digest_storage= NULL;
PFS_statement_stat *digest_stat= NULL;
+ PFS_program *pfs_program= NULL;
+ PFS_prepared_stmt *pfs_prepared_stmt= NULL;
if (flags & STATE_FLAG_THREAD)
{
PFS_thread *thread= reinterpret_cast<PFS_thread *> (state->m_thread);
DBUG_ASSERT(thread != NULL);
- event_name_array= thread->m_instr_class_statements_stats;
+ event_name_array= thread->write_instr_class_statements_stats();
/* Aggregate to EVENTS_STATEMENTS_SUMMARY_BY_THREAD_BY_EVENT_NAME */
stat= & event_name_array[index];
@@ -4850,7 +5449,8 @@ static void end_statement_v1(PSI_statement_locker *locker, void *stmt_da)
PFS_events_statements *pfs= reinterpret_cast<PFS_events_statements*> (state->m_statement);
DBUG_ASSERT(pfs != NULL);
- thread->m_stmt_lock.allocated_to_dirty();
+ pfs_dirty_state dirty_state;
+ thread->m_stmt_lock.allocated_to_dirty(& dirty_state);
switch(da->status())
{
@@ -4858,7 +5458,8 @@ static void end_statement_v1(PSI_statement_locker *locker, void *stmt_da)
case Diagnostics_area::DA_EMPTY:
break;
case Diagnostics_area::DA_OK:
- memcpy(pfs->m_message_text, da->message(), MYSQL_ERRMSG_SIZE);
+ memcpy(pfs->m_message_text, da->message(),
+ MYSQL_ERRMSG_SIZE);
pfs->m_message_text[MYSQL_ERRMSG_SIZE]= 0;
pfs->m_rows_affected= da->affected_rows();
pfs->m_warning_count= da->statement_warn_count();
@@ -4868,11 +5469,12 @@ static void end_statement_v1(PSI_statement_locker *locker, void *stmt_da)
pfs->m_warning_count= da->statement_warn_count();
break;
case Diagnostics_area::DA_ERROR:
- memcpy(pfs->m_message_text, da->message(), MYSQL_ERRMSG_SIZE);
+ memcpy(pfs->m_message_text, da->message(),
+ MYSQL_ERRMSG_SIZE);
pfs->m_message_text[MYSQL_ERRMSG_SIZE]= 0;
pfs->m_sql_errno= da->sql_errno();
- pfs->m_error_count++;
memcpy(pfs->m_sqlstate, da->get_sqlstate(), SQLSTATE_LENGTH);
+ pfs->m_error_count++;
break;
case Diagnostics_area::DA_DISABLED:
break;
@@ -4892,21 +5494,24 @@ static void end_statement_v1(PSI_statement_locker *locker, void *stmt_da)
pfs->m_digest_storage.copy(digest_storage);
}
- if (flag_events_statements_history)
+ pfs_program= reinterpret_cast<PFS_program*>(state->m_parent_sp_share);
+ pfs_prepared_stmt= reinterpret_cast<PFS_prepared_stmt*>(state->m_parent_prepared_stmt);
+
+ if (thread->m_flag_events_statements_history)
insert_events_statements_history(thread, pfs);
- if (flag_events_statements_history_long)
+ if (thread->m_flag_events_statements_history_long)
insert_events_statements_history_long(pfs);
DBUG_ASSERT(thread->m_events_statements_count > 0);
thread->m_events_statements_count--;
- thread->m_stmt_lock.dirty_to_allocated();
+ thread->m_stmt_lock.dirty_to_allocated(& dirty_state);
}
}
else
{
if (flags & STATE_FLAG_DIGEST)
{
- PFS_thread *thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+ PFS_thread *thread= my_thread_get_THR_PFS();
/* An instrumented thread is required, for LF_PINS. */
if (thread != NULL)
@@ -4929,6 +5534,8 @@ static void end_statement_v1(PSI_statement_locker *locker, void *stmt_da)
stat= & event_name_array[index];
}
+ stat->mark_used();
+
if (flags & STATE_FLAG_TIMED)
{
/* Aggregate to EVENTS_STATEMENTS_SUMMARY_..._BY_EVENT_NAME (timed) */
@@ -4959,6 +5566,8 @@ static void end_statement_v1(PSI_statement_locker *locker, void *stmt_da)
if (digest_stat != NULL)
{
+ digest_stat->mark_used();
+
if (flags & STATE_FLAG_TIMED)
{
digest_stat->aggregate_value(wait_time);
@@ -4986,6 +5595,103 @@ static void end_statement_v1(PSI_statement_locker *locker, void *stmt_da)
digest_stat->m_no_good_index_used+= state->m_no_good_index_used;
}
+ if(pfs_program != NULL)
+ {
+ PFS_statement_stat *sub_stmt_stat= NULL;
+ sub_stmt_stat= &pfs_program->m_stmt_stat;
+ if(sub_stmt_stat != NULL)
+ {
+ sub_stmt_stat->mark_used();
+
+ if (flags & STATE_FLAG_TIMED)
+ {
+ sub_stmt_stat->aggregate_value(wait_time);
+ }
+ else
+ {
+ sub_stmt_stat->aggregate_counted();
+ }
+
+ sub_stmt_stat->m_lock_time+= state->m_lock_time;
+ sub_stmt_stat->m_rows_sent+= state->m_rows_sent;
+ sub_stmt_stat->m_rows_examined+= state->m_rows_examined;
+ sub_stmt_stat->m_created_tmp_disk_tables+= state->m_created_tmp_disk_tables;
+ sub_stmt_stat->m_created_tmp_tables+= state->m_created_tmp_tables;
+ sub_stmt_stat->m_select_full_join+= state->m_select_full_join;
+ sub_stmt_stat->m_select_full_range_join+= state->m_select_full_range_join;
+ sub_stmt_stat->m_select_range+= state->m_select_range;
+ sub_stmt_stat->m_select_range_check+= state->m_select_range_check;
+ sub_stmt_stat->m_select_scan+= state->m_select_scan;
+ sub_stmt_stat->m_sort_merge_passes+= state->m_sort_merge_passes;
+ sub_stmt_stat->m_sort_range+= state->m_sort_range;
+ sub_stmt_stat->m_sort_rows+= state->m_sort_rows;
+ sub_stmt_stat->m_sort_scan+= state->m_sort_scan;
+ sub_stmt_stat->m_no_index_used+= state->m_no_index_used;
+ sub_stmt_stat->m_no_good_index_used+= state->m_no_good_index_used;
+ }
+ }
+
+ if (pfs_prepared_stmt != NULL)
+ {
+ if(state->m_in_prepare)
+ {
+ PFS_single_stat *prepared_stmt_stat= NULL;
+ prepared_stmt_stat= &pfs_prepared_stmt->m_prepare_stat;
+ if(prepared_stmt_stat != NULL)
+ {
+ if (flags & STATE_FLAG_TIMED)
+ {
+ prepared_stmt_stat->aggregate_value(wait_time);
+ }
+ else
+ {
+ prepared_stmt_stat->aggregate_counted();
+ }
+ }
+ }
+ else
+ {
+ PFS_statement_stat *prepared_stmt_stat= NULL;
+ prepared_stmt_stat= &pfs_prepared_stmt->m_execute_stat;
+ if(prepared_stmt_stat != NULL)
+ {
+ if (flags & STATE_FLAG_TIMED)
+ {
+ prepared_stmt_stat->aggregate_value(wait_time);
+ }
+ else
+ {
+ prepared_stmt_stat->aggregate_counted();
+ }
+
+ prepared_stmt_stat->m_lock_time+= state->m_lock_time;
+ prepared_stmt_stat->m_rows_sent+= state->m_rows_sent;
+ prepared_stmt_stat->m_rows_examined+= state->m_rows_examined;
+ prepared_stmt_stat->m_created_tmp_disk_tables+= state->m_created_tmp_disk_tables;
+ prepared_stmt_stat->m_created_tmp_tables+= state->m_created_tmp_tables;
+ prepared_stmt_stat->m_select_full_join+= state->m_select_full_join;
+ prepared_stmt_stat->m_select_full_range_join+= state->m_select_full_range_join;
+ prepared_stmt_stat->m_select_range+= state->m_select_range;
+ prepared_stmt_stat->m_select_range_check+= state->m_select_range_check;
+ prepared_stmt_stat->m_select_scan+= state->m_select_scan;
+ prepared_stmt_stat->m_sort_merge_passes+= state->m_sort_merge_passes;
+ prepared_stmt_stat->m_sort_range+= state->m_sort_range;
+ prepared_stmt_stat->m_sort_rows+= state->m_sort_rows;
+ prepared_stmt_stat->m_sort_scan+= state->m_sort_scan;
+ prepared_stmt_stat->m_no_index_used+= state->m_no_index_used;
+ prepared_stmt_stat->m_no_good_index_used+= state->m_no_good_index_used;
+ }
+ }
+ }
+
+ PFS_statement_stat *sub_stmt_stat= NULL;
+ if (pfs_program != NULL)
+ sub_stmt_stat= &pfs_program->m_stmt_stat;
+
+ PFS_statement_stat *prepared_stmt_stat= NULL;
+ if (pfs_prepared_stmt != NULL && !state->m_in_prepare)
+ prepared_stmt_stat= &pfs_prepared_stmt->m_execute_stat;
+
switch (da->status())
{
case Diagnostics_area::DA_OK_BULK:
@@ -4999,6 +5705,16 @@ static void end_statement_v1(PSI_statement_locker *locker, void *stmt_da)
digest_stat->m_rows_affected+= da->affected_rows();
digest_stat->m_warning_count+= da->statement_warn_count();
}
+ if(sub_stmt_stat != NULL)
+ {
+ sub_stmt_stat->m_rows_affected+= da->affected_rows();
+ sub_stmt_stat->m_warning_count+= da->statement_warn_count();
+ }
+ if (prepared_stmt_stat != NULL)
+ {
+ prepared_stmt_stat->m_rows_affected+= da->affected_rows();
+ prepared_stmt_stat->m_warning_count+= da->statement_warn_count();
+ }
break;
case Diagnostics_area::DA_EOF:
stat->m_warning_count+= da->statement_warn_count();
@@ -5006,6 +5722,14 @@ static void end_statement_v1(PSI_statement_locker *locker, void *stmt_da)
{
digest_stat->m_warning_count+= da->statement_warn_count();
}
+ if(sub_stmt_stat != NULL)
+ {
+ sub_stmt_stat->m_warning_count+= da->statement_warn_count();
+ }
+ if (prepared_stmt_stat != NULL)
+ {
+ prepared_stmt_stat->m_warning_count+= da->statement_warn_count();
+ }
break;
case Diagnostics_area::DA_ERROR:
stat->m_error_count++;
@@ -5013,17 +5737,472 @@ static void end_statement_v1(PSI_statement_locker *locker, void *stmt_da)
{
digest_stat->m_error_count++;
}
+ if (sub_stmt_stat != NULL)
+ {
+ sub_stmt_stat->m_error_count++;
+ }
+ if (prepared_stmt_stat != NULL)
+ {
+ prepared_stmt_stat->m_error_count++;
+ }
break;
case Diagnostics_area::DA_DISABLED:
break;
}
}
+static inline enum_object_type sp_type_to_object_type(uint sp_type)
+{
+ enum enum_sp_type value= static_cast<enum enum_sp_type> (sp_type);
+
+ switch (value)
+ {
+ case SP_TYPE_FUNCTION:
+ return OBJECT_TYPE_FUNCTION;
+ case SP_TYPE_PROCEDURE:
+ return OBJECT_TYPE_PROCEDURE;
+ case SP_TYPE_TRIGGER:
+ return OBJECT_TYPE_TRIGGER;
+ case SP_TYPE_EVENT:
+ return OBJECT_TYPE_EVENT;
+ default:
+ DBUG_ASSERT(false);
+ /* Dead code */
+ return NO_OBJECT_TYPE;
+ }
+}
+
+/**
+ Implementation of the stored program instrumentation interface.
+ @sa PSI_v1::get_sp_share.
+*/
+PSI_sp_share *pfs_get_sp_share_v1(uint sp_type,
+ const char* schema_name,
+ uint schema_name_length,
+ const char* object_name,
+ uint object_name_length)
+{
+
+ PFS_thread *pfs_thread= my_thread_get_THR_PFS();
+ if (unlikely(pfs_thread == NULL))
+ return NULL;
+
+ if (object_name_length > COL_OBJECT_NAME_SIZE)
+ object_name_length= COL_OBJECT_NAME_SIZE;
+ if (schema_name_length > COL_OBJECT_SCHEMA_SIZE)
+ schema_name_length= COL_OBJECT_SCHEMA_SIZE;
+
+ PFS_program *pfs_program;
+ pfs_program= find_or_create_program(pfs_thread,
+ sp_type_to_object_type(sp_type),
+ object_name,
+ object_name_length,
+ schema_name,
+ schema_name_length);
+
+ return reinterpret_cast<PSI_sp_share *>(pfs_program);
+}
+
+void pfs_release_sp_share_v1(PSI_sp_share* sp_share)
+{
+ /* Unused */
+ return;
+}
+
+PSI_sp_locker* pfs_start_sp_v1(PSI_sp_locker_state *state,
+ PSI_sp_share *sp_share)
+{
+ DBUG_ASSERT(state != NULL);
+ if (! flag_global_instrumentation)
+ return NULL;
+
+ if (flag_thread_instrumentation)
+ {
+ PFS_thread *pfs_thread= my_thread_get_THR_PFS();
+ if (unlikely(pfs_thread == NULL))
+ return NULL;
+ if (! pfs_thread->m_enabled)
+ return NULL;
+ }
+
+ /*
+ sp share might be null in case when stat array is full and no new
+ stored program stats are being inserted into it.
+ */
+ PFS_program *pfs_program= reinterpret_cast<PFS_program*>(sp_share);
+ if (pfs_program == NULL || !pfs_program->m_enabled)
+ return NULL;
+
+ state->m_flags= 0;
+
+ if(pfs_program->m_timed)
+ {
+ state->m_flags|= STATE_FLAG_TIMED;
+ state->m_timer_start= get_timer_raw_value_and_function(statement_timer,
+ & state->m_timer);
+ }
+
+ state->m_sp_share= sp_share;
+
+ return reinterpret_cast<PSI_sp_locker*> (state);
+}
+
+void pfs_end_sp_v1(PSI_sp_locker *locker)
+{
+ PSI_sp_locker_state *state= reinterpret_cast<PSI_sp_locker_state*> (locker);
+ DBUG_ASSERT(state != NULL);
+
+ ulonglong timer_end;
+ ulonglong wait_time;
+
+ PFS_program *pfs_program= reinterpret_cast<PFS_program *>(state->m_sp_share);
+ PFS_sp_stat *stat= &pfs_program->m_sp_stat;
+
+ if (state->m_flags & STATE_FLAG_TIMED)
+ {
+ timer_end= state->m_timer();
+ wait_time= timer_end - state->m_timer_start;
+
+ /* Now use this timer_end and wait_time for timing information. */
+ stat->aggregate_value(wait_time);
+ }
+ else
+ {
+ stat->aggregate_counted();
+ }
+}
+
+void pfs_drop_sp_v1(uint sp_type,
+ const char* schema_name,
+ uint schema_name_length,
+ const char* object_name,
+ uint object_name_length)
+{
+ PFS_thread *pfs_thread= my_thread_get_THR_PFS();
+ if (unlikely(pfs_thread == NULL))
+ return;
+
+ if (object_name_length > COL_OBJECT_NAME_SIZE)
+ object_name_length= COL_OBJECT_NAME_SIZE;
+ if (schema_name_length > COL_OBJECT_SCHEMA_SIZE)
+ schema_name_length= COL_OBJECT_SCHEMA_SIZE;
+
+ drop_program(pfs_thread,
+ sp_type_to_object_type(sp_type),
+ object_name, object_name_length,
+ schema_name, schema_name_length);
+}
+
+PSI_transaction_locker*
+pfs_get_thread_transaction_locker_v1(PSI_transaction_locker_state *state,
+ const void *xid,
+ const ulonglong *trxid,
+ int isolation_level,
+ my_bool read_only,
+ my_bool autocommit)
+{
+ DBUG_ASSERT(state != NULL);
+
+ if (!flag_global_instrumentation)
+ return NULL;
+
+ if (!global_transaction_class.m_enabled)
+ return NULL;
+
+ uint flags;
+
+ if (flag_thread_instrumentation)
+ {
+ PFS_thread *pfs_thread= my_thread_get_THR_PFS();
+ if (unlikely(pfs_thread == NULL))
+ return NULL;
+ if (!pfs_thread->m_enabled)
+ return NULL;
+ state->m_thread= reinterpret_cast<PSI_thread *> (pfs_thread);
+ flags= STATE_FLAG_THREAD;
+
+ if (global_transaction_class.m_timed)
+ flags|= STATE_FLAG_TIMED;
+
+ if (flag_events_transactions_current)
+ {
+ ulonglong event_id= pfs_thread->m_event_id++;
+
+ PFS_events_transactions *pfs= &pfs_thread->m_transaction_current;
+ pfs->m_thread_internal_id = pfs_thread->m_thread_internal_id;
+ pfs->m_event_id= event_id;
+ pfs->m_event_type= EVENT_TYPE_TRANSACTION;
+ pfs->m_end_event_id= 0;
+ pfs->m_class= &global_transaction_class;
+ pfs->m_timer_start= 0;
+ pfs->m_timer_end= 0;
+ if (xid != NULL)
+ pfs->m_xid= *(PSI_xid *)xid;
+ pfs->m_xa= false;
+ pfs->m_xa_state= TRANS_STATE_XA_NOTR;
+ pfs->m_trxid= (trxid == NULL) ? 0 : *trxid;
+ pfs->m_isolation_level= (enum_isolation_level)isolation_level;
+ pfs->m_read_only= read_only;
+ pfs->m_autocommit= autocommit;
+ pfs->m_savepoint_count= 0;
+ pfs->m_rollback_to_savepoint_count= 0;
+ pfs->m_release_savepoint_count= 0;
+
+ uint statements_count= pfs_thread->m_events_statements_count;
+ if (statements_count > 0)
+ {
+ PFS_events_statements *pfs_statement=
+ &pfs_thread->m_statement_stack[statements_count - 1];
+ pfs->m_nesting_event_id= pfs_statement->m_event_id;
+ pfs->m_nesting_event_type= pfs_statement->m_event_type;
+ }
+ else
+ {
+ pfs->m_nesting_event_id= 0;
+ /* pfs->m_nesting_event_type not used when m_nesting_event_id is 0 */
+ }
+
+ state->m_transaction= pfs;
+ flags|= STATE_FLAG_EVENT;
+ }
+ }
+ else
+ {
+ if (global_transaction_class.m_timed)
+ flags= STATE_FLAG_TIMED;
+ else
+ flags= 0;
+ }
+
+ state->m_class= &global_transaction_class;
+ state->m_flags= flags;
+ state->m_autocommit= autocommit;
+ state->m_read_only= read_only;
+ state->m_savepoint_count= 0;
+ state->m_rollback_to_savepoint_count= 0;
+ state->m_release_savepoint_count= 0;
+
+ return reinterpret_cast<PSI_transaction_locker*> (state);
+}
+
+void pfs_start_transaction_v1(PSI_transaction_locker *locker,
+ const char *src_file, uint src_line)
+{
+ PSI_transaction_locker_state *state= reinterpret_cast<PSI_transaction_locker_state*> (locker);
+ DBUG_ASSERT(state != NULL);
+
+ uint flags= state->m_flags;
+ ulonglong timer_start= 0;
+
+ if (flags & STATE_FLAG_TIMED)
+ {
+ timer_start= get_timer_raw_value_and_function(transaction_timer, &state->m_timer);
+ state->m_timer_start= timer_start;
+ }
+
+ if (flags & STATE_FLAG_EVENT)
+ {
+ PFS_events_transactions *pfs= reinterpret_cast<PFS_events_transactions*> (state->m_transaction);
+ DBUG_ASSERT(pfs != NULL);
+
+ pfs->m_timer_start= timer_start;
+ pfs->m_source_file= src_file;
+ pfs->m_source_line= src_line;
+ pfs->m_state= TRANS_STATE_ACTIVE;
+ //pfs->m_sid.clear();
+ bzero(&pfs->m_gtid_spec, sizeof(pfs->m_gtid_spec));
+ }
+}
+
+void pfs_set_transaction_gtid_v1(PSI_transaction_locker *locker,
+ const void *sid,
+ const void *gtid_spec)
+{
+ PSI_transaction_locker_state *state= reinterpret_cast<PSI_transaction_locker_state*> (locker);
+ DBUG_ASSERT(state != NULL);
+ DBUG_ASSERT(sid != NULL);
+ DBUG_ASSERT(gtid_spec != NULL);
+
+ if (state->m_flags & STATE_FLAG_EVENT)
+ {
+ PFS_events_transactions *pfs= reinterpret_cast<PFS_events_transactions*> (state->m_transaction);
+ DBUG_ASSERT(pfs != NULL);
+ //pfs->m_sid= *(rpl_sid *)sid;
+ pfs->m_gtid_spec= *(Gtid_specification*)gtid_spec;
+ }
+}
+
+void pfs_set_transaction_xid_v1(PSI_transaction_locker *locker,
+ const void *xid,
+ int xa_state)
+{
+ PSI_transaction_locker_state *state= reinterpret_cast<PSI_transaction_locker_state*> (locker);
+ DBUG_ASSERT(state != NULL);
+
+ if (state->m_flags & STATE_FLAG_EVENT)
+ {
+ PFS_events_transactions *pfs= reinterpret_cast<PFS_events_transactions*> (state->m_transaction);
+ DBUG_ASSERT(pfs != NULL);
+ DBUG_ASSERT(xid != NULL);
+
+ pfs->m_xid= *(PSI_xid *)xid;
+ pfs->m_xa_state= (enum_xa_transaction_state)xa_state;
+ pfs->m_xa= true;
+ }
+ return;
+}
+
+void pfs_set_transaction_xa_state_v1(PSI_transaction_locker *locker,
+ int xa_state)
+{
+ PSI_transaction_locker_state *state= reinterpret_cast<PSI_transaction_locker_state*> (locker);
+ DBUG_ASSERT(state != NULL);
+
+ if (state->m_flags & STATE_FLAG_EVENT)
+ {
+ PFS_events_transactions *pfs= reinterpret_cast<PFS_events_transactions*> (state->m_transaction);
+ DBUG_ASSERT(pfs != NULL);
+
+ pfs->m_xa_state= (enum_xa_transaction_state)xa_state;
+ pfs->m_xa= true;
+ }
+ return;
+}
+
+void pfs_set_transaction_trxid_v1(PSI_transaction_locker *locker,
+ const ulonglong *trxid)
+{
+ DBUG_ASSERT(trxid != NULL);
+
+ PSI_transaction_locker_state *state= reinterpret_cast<PSI_transaction_locker_state*> (locker);
+ DBUG_ASSERT(state != NULL);
+
+ if (state->m_flags & STATE_FLAG_EVENT)
+ {
+ PFS_events_transactions *pfs= reinterpret_cast<PFS_events_transactions*> (state->m_transaction);
+ DBUG_ASSERT(pfs != NULL);
+
+ if (pfs->m_trxid == 0)
+ pfs->m_trxid= *trxid;
+ }
+}
+
+#define INC_TRANSACTION_ATTR_BODY(LOCKER, ATTR, VALUE) \
+ PSI_transaction_locker_state *state; \
+ state= reinterpret_cast<PSI_transaction_locker_state*> (LOCKER); \
+ if (unlikely(state == NULL)) \
+ return; \
+ state->ATTR+= VALUE; \
+ if (state->m_flags & STATE_FLAG_EVENT) \
+ { \
+ PFS_events_transactions *pfs; \
+ pfs= reinterpret_cast<PFS_events_transactions*> (state->m_transaction); \
+ DBUG_ASSERT(pfs != NULL); \
+ pfs->ATTR+= VALUE; \
+ } \
+ return;
+
+
+void pfs_inc_transaction_savepoints_v1(PSI_transaction_locker *locker,
+ ulong count)
+{
+ INC_TRANSACTION_ATTR_BODY(locker, m_savepoint_count, count);
+}
+
+void pfs_inc_transaction_rollback_to_savepoint_v1(PSI_transaction_locker *locker,
+ ulong count)
+{
+ INC_TRANSACTION_ATTR_BODY(locker, m_rollback_to_savepoint_count, count);
+}
+
+void pfs_inc_transaction_release_savepoint_v1(PSI_transaction_locker *locker,
+ ulong count)
+{
+ INC_TRANSACTION_ATTR_BODY(locker, m_release_savepoint_count, count);
+}
+
+void pfs_end_transaction_v1(PSI_transaction_locker *locker, my_bool commit)
+{
+ PSI_transaction_locker_state *state= reinterpret_cast<PSI_transaction_locker_state*> (locker);
+ DBUG_ASSERT(state != NULL);
+
+ ulonglong timer_end= 0;
+ ulonglong wait_time= 0;
+ uint flags= state->m_flags;
+
+ if (flags & STATE_FLAG_TIMED)
+ {
+ timer_end= state->m_timer();
+ wait_time= timer_end - state->m_timer_start;
+ }
+
+ PFS_transaction_stat *stat;
+
+ if (flags & STATE_FLAG_THREAD)
+ {
+ PFS_thread *pfs_thread= reinterpret_cast<PFS_thread *> (state->m_thread);
+ DBUG_ASSERT(pfs_thread != NULL);
+
+ /* Aggregate to EVENTS_TRANSACTIONS_SUMMARY_BY_THREAD_BY_EVENT_NAME */
+ stat= &pfs_thread->write_instr_class_transactions_stats()[GLOBAL_TRANSACTION_INDEX];
+
+ if (flags & STATE_FLAG_EVENT)
+ {
+ PFS_events_transactions *pfs= reinterpret_cast<PFS_events_transactions*> (state->m_transaction);
+ DBUG_ASSERT(pfs != NULL);
+
+ /* events_transactions_current may have been cleared while the transaction was active */
+ if (unlikely(pfs->m_class == NULL))
+ return;
+
+ pfs->m_timer_end= timer_end;
+ pfs->m_end_event_id= pfs_thread->m_event_id;
+
+ pfs->m_state= (commit ? TRANS_STATE_COMMITTED : TRANS_STATE_ROLLED_BACK);
+
+ if (pfs->m_xa)
+ pfs->m_xa_state= (commit ? TRANS_STATE_XA_COMMITTED : TRANS_STATE_XA_ROLLBACK_ONLY);
+
+ if (pfs_thread->m_flag_events_transactions_history)
+ insert_events_transactions_history(pfs_thread, pfs);
+ if (pfs_thread->m_flag_events_transactions_history_long)
+ insert_events_transactions_history_long(pfs);
+ }
+ }
+ else
+ {
+ /* Aggregate to EVENTS_TRANSACTIONS_SUMMARY_GLOBAL_BY_EVENT_NAME */
+ stat= &global_transaction_stat;
+ }
+
+ if (flags & STATE_FLAG_TIMED)
+ {
+ /* Aggregate to EVENTS_TRANSACTIONS_SUMMARY_..._BY_EVENT_NAME (timed) */
+ if(state->m_read_only)
+ stat->m_read_only_stat.aggregate_value(wait_time);
+ else
+ stat->m_read_write_stat.aggregate_value(wait_time);
+ }
+ else
+ {
+ /* Aggregate to EVENTS_TRANSACTIONS_SUMMARY_..._BY_EVENT_NAME (counted) */
+ if(state->m_read_only)
+ stat->m_read_only_stat.aggregate_counted();
+ else
+ stat->m_read_write_stat.aggregate_counted();
+ }
+
+ stat->m_savepoint_count+= state->m_savepoint_count;
+ stat->m_rollback_to_savepoint_count+= state->m_rollback_to_savepoint_count;
+ stat->m_release_savepoint_count+= state->m_release_savepoint_count;
+}
+
+
/**
Implementation of the socket instrumentation interface.
@sa PSI_v1::end_socket_wait.
*/
-static void end_socket_wait_v1(PSI_socket_locker *locker, size_t byte_count)
+void pfs_end_socket_wait_v1(PSI_socket_locker *locker, size_t byte_count)
{
PSI_socket_locker_state *state= reinterpret_cast<PSI_socket_locker_state*> (locker);
DBUG_ASSERT(state != NULL);
@@ -5096,9 +6275,9 @@ static void end_socket_wait_v1(PSI_socket_locker *locker, size_t byte_count)
wait->m_end_event_id= thread->m_event_id;
wait->m_number_of_bytes= bytes;
- if (flag_events_waits_history)
+ if (thread->m_flag_events_waits_history)
insert_events_waits_history(thread, wait);
- if (flag_events_waits_history_long)
+ if (thread->m_flag_events_waits_history_long)
insert_events_waits_history_long(wait);
thread->m_events_waits_current--;
@@ -5106,7 +6285,7 @@ static void end_socket_wait_v1(PSI_socket_locker *locker, size_t byte_count)
}
}
-static void set_socket_state_v1(PSI_socket *socket, PSI_socket_state state)
+void pfs_set_socket_state_v1(PSI_socket *socket, PSI_socket_state state)
{
DBUG_ASSERT((state == PSI_SOCKET_STATE_IDLE) || (state == PSI_SOCKET_STATE_ACTIVE));
PFS_socket *pfs= reinterpret_cast<PFS_socket*>(socket);
@@ -5119,10 +6298,10 @@ static void set_socket_state_v1(PSI_socket *socket, PSI_socket_state state)
/**
Set socket descriptor and address info.
*/
-static void set_socket_info_v1(PSI_socket *socket,
- const my_socket *fd,
- const struct sockaddr *addr,
- socklen_t addr_len)
+void pfs_set_socket_info_v1(PSI_socket *socket,
+ const my_socket *fd,
+ const struct sockaddr *addr,
+ socklen_t addr_len)
{
PFS_socket *pfs= reinterpret_cast<PFS_socket*>(socket);
DBUG_ASSERT(pfs != NULL);
@@ -5148,11 +6327,11 @@ static void set_socket_info_v1(PSI_socket *socket,
Implementation of the socket instrumentation interface.
@sa PSI_v1::set_socket_info.
*/
-static void set_socket_thread_owner_v1(PSI_socket *socket)
+void pfs_set_socket_thread_owner_v1(PSI_socket *socket)
{
PFS_socket *pfs_socket= reinterpret_cast<PFS_socket*>(socket);
DBUG_ASSERT(pfs_socket != NULL);
- pfs_socket->m_thread_owner= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+ pfs_socket->m_thread_owner= my_thread_get_THR_PFS();
}
struct PSI_digest_locker*
@@ -5189,30 +6368,86 @@ void pfs_digest_end_v1(PSI_digest_locker *locker, const sql_digest_storage *dige
}
}
+PSI_prepared_stmt*
+pfs_create_prepared_stmt_v1(void *identity, uint stmt_id,
+ PSI_statement_locker *locker,
+ const char *stmt_name, size_t stmt_name_length,
+ const char *sql_text, size_t sql_text_length)
+{
+ PSI_statement_locker_state *state= reinterpret_cast<PSI_statement_locker_state*> (locker);
+ PFS_events_statements *pfs_stmt= reinterpret_cast<PFS_events_statements*> (state->m_statement);
+ PFS_program *pfs_program= reinterpret_cast<PFS_program *>(state->m_parent_sp_share);
+
+ PFS_thread *pfs_thread= my_thread_get_THR_PFS();
+ if (unlikely(pfs_thread == NULL))
+ return NULL;
+
+ if (sql_text_length > COL_INFO_SIZE)
+ sql_text_length= COL_INFO_SIZE;
+
+ PFS_prepared_stmt *pfs= create_prepared_stmt(identity,
+ pfs_thread, pfs_program,
+ pfs_stmt, stmt_id,
+ stmt_name, stmt_name_length,
+ sql_text, sql_text_length);
+
+ state->m_parent_prepared_stmt= reinterpret_cast<PSI_prepared_stmt*>(pfs);
+ state->m_in_prepare= true;
+
+ return reinterpret_cast<PSI_prepared_stmt*>(pfs);
+}
+
+void pfs_execute_prepared_stmt_v1 (PSI_statement_locker *locker,
+ PSI_prepared_stmt* ps)
+{
+ PSI_statement_locker_state *state= reinterpret_cast<PSI_statement_locker_state*> (locker);
+ DBUG_ASSERT(state != NULL);
+
+ state->m_parent_prepared_stmt= ps;
+ state->m_in_prepare= false;
+}
+
+void pfs_destroy_prepared_stmt_v1(PSI_prepared_stmt* prepared_stmt)
+{
+ PFS_prepared_stmt *pfs_prepared_stmt= reinterpret_cast<PFS_prepared_stmt*>(prepared_stmt);
+ delete_prepared_stmt(pfs_prepared_stmt);
+ return;
+}
+
+void pfs_reprepare_prepared_stmt_v1(PSI_prepared_stmt* prepared_stmt)
+{
+ PFS_prepared_stmt *pfs_prepared_stmt= reinterpret_cast<PFS_prepared_stmt*>(prepared_stmt);
+ PFS_single_stat *prepared_stmt_stat= &pfs_prepared_stmt->m_reprepare_stat;
+
+ if (prepared_stmt_stat != NULL)
+ prepared_stmt_stat->aggregate_counted();
+ return;
+}
+
/**
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)
+int pfs_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);
+ PFS_thread *thd= my_thread_get_THR_PFS();
DBUG_ASSERT(buffer != NULL);
if (likely(thd != NULL) && session_connect_attrs_size_per_thread > 0)
{
+ pfs_dirty_state dirty_state;
const CHARSET_INFO *cs = static_cast<const CHARSET_INFO *> (from_cs);
/* 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_session_lock.allocated_to_dirty();
+ thd->m_session_lock.allocated_to_dirty(& dirty_state);
memcpy(thd->m_session_connect_attrs, buffer, copy_size);
thd->m_session_connect_attrs_length= copy_size;
thd->m_session_connect_attrs_cs_number= cs->number;
- thd->m_session_lock.dirty_to_allocated();
+ thd->m_session_lock.dirty_to_allocated(& dirty_state);
if (copy_size == length)
return 0;
@@ -5223,6 +6458,532 @@ static int set_thread_connect_attrs_v1(const char *buffer, uint length,
return 0;
}
+void pfs_register_memory_v1(const char *category,
+ PSI_memory_info_v1 *info,
+ int count)
+{
+ REGISTER_BODY_V1(PSI_memory_key,
+ memory_instrument_prefix,
+ register_memory_class)
+}
+
+PSI_memory_key pfs_memory_alloc_v1(PSI_memory_key key, size_t size, PSI_thread **owner)
+{
+ PFS_thread ** owner_thread= reinterpret_cast<PFS_thread**>(owner);
+ DBUG_ASSERT(owner_thread != NULL);
+
+ if (! flag_global_instrumentation)
+ {
+ *owner_thread= NULL;
+ return PSI_NOT_INSTRUMENTED;
+ }
+
+ PFS_memory_class *klass= find_memory_class(key);
+ if (klass == NULL)
+ {
+ *owner_thread= NULL;
+ return PSI_NOT_INSTRUMENTED;
+ }
+
+ if (! klass->m_enabled)
+ {
+ *owner_thread= NULL;
+ return PSI_NOT_INSTRUMENTED;
+ }
+
+ PFS_memory_stat *event_name_array;
+ PFS_memory_stat *stat;
+ uint index= klass->m_event_name_index;
+ PFS_memory_stat_delta delta_buffer;
+ PFS_memory_stat_delta *delta;
+
+ if (flag_thread_instrumentation && ! klass->is_global())
+ {
+ PFS_thread *pfs_thread= my_thread_get_THR_PFS();
+ if (unlikely(pfs_thread == NULL))
+ {
+ *owner_thread= NULL;
+ return PSI_NOT_INSTRUMENTED;
+ }
+ if (! pfs_thread->m_enabled)
+ {
+ *owner_thread= NULL;
+ return PSI_NOT_INSTRUMENTED;
+ }
+
+ /* Aggregate to MEMORY_SUMMARY_BY_THREAD_BY_EVENT_NAME */
+ event_name_array= pfs_thread->write_instr_class_memory_stats();
+ stat= & event_name_array[index];
+ delta= stat->count_alloc(size, &delta_buffer);
+
+ if (delta != NULL)
+ {
+ pfs_thread->carry_memory_stat_delta(delta, index);
+ }
+
+ /* Flag this memory as owned by the current thread. */
+ *owner_thread= pfs_thread;
+ }
+ else
+ {
+ /* Aggregate to MEMORY_SUMMARY_GLOBAL_BY_EVENT_NAME */
+ event_name_array= global_instr_class_memory_array;
+ stat= & event_name_array[index];
+ (void) stat->count_alloc(size, &delta_buffer);
+
+ *owner_thread= NULL;
+ }
+
+ return key;
+}
+
+PSI_memory_key pfs_memory_realloc_v1(PSI_memory_key key, size_t old_size, size_t new_size, PSI_thread **owner)
+{
+ PFS_thread ** owner_thread_hdl= reinterpret_cast<PFS_thread**>(owner);
+ DBUG_ASSERT(owner != NULL);
+
+ PFS_memory_class *klass= find_memory_class(key);
+ if (klass == NULL)
+ {
+ *owner_thread_hdl= NULL;
+ return PSI_NOT_INSTRUMENTED;
+ }
+
+ PFS_memory_stat *event_name_array;
+ PFS_memory_stat *stat;
+ uint index= klass->m_event_name_index;
+ PFS_memory_stat_delta delta_buffer;
+ PFS_memory_stat_delta *delta;
+
+ if (flag_thread_instrumentation && ! klass->is_global())
+ {
+ PFS_thread *pfs_thread= my_thread_get_THR_PFS();
+ if (likely(pfs_thread != NULL))
+ {
+#ifdef PFS_PARANOID
+ PFS_thread *owner_thread= *owner_thread_hdl;
+ if (owner_thread != pfs_thread)
+ {
+ owner_thread= sanitize_thread(owner_thread);
+ if (owner_thread != NULL)
+ {
+ report_memory_accounting_error("pfs_memory_realloc_v1",
+ pfs_thread, old_size, klass, owner_thread);
+ }
+ }
+#endif /* PFS_PARANOID */
+
+ /* Aggregate to MEMORY_SUMMARY_BY_THREAD_BY_EVENT_NAME */
+ event_name_array= pfs_thread->write_instr_class_memory_stats();
+ stat= & event_name_array[index];
+
+ if (flag_global_instrumentation && klass->m_enabled)
+ {
+ delta= stat->count_realloc(old_size, new_size, &delta_buffer);
+ *owner_thread_hdl= pfs_thread;
+ }
+ else
+ {
+ delta= stat->count_free(old_size, &delta_buffer);
+ *owner_thread_hdl= NULL;
+ key= PSI_NOT_INSTRUMENTED;
+ }
+
+ if (delta != NULL)
+ {
+ pfs_thread->carry_memory_stat_delta(delta, index);
+ }
+ return key;
+ }
+ }
+
+ /* Aggregate to MEMORY_SUMMARY_GLOBAL_BY_EVENT_NAME */
+ event_name_array= global_instr_class_memory_array;
+ stat= & event_name_array[index];
+
+ if (flag_global_instrumentation && klass->m_enabled)
+ {
+ (void) stat->count_realloc(old_size, new_size, &delta_buffer);
+ }
+ else
+ {
+ (void) stat->count_free(old_size, &delta_buffer);
+ key= PSI_NOT_INSTRUMENTED;
+ }
+
+ *owner_thread_hdl= NULL;
+ return key;
+}
+
+PSI_memory_key pfs_memory_claim_v1(PSI_memory_key key, size_t size, PSI_thread **owner)
+{
+ PFS_thread ** owner_thread= reinterpret_cast<PFS_thread**>(owner);
+ DBUG_ASSERT(owner_thread != NULL);
+
+ PFS_memory_class *klass= find_memory_class(key);
+ if (klass == NULL)
+ {
+ *owner_thread= NULL;
+ return PSI_NOT_INSTRUMENTED;
+ }
+
+ /*
+ Do not check klass->m_enabled.
+ Do not check flag_global_instrumentation.
+ If a memory alloc was instrumented,
+ the corresponding free must be instrumented.
+ */
+
+ PFS_memory_stat *event_name_array;
+ PFS_memory_stat *stat;
+ uint index= klass->m_event_name_index;
+ PFS_memory_stat_delta delta_buffer;
+ PFS_memory_stat_delta *delta;
+
+ if (flag_thread_instrumentation)
+ {
+ PFS_thread *old_thread= sanitize_thread(*owner_thread);
+ PFS_thread *new_thread= my_thread_get_THR_PFS();
+ if (old_thread != new_thread)
+ {
+ if (old_thread != NULL)
+ {
+ event_name_array= old_thread->write_instr_class_memory_stats();
+ stat= & event_name_array[index];
+ delta= stat->count_free(size, &delta_buffer);
+
+ if (delta != NULL)
+ {
+ old_thread->carry_memory_stat_delta(delta, index);
+ }
+ }
+
+ if (new_thread != NULL)
+ {
+ event_name_array= new_thread->write_instr_class_memory_stats();
+ stat= & event_name_array[index];
+ delta= stat->count_alloc(size, &delta_buffer);
+
+ if (delta != NULL)
+ {
+ new_thread->carry_memory_stat_delta(delta, index);
+ }
+ }
+
+ *owner_thread= new_thread;
+ }
+
+ return key;
+ }
+
+ *owner_thread= NULL;
+ return key;
+}
+
+void pfs_memory_free_v1(PSI_memory_key key, size_t size, PSI_thread *owner)
+{
+ PFS_memory_class *klass= find_memory_class(key);
+ if (klass == NULL)
+ return;
+
+ /*
+ Do not check klass->m_enabled.
+ Do not check flag_global_instrumentation.
+ If a memory alloc was instrumented,
+ the corresponding free must be instrumented.
+ */
+
+ PFS_memory_stat *event_name_array;
+ PFS_memory_stat *stat;
+ uint index= klass->m_event_name_index;
+ PFS_memory_stat_delta delta_buffer;
+ PFS_memory_stat_delta *delta;
+
+ if (flag_thread_instrumentation && ! klass->is_global())
+ {
+ PFS_thread *pfs_thread= my_thread_get_THR_PFS();
+ if (likely(pfs_thread != NULL))
+ {
+#ifdef PFS_PARANOID
+ PFS_thread *owner_thread= reinterpret_cast<PFS_thread*>(owner);
+
+ if (owner_thread != pfs_thread)
+ {
+ owner_thread= sanitize_thread(owner_thread);
+ if (owner_thread != NULL)
+ {
+ report_memory_accounting_error("pfs_memory_free_v1",
+ pfs_thread, size, klass, owner_thread);
+ }
+ }
+#endif /* PFS_PARANOID */
+
+ /*
+ Do not check pfs_thread->m_enabled.
+ If a memory alloc was instrumented,
+ the corresponding free must be instrumented.
+ */
+ /* Aggregate to MEMORY_SUMMARY_BY_THREAD_BY_EVENT_NAME */
+ event_name_array= pfs_thread->write_instr_class_memory_stats();
+ stat= & event_name_array[index];
+ delta= stat->count_free(size, &delta_buffer);
+
+ if (delta != NULL)
+ {
+ pfs_thread->carry_memory_stat_delta(delta, index);
+ }
+ return;
+ }
+ }
+
+ /* Aggregate to MEMORY_SUMMARY_GLOBAL_BY_EVENT_NAME */
+ event_name_array= global_instr_class_memory_array;
+ if (event_name_array)
+ {
+ stat= & event_name_array[index];
+ (void) stat->count_free(size, &delta_buffer);
+ }
+ return;
+}
+
+void pfs_unlock_table_v1(PSI_table *table)
+{
+ PFS_table *pfs_table= reinterpret_cast<PFS_table*> (table);
+
+ DBUG_ASSERT(pfs_table != NULL);
+
+ pfs_table->m_internal_lock= PFS_TL_NONE;
+ return;
+}
+
+PSI_metadata_lock *
+pfs_create_metadata_lock_v1(
+ void *identity,
+ const MDL_key *mdl_key,
+ opaque_mdl_type mdl_type,
+ opaque_mdl_duration mdl_duration,
+ opaque_mdl_status mdl_status,
+ const char *src_file,
+ uint src_line)
+{
+ if (! flag_global_instrumentation)
+ return NULL;
+
+ if (! global_metadata_class.m_enabled)
+ return NULL;
+
+ PFS_thread *pfs_thread= my_thread_get_THR_PFS();
+ if (pfs_thread == NULL)
+ return NULL;
+
+ PFS_metadata_lock *pfs;
+ pfs= create_metadata_lock(identity, mdl_key,
+ mdl_type, mdl_duration, mdl_status,
+ src_file, src_line);
+
+ if (pfs != NULL)
+ {
+ pfs->m_owner_thread_id= pfs_thread->m_thread_internal_id;
+ pfs->m_owner_event_id= pfs_thread->m_event_id;
+ }
+
+ return reinterpret_cast<PSI_metadata_lock *> (pfs);
+}
+
+void
+pfs_set_metadata_lock_status_v1(PSI_metadata_lock *lock, opaque_mdl_status mdl_status)
+{
+ PFS_metadata_lock *pfs= reinterpret_cast<PFS_metadata_lock*> (lock);
+ DBUG_ASSERT(pfs != NULL);
+ pfs->m_mdl_status= mdl_status;
+}
+
+void
+pfs_destroy_metadata_lock_v1(PSI_metadata_lock *lock)
+{
+ PFS_metadata_lock *pfs= reinterpret_cast<PFS_metadata_lock*> (lock);
+ DBUG_ASSERT(pfs != NULL);
+ destroy_metadata_lock(pfs);
+}
+
+PSI_metadata_locker *
+pfs_start_metadata_wait_v1(PSI_metadata_locker_state *state,
+ PSI_metadata_lock *lock,
+ const char *src_file,
+ uint src_line)
+{
+ PFS_metadata_lock *pfs_lock= reinterpret_cast<PFS_metadata_lock*> (lock);
+ DBUG_ASSERT(state != NULL);
+ DBUG_ASSERT(pfs_lock != NULL);
+
+ if (! pfs_lock->m_enabled)
+ return NULL;
+
+ uint flags;
+ ulonglong timer_start= 0;
+
+ if (flag_thread_instrumentation)
+ {
+ PFS_thread *pfs_thread= my_thread_get_THR_PFS();
+ if (unlikely(pfs_thread == NULL))
+ return NULL;
+ if (! pfs_thread->m_enabled)
+ return NULL;
+ state->m_thread= reinterpret_cast<PSI_thread *> (pfs_thread);
+ flags= STATE_FLAG_THREAD;
+
+ if (pfs_lock->m_timed)
+ {
+ timer_start= get_timer_raw_value_and_function(wait_timer, & state->m_timer);
+ state->m_timer_start= timer_start;
+ flags|= STATE_FLAG_TIMED;
+ }
+
+ if (flag_events_waits_current)
+ {
+ if (unlikely(pfs_thread->m_events_waits_current >=
+ & pfs_thread->m_events_waits_stack[WAIT_STACK_SIZE]))
+ {
+ locker_lost++;
+ return NULL;
+ }
+ PFS_events_waits *wait= pfs_thread->m_events_waits_current;
+ state->m_wait= wait;
+ flags|= STATE_FLAG_EVENT;
+
+ PFS_events_waits *parent_event= wait - 1;
+ wait->m_event_type= EVENT_TYPE_WAIT;
+ wait->m_nesting_event_id= parent_event->m_event_id;
+ wait->m_nesting_event_type= parent_event->m_event_type;
+
+ wait->m_thread_internal_id= pfs_thread->m_thread_internal_id;
+ wait->m_class= &global_metadata_class;
+ wait->m_timer_start= timer_start;
+ wait->m_timer_end= 0;
+ wait->m_object_instance_addr= pfs_lock->m_identity;
+ wait->m_event_id= pfs_thread->m_event_id++;
+ wait->m_end_event_id= 0;
+ wait->m_weak_metadata_lock= pfs_lock;
+ wait->m_weak_version= pfs_lock->get_version();
+ wait->m_operation= OPERATION_TYPE_METADATA;
+ wait->m_source_file= src_file;
+ wait->m_source_line= src_line;
+ wait->m_wait_class= WAIT_CLASS_METADATA;
+
+ pfs_thread->m_events_waits_current++;
+ }
+ }
+ else
+ {
+ if (pfs_lock->m_timed)
+ {
+ timer_start= get_timer_raw_value_and_function(wait_timer, & state->m_timer);
+ state->m_timer_start= timer_start;
+ flags= STATE_FLAG_TIMED;
+ state->m_thread= NULL;
+ }
+ else
+ {
+ /*
+ Complete shortcut.
+ */
+ /* Aggregate to EVENTS_WAITS_SUMMARY_GLOBAL_BY_EVENT_NAME (counted) */
+ global_metadata_stat.aggregate_counted();
+ return NULL;
+ }
+ }
+
+ state->m_flags= flags;
+ state->m_metadata_lock= lock;
+ return reinterpret_cast<PSI_metadata_locker*> (state);
+}
+
+void
+pfs_end_metadata_wait_v1(PSI_metadata_locker *locker,
+ int rc)
+{
+ PSI_metadata_locker_state *state= reinterpret_cast<PSI_metadata_locker_state*> (locker);
+ DBUG_ASSERT(state != NULL);
+
+ ulonglong timer_end= 0;
+ ulonglong wait_time= 0;
+
+ PFS_thread *thread= reinterpret_cast<PFS_thread *> (state->m_thread);
+
+ uint flags= state->m_flags;
+
+ if (flags & STATE_FLAG_TIMED)
+ {
+ timer_end= state->m_timer();
+ wait_time= timer_end - state->m_timer_start;
+ }
+
+ if (flags & STATE_FLAG_THREAD)
+ {
+ PFS_single_stat *event_name_array;
+ event_name_array= thread->write_instr_class_waits_stats();
+
+ if (flags & STATE_FLAG_TIMED)
+ {
+ /* Aggregate to EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME (timed) */
+ event_name_array[GLOBAL_METADATA_EVENT_INDEX].aggregate_value(wait_time);
+ }
+ else
+ {
+ /* Aggregate to EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME (counted) */
+ event_name_array[GLOBAL_METADATA_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 (thread->m_flag_events_waits_history)
+ insert_events_waits_history(thread, wait);
+ if (thread->m_flag_events_waits_history_long)
+ insert_events_waits_history_long(wait);
+ thread->m_events_waits_current--;
+
+ DBUG_ASSERT(wait == thread->m_events_waits_current);
+ }
+ }
+ else
+ {
+ if (flags & STATE_FLAG_TIMED)
+ {
+ /* Aggregate to EVENTS_WAITS_SUMMARY_GLOBAL_BY_EVENT_NAME (timed) */
+ global_metadata_stat.aggregate_value(wait_time);
+ }
+ else
+ {
+ /* Aggregate to EVENTS_WAITS_SUMMARY_GLOBAL_BY_EVENT_NAME (counted) */
+ global_metadata_stat.aggregate_counted();
+ }
+ }
+}
+
+void pfs_set_prepared_stmt_text_v1(PSI_prepared_stmt *prepared_stmt,
+ const char *text,
+ uint text_len)
+{
+ PFS_prepared_stmt *pfs_prepared_stmt =
+ reinterpret_cast<PFS_prepared_stmt *>(prepared_stmt);
+ DBUG_ASSERT(pfs_prepared_stmt != NULL);
+
+ uint max_len = COL_INFO_SIZE;
+ if (text_len > max_len)
+ {
+ text_len = max_len;
+ }
+
+ memcpy(pfs_prepared_stmt->m_sqltext, text, text_len);
+ pfs_prepared_stmt->m_sqltext_length = text_len;
+
+ return;
+}
/**
Implementation of the instrumentation interface.
@@ -5230,103 +6991,140 @@ static int set_thread_connect_attrs_v1(const char *buffer, uint length,
*/
PSI_v1 PFS_v1=
{
- register_mutex_v1,
- register_rwlock_v1,
- register_cond_v1,
- register_thread_v1,
- register_file_v1,
- register_stage_v1,
- register_statement_v1,
- register_socket_v1,
- init_mutex_v1,
- destroy_mutex_v1,
- init_rwlock_v1,
- destroy_rwlock_v1,
- init_cond_v1,
- destroy_cond_v1,
- init_socket_v1,
- destroy_socket_v1,
- get_table_share_v1,
- release_table_share_v1,
- drop_table_share_v1,
- open_table_v1,
- unbind_table_v1,
- rebind_table_v1,
- close_table_v1,
- create_file_v1,
- spawn_thread_v1,
- new_thread_v1,
- set_thread_id_v1,
- get_thread_v1,
- set_thread_user_v1,
- set_thread_account_v1,
- set_thread_db_v1,
- set_thread_command_v1,
- set_thread_start_time_v1,
- set_thread_state_v1,
- set_thread_info_v1,
- set_thread_v1,
- delete_current_thread_v1,
- delete_thread_v1,
- get_thread_file_name_locker_v1,
- get_thread_file_stream_locker_v1,
- get_thread_file_descriptor_locker_v1,
- unlock_mutex_v1,
- unlock_rwlock_v1,
- signal_cond_v1,
- broadcast_cond_v1,
- start_idle_wait_v1,
- end_idle_wait_v1,
- start_mutex_wait_v1,
- end_mutex_wait_v1,
- start_rwlock_wait_v1, /* read */
- end_rwlock_rdwait_v1,
- start_rwlock_wait_v1, /* write */
- end_rwlock_wrwait_v1,
- start_cond_wait_v1,
- end_cond_wait_v1,
- start_table_io_wait_v1,
- end_table_io_wait_v1,
- start_table_lock_wait_v1,
- end_table_lock_wait_v1,
- start_file_open_wait_v1,
- end_file_open_wait_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,
- refine_statement_v1,
- start_statement_v1,
- set_statement_text_v1,
- set_statement_lock_time_v1,
- set_statement_rows_sent_v1,
- set_statement_rows_examined_v1,
- inc_statement_created_tmp_disk_tables_v1,
- inc_statement_created_tmp_tables_v1,
- inc_statement_select_full_join_v1,
- inc_statement_select_full_range_join_v1,
- inc_statement_select_range_v1,
- inc_statement_select_range_check_v1,
- inc_statement_select_scan_v1,
- inc_statement_sort_merge_passes_v1,
- inc_statement_sort_range_v1,
- inc_statement_sort_rows_v1,
- inc_statement_sort_scan_v1,
- set_statement_no_index_used_v1,
- set_statement_no_good_index_used_v1,
- end_statement_v1,
- start_socket_wait_v1,
- end_socket_wait_v1,
- set_socket_state_v1,
- set_socket_info_v1,
- set_socket_thread_owner_v1,
+ pfs_register_mutex_v1,
+ pfs_register_rwlock_v1,
+ pfs_register_cond_v1,
+ pfs_register_thread_v1,
+ pfs_register_file_v1,
+ pfs_register_stage_v1,
+ pfs_register_statement_v1,
+ pfs_register_socket_v1,
+ pfs_init_mutex_v1,
+ pfs_destroy_mutex_v1,
+ pfs_init_rwlock_v1,
+ pfs_destroy_rwlock_v1,
+ pfs_init_cond_v1,
+ pfs_destroy_cond_v1,
+ pfs_init_socket_v1,
+ pfs_destroy_socket_v1,
+ pfs_get_table_share_v1,
+ pfs_release_table_share_v1,
+ pfs_drop_table_share_v1,
+ pfs_open_table_v1,
+ pfs_unbind_table_v1,
+ pfs_rebind_table_v1,
+ pfs_close_table_v1,
+ pfs_create_file_v1,
+ pfs_spawn_thread_v1,
+ pfs_new_thread_v1,
+ pfs_set_thread_id_v1,
+ pfs_set_thread_THD_v1,
+ pfs_set_thread_os_id_v1,
+ pfs_get_thread_v1,
+ pfs_set_thread_user_v1,
+ pfs_set_thread_account_v1,
+ pfs_set_thread_db_v1,
+ pfs_set_thread_command_v1,
+ pfs_set_connection_type_v1,
+ pfs_set_thread_start_time_v1,
+ pfs_set_thread_state_v1,
+ pfs_set_thread_info_v1,
+ pfs_set_thread_v1,
+ pfs_delete_current_thread_v1,
+ pfs_delete_thread_v1,
+ pfs_get_thread_file_name_locker_v1,
+ pfs_get_thread_file_stream_locker_v1,
+ pfs_get_thread_file_descriptor_locker_v1,
+ pfs_unlock_mutex_v1,
+ pfs_unlock_rwlock_v1,
+ pfs_signal_cond_v1,
+ pfs_broadcast_cond_v1,
+ pfs_start_idle_wait_v1,
+ pfs_end_idle_wait_v1,
+ pfs_start_mutex_wait_v1,
+ pfs_end_mutex_wait_v1,
+ pfs_start_rwlock_rdwait_v1,
+ pfs_end_rwlock_rdwait_v1,
+ pfs_start_rwlock_wrwait_v1,
+ pfs_end_rwlock_wrwait_v1,
+ pfs_start_cond_wait_v1,
+ pfs_end_cond_wait_v1,
+ pfs_start_table_io_wait_v1,
+ pfs_end_table_io_wait_v1,
+ pfs_start_table_lock_wait_v1,
+ pfs_end_table_lock_wait_v1,
+ pfs_start_file_open_wait_v1,
+ pfs_end_file_open_wait_v1,
+ pfs_end_file_open_wait_and_bind_to_descriptor_v1,
+ pfs_end_temp_file_open_wait_and_bind_to_descriptor_v1,
+ pfs_start_file_wait_v1,
+ pfs_end_file_wait_v1,
+ pfs_start_file_close_wait_v1,
+ pfs_end_file_close_wait_v1,
+ pfs_end_file_rename_wait_v1,
+ pfs_start_stage_v1,
+ pfs_get_current_stage_progress_v1,
+ pfs_end_stage_v1,
+ pfs_get_thread_statement_locker_v1,
+ pfs_refine_statement_v1,
+ pfs_start_statement_v1,
+ pfs_set_statement_text_v1,
+ pfs_set_statement_lock_time_v1,
+ pfs_set_statement_rows_sent_v1,
+ pfs_set_statement_rows_examined_v1,
+ pfs_inc_statement_created_tmp_disk_tables_v1,
+ pfs_inc_statement_created_tmp_tables_v1,
+ pfs_inc_statement_select_full_join_v1,
+ pfs_inc_statement_select_full_range_join_v1,
+ pfs_inc_statement_select_range_v1,
+ pfs_inc_statement_select_range_check_v1,
+ pfs_inc_statement_select_scan_v1,
+ pfs_inc_statement_sort_merge_passes_v1,
+ pfs_inc_statement_sort_range_v1,
+ pfs_inc_statement_sort_rows_v1,
+ pfs_inc_statement_sort_scan_v1,
+ pfs_set_statement_no_index_used_v1,
+ pfs_set_statement_no_good_index_used_v1,
+ pfs_end_statement_v1,
+ pfs_get_thread_transaction_locker_v1,
+ pfs_start_transaction_v1,
+ pfs_set_transaction_xid_v1,
+ pfs_set_transaction_xa_state_v1,
+ pfs_set_transaction_gtid_v1,
+ pfs_set_transaction_trxid_v1,
+ pfs_inc_transaction_savepoints_v1,
+ pfs_inc_transaction_rollback_to_savepoint_v1,
+ pfs_inc_transaction_release_savepoint_v1,
+ pfs_end_transaction_v1,
+ pfs_start_socket_wait_v1,
+ pfs_end_socket_wait_v1,
+ pfs_set_socket_state_v1,
+ pfs_set_socket_info_v1,
+ pfs_set_socket_thread_owner_v1,
+ pfs_create_prepared_stmt_v1,
+ pfs_destroy_prepared_stmt_v1,
+ pfs_reprepare_prepared_stmt_v1,
+ pfs_execute_prepared_stmt_v1,
+ pfs_set_prepared_stmt_text_v1,
pfs_digest_start_v1,
pfs_digest_end_v1,
- set_thread_connect_attrs_v1,
+ pfs_set_thread_connect_attrs_v1,
+ pfs_start_sp_v1,
+ pfs_end_sp_v1,
+ pfs_drop_sp_v1,
+ pfs_get_sp_share_v1,
+ pfs_release_sp_share_v1,
+ pfs_register_memory_v1,
+ pfs_memory_alloc_v1,
+ pfs_memory_realloc_v1,
+ pfs_memory_claim_v1,
+ pfs_memory_free_v1,
+ pfs_unlock_table_v1,
+ pfs_create_metadata_lock_v1,
+ pfs_set_metadata_lock_status_v1,
+ pfs_destroy_metadata_lock_v1,
+ pfs_start_metadata_wait_v1,
+ pfs_end_metadata_wait_v1
};
static void* get_interface(int version)
diff --git a/storage/perfschema/pfs.h b/storage/perfschema/pfs.h
index 3649143f8fa..69b23be4206 100644
--- a/storage/perfschema/pfs.h
+++ b/storage/perfschema/pfs.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2016, 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, version 2.0,
@@ -30,7 +30,8 @@
#define HAVE_PSI_1
-#include <my_pthread.h>
+#include <my_global.h>
+#include "my_thread.h"
#include <mysql/psi/psi.h>
/**
@@ -39,9 +40,24 @@
*/
extern struct PSI_bootstrap PFS_bootstrap;
/** Performance schema Thread Local Storage key. */
-extern pthread_key(PFS_thread*, THR_PFS);
-/** True when @c THR_PFS is initialized. */
+extern pthread_key_t THR_PFS;
+extern pthread_key_t THR_PFS_VG; // global_variables
+extern pthread_key_t THR_PFS_SV; // session_variables
+extern pthread_key_t THR_PFS_VBT; // variables_by_thread
+extern pthread_key_t THR_PFS_SG; // global_status
+extern pthread_key_t THR_PFS_SS; // session_status
+extern pthread_key_t THR_PFS_SBT; // status_by_thread
+extern pthread_key_t THR_PFS_SBU; // status_by_user
+extern pthread_key_t THR_PFS_SBA; // status_by_host
+extern pthread_key_t THR_PFS_SBH; // status_by_account
+
+/** True when @c THR_PFS and all other Performance Schema TLS keys are initialized. */
extern bool THR_PFS_initialized;
+#define PSI_VOLATILITY_UNKNOWN 0
+#define PSI_VOLATILITY_SESSION 1
+
+#define PSI_COUNT_VOLATILITY 2
+
#endif
diff --git a/storage/perfschema/pfs_account.cc b/storage/perfschema/pfs_account.cc
index be2153e84ae..9d7a0afb783 100644
--- a/storage/perfschema/pfs_account.cc
+++ b/storage/perfschema/pfs_account.cc
@@ -22,7 +22,7 @@
/**
@file storage/perfschema/pfs_account.cc
- Performance schema user@host (implementation).
+ Performance schema account (implementation).
*/
#include "my_global.h"
@@ -37,21 +37,13 @@
#include "pfs_account.h"
#include "pfs_global.h"
#include "pfs_instr_class.h"
+#include "pfs_buffer_container.h"
/**
@addtogroup Performance_schema_buffers
@{
*/
-ulong account_max;
-ulong account_lost;
-
-PFS_account *account_array= NULL;
-
-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;
-
LF_HASH account_hash;
static bool account_hash_inited= false;
@@ -62,75 +54,16 @@ static bool account_hash_inited= false;
*/
int init_account(const PFS_global_param *param)
{
- uint index;
-
- account_max= param->m_account_sizing;
-
- account_array= NULL;
- account_instr_class_waits_array= NULL;
- account_instr_class_stages_array= NULL;
- account_instr_class_statements_array= NULL;
- uint waits_sizing= account_max * wait_class_max;
- uint stages_sizing= account_max * stage_class_max;
- uint statements_sizing= account_max * statement_class_max;
-
- if (account_max > 0)
- {
- account_array= PFS_MALLOC_ARRAY(account_max, sizeof(PFS_account), PFS_account,
- MYF(MY_ZEROFILL));
- if (unlikely(account_array == NULL))
- return 1;
- }
-
- if (waits_sizing > 0)
- {
- account_instr_class_waits_array=
- PFS_connection_slice::alloc_waits_slice(waits_sizing);
- if (unlikely(account_instr_class_waits_array == NULL))
- return 1;
- }
-
- if (stages_sizing > 0)
- {
- account_instr_class_stages_array=
- PFS_connection_slice::alloc_stages_slice(stages_sizing);
- if (unlikely(account_instr_class_stages_array == NULL))
- return 1;
- }
-
- if (statements_sizing > 0)
- {
- account_instr_class_statements_array=
- PFS_connection_slice::alloc_statements_slice(statements_sizing);
- if (unlikely(account_instr_class_statements_array == NULL))
- return 1;
- }
-
- for (index= 0; index < account_max; index++)
- {
- account_array[index].m_instr_class_waits_stats=
- &account_instr_class_waits_array[index * wait_class_max];
- account_array[index].m_instr_class_stages_stats=
- &account_instr_class_stages_array[index * stage_class_max];
- account_array[index].m_instr_class_statements_stats=
- &account_instr_class_statements_array[index * statement_class_max];
- }
+ if (global_account_container.init(param->m_account_sizing))
+ return 1;
return 0;
}
-/** Cleanup all the user buffers. */
+/** Cleanup all the account buffers. */
void cleanup_account(void)
{
- pfs_free(account_array);
- account_array= NULL;
- pfs_free(account_instr_class_waits_array);
- account_instr_class_waits_array= NULL;
- pfs_free(account_instr_class_stages_array);
- account_instr_class_stages_array= 0;
- pfs_free(account_instr_class_statements_array);
- account_instr_class_statements_array=0;
- account_max= 0;
+ global_account_container.cleanup();
}
C_MODE_START
@@ -154,13 +87,12 @@ C_MODE_END
Initialize the user hash.
@return 0 on success
*/
-int init_account_hash(void)
+int init_account_hash(const PFS_global_param *param)
{
- if ((! account_hash_inited) && (account_max > 0))
+ if ((! account_hash_inited) && (param->m_account_sizing != 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;
@@ -217,16 +149,10 @@ find_or_create_account(PFS_thread *thread,
const char *username, uint username_length,
const char *hostname, uint hostname_length)
{
- if (account_max == 0)
- {
- account_lost++;
- return NULL;
- }
-
LF_PINS *pins= get_account_hash_pins(thread);
if (unlikely(pins == NULL))
{
- account_lost++;
+ global_account_container.m_lost++;
return NULL;
}
@@ -235,8 +161,10 @@ find_or_create_account(PFS_thread *thread,
hostname, hostname_length);
PFS_account **entry;
+ PFS_account *pfs;
uint retry_count= 0;
const uint retry_max= 3;
+ pfs_dirty_state dirty_state;
search:
entry= reinterpret_cast<PFS_account**>
@@ -244,7 +172,6 @@ search:
key.m_hash_key, key.m_key_length));
if (entry && (entry != MY_ERRPTR))
{
- PFS_account *pfs;
pfs= *entry;
pfs->inc_refcount();
lf_hash_search_unpin(pins);
@@ -253,93 +180,94 @@ search:
lf_hash_search_unpin(pins);
- PFS_scan scan;
- uint random= randomized_index(username, account_max);
-
- for (scan.init(random, account_max);
- scan.has_pass();
- scan.next_pass())
+ pfs= global_account_container.allocate(& dirty_state);
+ if (pfs != NULL)
{
- PFS_account *pfs= account_array + scan.first();
- PFS_account *pfs_last= account_array + scan.last();
- for ( ; pfs < pfs_last; pfs++)
+ pfs->m_key= key;
+ if (username_length > 0)
+ pfs->m_username= &pfs->m_key.m_hash_key[0];
+ else
+ pfs->m_username= NULL;
+ pfs->m_username_length= username_length;
+
+ if (hostname_length > 0)
+ pfs->m_hostname= &pfs->m_key.m_hash_key[username_length + 1];
+ else
+ pfs->m_hostname= NULL;
+ pfs->m_hostname_length= hostname_length;
+
+ pfs->m_user= find_or_create_user(thread, username, username_length);
+ pfs->m_host= find_or_create_host(thread, hostname, hostname_length);
+
+ pfs->init_refcount();
+ pfs->reset_stats();
+ pfs->m_disconnected_count= 0;
+
+ if (username_length > 0 && hostname_length > 0)
+ {
+ lookup_setup_actor(thread, username, username_length, hostname, hostname_length,
+ & pfs->m_enabled, & pfs->m_history);
+ }
+ else
{
- if (pfs->m_lock.is_free())
+ pfs->m_enabled= true;
+ pfs->m_history= true;
+ }
+
+ int res;
+ pfs->m_lock.dirty_to_allocated(& dirty_state);
+ res= lf_hash_insert(&account_hash, pins, &pfs);
+ if (likely(res == 0))
+ {
+ return pfs;
+ }
+
+ if (pfs->m_user)
+ {
+ pfs->m_user->release();
+ pfs->m_user= NULL;
+ }
+ if (pfs->m_host)
+ {
+ pfs->m_host->release();
+ pfs->m_host= NULL;
+ }
+
+ global_account_container.deallocate(pfs);
+
+ if (res > 0)
+ {
+ if (++retry_count > retry_max)
{
- if (pfs->m_lock.free_to_dirty())
- {
- pfs->m_key= key;
- if (username_length > 0)
- pfs->m_username= &pfs->m_key.m_hash_key[0];
- else
- pfs->m_username= NULL;
- pfs->m_username_length= username_length;
-
- if (hostname_length > 0)
- pfs->m_hostname= &pfs->m_key.m_hash_key[username_length + 1];
- else
- pfs->m_hostname= NULL;
- pfs->m_hostname_length= hostname_length;
-
- pfs->m_user= find_or_create_user(thread, username, username_length);
- pfs->m_host= find_or_create_host(thread, hostname, hostname_length);
-
- pfs->init_refcount();
- pfs->reset_stats();
- pfs->m_disconnected_count= 0;
-
- int res;
- res= lf_hash_insert(&account_hash, pins, &pfs);
- if (likely(res == 0))
- {
- pfs->m_lock.dirty_to_allocated();
- return pfs;
- }
-
- if (pfs->m_user)
- {
- pfs->m_user->release();
- pfs->m_user= NULL;
- }
- if (pfs->m_host)
- {
- pfs->m_host->release();
- pfs->m_host= NULL;
- }
-
- pfs->m_lock.dirty_to_free();
-
- if (res > 0)
- {
- if (++retry_count > retry_max)
- {
- account_lost++;
- return NULL;
- }
- goto search;
- }
-
- account_lost++;
- return NULL;
- }
+ global_account_container.m_lost++;
+ return NULL;
}
+ goto search;
}
+
+ global_account_container.m_lost++;
+ return NULL;
}
- account_lost++;
return NULL;
}
-void PFS_account::aggregate(PFS_user *safe_user, PFS_host *safe_host)
+void PFS_account::aggregate(bool alive, PFS_user *safe_user, PFS_host *safe_host)
{
aggregate_waits(safe_user, safe_host);
aggregate_stages(safe_user, safe_host);
aggregate_statements(safe_user, safe_host);
+ aggregate_transactions(safe_user, safe_host);
+ aggregate_memory(alive, safe_user, safe_host);
+ aggregate_status(safe_user, safe_host);
aggregate_stats(safe_user, safe_host);
}
void PFS_account::aggregate_waits(PFS_user *safe_user, PFS_host *safe_host)
{
+ if (read_instr_class_waits_stats() == NULL)
+ return;
+
if (likely(safe_user != NULL && safe_host != NULL))
{
/*
@@ -348,9 +276,9 @@ void PFS_account::aggregate_waits(PFS_user *safe_user, PFS_host *safe_host)
- EVENTS_WAITS_SUMMARY_BY_HOST_BY_EVENT_NAME
in parallel.
*/
- aggregate_all_event_names(m_instr_class_waits_stats,
- safe_user->m_instr_class_waits_stats,
- safe_host->m_instr_class_waits_stats);
+ aggregate_all_event_names(write_instr_class_waits_stats(),
+ safe_user->write_instr_class_waits_stats(),
+ safe_host->write_instr_class_waits_stats());
return;
}
@@ -360,8 +288,8 @@ void PFS_account::aggregate_waits(PFS_user *safe_user, PFS_host *safe_host)
Aggregate EVENTS_WAITS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
- EVENTS_WAITS_SUMMARY_BY_USER_BY_EVENT_NAME
*/
- aggregate_all_event_names(m_instr_class_waits_stats,
- safe_user->m_instr_class_waits_stats);
+ aggregate_all_event_names(write_instr_class_waits_stats(),
+ safe_user->write_instr_class_waits_stats());
return;
}
@@ -371,8 +299,8 @@ void PFS_account::aggregate_waits(PFS_user *safe_user, PFS_host *safe_host)
Aggregate EVENTS_WAITS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
- EVENTS_WAITS_SUMMARY_BY_HOST_BY_EVENT_NAME
*/
- aggregate_all_event_names(m_instr_class_waits_stats,
- safe_host->m_instr_class_waits_stats);
+ aggregate_all_event_names(write_instr_class_waits_stats(),
+ safe_host->write_instr_class_waits_stats());
return;
}
@@ -383,6 +311,9 @@ void PFS_account::aggregate_waits(PFS_user *safe_user, PFS_host *safe_host)
void PFS_account::aggregate_stages(PFS_user *safe_user, PFS_host *safe_host)
{
+ if (read_instr_class_stages_stats() == NULL)
+ return;
+
if (likely(safe_user != NULL && safe_host != NULL))
{
/*
@@ -391,9 +322,9 @@ void PFS_account::aggregate_stages(PFS_user *safe_user, PFS_host *safe_host)
- EVENTS_STAGES_SUMMARY_BY_HOST_BY_EVENT_NAME
in parallel.
*/
- aggregate_all_stages(m_instr_class_stages_stats,
- safe_user->m_instr_class_stages_stats,
- safe_host->m_instr_class_stages_stats);
+ aggregate_all_stages(write_instr_class_stages_stats(),
+ safe_user->write_instr_class_stages_stats(),
+ safe_host->write_instr_class_stages_stats());
return;
}
@@ -405,8 +336,8 @@ void PFS_account::aggregate_stages(PFS_user *safe_user, PFS_host *safe_host)
- EVENTS_STAGES_SUMMARY_GLOBAL_BY_EVENT_NAME
in parallel.
*/
- aggregate_all_stages(m_instr_class_stages_stats,
- safe_user->m_instr_class_stages_stats,
+ aggregate_all_stages(write_instr_class_stages_stats(),
+ safe_user->write_instr_class_stages_stats(),
global_instr_class_stages_array);
return;
}
@@ -417,8 +348,8 @@ void PFS_account::aggregate_stages(PFS_user *safe_user, PFS_host *safe_host)
Aggregate EVENTS_STAGES_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
- EVENTS_STAGES_SUMMARY_BY_HOST_BY_EVENT_NAME
*/
- aggregate_all_stages(m_instr_class_stages_stats,
- safe_host->m_instr_class_stages_stats);
+ aggregate_all_stages(write_instr_class_stages_stats(),
+ safe_host->write_instr_class_stages_stats());
return;
}
@@ -426,13 +357,16 @@ void PFS_account::aggregate_stages(PFS_user *safe_user, PFS_host *safe_host)
Aggregate EVENTS_STAGES_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
- EVENTS_STAGES_SUMMARY_GLOBAL_BY_EVENT_NAME
*/
- aggregate_all_stages(m_instr_class_stages_stats,
+ aggregate_all_stages(write_instr_class_stages_stats(),
global_instr_class_stages_array);
return;
}
void PFS_account::aggregate_statements(PFS_user *safe_user, PFS_host *safe_host)
{
+ if (read_instr_class_statements_stats() == NULL)
+ return;
+
if (likely(safe_user != NULL && safe_host != NULL))
{
/*
@@ -441,9 +375,9 @@ void PFS_account::aggregate_statements(PFS_user *safe_user, PFS_host *safe_host)
- EVENTS_STATEMENTS_SUMMARY_BY_HOST_BY_EVENT_NAME
in parallel.
*/
- aggregate_all_statements(m_instr_class_statements_stats,
- safe_user->m_instr_class_statements_stats,
- safe_host->m_instr_class_statements_stats);
+ aggregate_all_statements(write_instr_class_statements_stats(),
+ safe_user->write_instr_class_statements_stats(),
+ safe_host->write_instr_class_statements_stats());
return;
}
@@ -455,8 +389,8 @@ void PFS_account::aggregate_statements(PFS_user *safe_user, PFS_host *safe_host)
- EVENTS_STATEMENTS_SUMMARY_GLOBAL_BY_EVENT_NAME
in parallel.
*/
- aggregate_all_statements(m_instr_class_statements_stats,
- safe_user->m_instr_class_statements_stats,
+ aggregate_all_statements(write_instr_class_statements_stats(),
+ safe_user->write_instr_class_statements_stats(),
global_instr_class_statements_array);
return;
}
@@ -467,8 +401,8 @@ void PFS_account::aggregate_statements(PFS_user *safe_user, PFS_host *safe_host)
Aggregate EVENTS_STATEMENTS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
- EVENTS_STATEMENTS_SUMMARY_BY_HOST_BY_EVENT_NAME
*/
- aggregate_all_statements(m_instr_class_statements_stats,
- safe_host->m_instr_class_statements_stats);
+ aggregate_all_statements(write_instr_class_statements_stats(),
+ safe_host->write_instr_class_statements_stats());
return;
}
@@ -476,11 +410,169 @@ void PFS_account::aggregate_statements(PFS_user *safe_user, PFS_host *safe_host)
Aggregate EVENTS_STATEMENTS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
- EVENTS_STATEMENTS_SUMMARY_GLOBAL_BY_EVENT_NAME
*/
- aggregate_all_statements(m_instr_class_statements_stats,
+ aggregate_all_statements(write_instr_class_statements_stats(),
global_instr_class_statements_array);
return;
}
+void PFS_account::aggregate_transactions(PFS_user *safe_user, PFS_host *safe_host)
+{
+ if (read_instr_class_transactions_stats() == NULL)
+ return;
+
+ if (likely(safe_user != NULL && safe_host != NULL))
+ {
+ /*
+ Aggregate EVENTS_TRANSACTIONS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
+ - EVENTS_TRANSACTIONS_SUMMARY_BY_USER_BY_EVENT_NAME
+ - EVENTS_TRANSACTIONS_SUMMARY_BY_HOST_BY_EVENT_NAME
+ in parallel.
+ */
+ aggregate_all_transactions(write_instr_class_transactions_stats(),
+ safe_user->write_instr_class_transactions_stats(),
+ safe_host->write_instr_class_transactions_stats());
+ return;
+ }
+
+ if (safe_user != NULL)
+ {
+ /*
+ Aggregate EVENTS_TRANSACTIONS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
+ - EVENTS_TRANSACTIONS_SUMMARY_BY_USER_BY_EVENT_NAME
+ - EVENTS_TRANSACTIONS_SUMMARY_GLOBAL_BY_EVENT_NAME
+ in parallel.
+ */
+ aggregate_all_transactions(write_instr_class_transactions_stats(),
+ safe_user->write_instr_class_transactions_stats(),
+ &global_transaction_stat);
+ return;
+ }
+
+ if (safe_host != NULL)
+ {
+ /*
+ Aggregate EVENTS_TRANSACTIONS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
+ - EVENTS_TRANSACTIONS_SUMMARY_BY_HOST_BY_EVENT_NAME
+ */
+ aggregate_all_transactions(write_instr_class_transactions_stats(),
+ safe_host->write_instr_class_transactions_stats());
+ return;
+ }
+
+ /*
+ Aggregate EVENTS_TRANSACTIONS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
+ - EVENTS_TRANSACTIONS_SUMMARY_GLOBAL_BY_EVENT_NAME
+ */
+ aggregate_all_transactions(write_instr_class_transactions_stats(),
+ &global_transaction_stat);
+ return;
+}
+
+void PFS_account::aggregate_memory(bool alive, PFS_user *safe_user, PFS_host *safe_host)
+{
+ if (read_instr_class_memory_stats() == NULL)
+ return;
+
+ if (likely(safe_user != NULL && safe_host != NULL))
+ {
+ /*
+ Aggregate MEMORY_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
+ - MEMORY_SUMMARY_BY_USER_BY_EVENT_NAME
+ - MEMORY_SUMMARY_BY_HOST_BY_EVENT_NAME
+ in parallel.
+ */
+ aggregate_all_memory(alive,
+ write_instr_class_memory_stats(),
+ safe_user->write_instr_class_memory_stats(),
+ safe_host->write_instr_class_memory_stats());
+ return;
+ }
+
+ if (safe_user != NULL)
+ {
+ /*
+ Aggregate MEMORY_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
+ - MEMORY_SUMMARY_BY_USER_BY_EVENT_NAME
+ - MEMORY_SUMMARY_GLOBAL_BY_EVENT_NAME
+ in parallel.
+ */
+ aggregate_all_memory(alive,
+ write_instr_class_memory_stats(),
+ safe_user->write_instr_class_memory_stats(),
+ global_instr_class_memory_array);
+ return;
+ }
+
+ if (safe_host != NULL)
+ {
+ /*
+ Aggregate MEMORY_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
+ - MEMORY_SUMMARY_BY_HOST_BY_EVENT_NAME
+ */
+ aggregate_all_memory(alive,
+ write_instr_class_memory_stats(),
+ safe_host->write_instr_class_memory_stats());
+ return;
+ }
+
+ /*
+ Aggregate MEMORY_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME to:
+ - MEMORY_SUMMARY_GLOBAL_BY_EVENT_NAME
+ */
+ aggregate_all_memory(alive,
+ write_instr_class_memory_stats(),
+ global_instr_class_memory_array);
+ return;
+}
+
+void PFS_account::aggregate_status(PFS_user *safe_user, PFS_host *safe_host)
+{
+ if (likely(safe_user != NULL && safe_host != NULL))
+ {
+ /*
+ Aggregate STATUS_BY_ACCOUNT to:
+ - STATUS_BY_USER
+ - STATUS_BY_HOST
+ */
+ safe_user->m_status_stats.aggregate(& m_status_stats);
+ safe_host->m_status_stats.aggregate(& m_status_stats);
+ m_status_stats.reset();
+ return;
+ }
+
+ if (safe_user != NULL)
+ {
+ /*
+ Aggregate STATUS_BY_ACCOUNT to:
+ - STATUS_BY_USER
+ - GLOBAL_STATUS
+ */
+ safe_user->m_status_stats.aggregate(& m_status_stats);
+ m_status_stats.aggregate_to(& global_status_var);
+ m_status_stats.reset();
+ return;
+ }
+
+ if (safe_host != NULL)
+ {
+ /*
+ Aggregate STATUS_BY_ACCOUNT to:
+ - STATUS_BY_HOST
+ */
+ safe_host->m_status_stats.aggregate(& m_status_stats);
+ m_status_stats.reset();
+ return;
+ }
+
+ /*
+ Aggregate STATUS_BY_ACCOUNT to:
+ - GLOBAL_STATUS
+ */
+ m_status_stats.aggregate_to(& global_status_var);
+ m_status_stats.reset();
+ return;
+}
+
void PFS_account::aggregate_stats(PFS_user *safe_user, PFS_host *safe_host)
{
if (likely(safe_user != NULL && safe_host != NULL))
@@ -514,19 +606,42 @@ void PFS_account::release()
dec_refcount();
}
-PFS_account *sanitize_account(PFS_account *unsafe)
+void PFS_account::carry_memory_stat_delta(PFS_memory_stat_delta *delta, uint index)
{
- if ((&account_array[0] <= unsafe) &&
- (unsafe < &account_array[account_max]))
- return unsafe;
- return NULL;
+ PFS_memory_stat *event_name_array;
+ PFS_memory_stat *stat;
+ PFS_memory_stat_delta delta_buffer;
+ PFS_memory_stat_delta *remaining_delta;
+
+ event_name_array= write_instr_class_memory_stats();
+ stat= & event_name_array[index];
+ remaining_delta= stat->apply_delta(delta, &delta_buffer);
+
+ if (remaining_delta == NULL)
+ return;
+
+ if (m_user != NULL)
+ {
+ m_user->carry_memory_stat_delta(remaining_delta, index);
+ /* do not return, need to process m_host below */
+ }
+
+ if (m_host != NULL)
+ {
+ m_host->carry_memory_stat_delta(remaining_delta, index);
+ return;
+ }
+
+ carry_global_memory_stat_delta(remaining_delta, index);
}
-void purge_account(PFS_thread *thread, PFS_account *account,
- PFS_user *safe_user, PFS_host *safe_host)
+PFS_account *sanitize_account(PFS_account *unsafe)
{
- account->aggregate(safe_user, safe_host);
+ return global_account_container.sanitize(unsafe);
+}
+void purge_account(PFS_thread *thread, PFS_account *account)
+{
LF_PINS *pins= get_account_hash_pins(thread);
if (unlikely(pins == NULL))
return;
@@ -544,6 +659,7 @@ void purge_account(PFS_thread *thread, PFS_account *account,
lf_hash_delete(&account_hash, pins,
account->m_key.m_hash_key,
account->m_key.m_key_length);
+ account->aggregate(false, account->m_user, account->m_host);
if (account->m_user != NULL)
{
account->m_user->release();
@@ -554,37 +670,78 @@ void purge_account(PFS_thread *thread, PFS_account *account,
account->m_host->release();
account->m_host= NULL;
}
- account->m_lock.allocated_to_free();
+ global_account_container.deallocate(account);
}
}
lf_hash_search_unpin(pins);
}
-/** Purge non connected user@host, reset stats of connected user@host. */
+class Proc_purge_account
+ : public PFS_buffer_processor<PFS_account>
+{
+public:
+ Proc_purge_account(PFS_thread *thread)
+ : m_thread(thread)
+ {}
+
+ virtual void operator()(PFS_account *pfs)
+ {
+ PFS_user *user= sanitize_user(pfs->m_user);
+ PFS_host *host= sanitize_host(pfs->m_host);
+ pfs->aggregate(true, user, host);
+
+ if (pfs->get_refcount() == 0)
+ purge_account(m_thread, pfs);
+ }
+
+private:
+ PFS_thread *m_thread;
+};
+
+/** Purge non connected accounts, reset stats of connected account. */
void purge_all_account(void)
{
PFS_thread *thread= PFS_thread::get_current_thread();
if (unlikely(thread == NULL))
return;
- PFS_account *pfs= account_array;
- PFS_account *pfs_last= account_array + account_max;
- PFS_user *user;
- PFS_host *host;
+ Proc_purge_account proc(thread);
+ global_account_container.apply(proc);
+}
- for ( ; pfs < pfs_last; pfs++)
+class Proc_update_accounts_derived_flags
+ : public PFS_buffer_processor<PFS_account>
+{
+public:
+ Proc_update_accounts_derived_flags(PFS_thread *thread)
+ : m_thread(thread)
+ {}
+
+ virtual void operator()(PFS_account *pfs)
{
- if (pfs->m_lock.is_populated())
+ if (pfs->m_username_length > 0 && pfs->m_hostname_length > 0)
{
- user= sanitize_user(pfs->m_user);
- host= sanitize_host(pfs->m_host);
- pfs->aggregate_stats(user, host);
-
- if (pfs->get_refcount() == 0)
- purge_account(thread, pfs, user, host);
+ lookup_setup_actor(m_thread,
+ pfs->m_username, pfs->m_username_length,
+ pfs->m_hostname, pfs->m_hostname_length,
+ & pfs->m_enabled, & pfs->m_history);
+ }
+ else
+ {
+ pfs->m_enabled= true;
+ pfs->m_history= true;
}
}
+
+private:
+ PFS_thread *m_thread;
+};
+
+void update_accounts_derived_flags(PFS_thread *thread)
+{
+ Proc_update_accounts_derived_flags proc(thread);
+ global_account_container.apply(proc);
}
/** @} */
diff --git a/storage/perfschema/pfs_account.h b/storage/perfschema/pfs_account.h
index cd7b1520df5..8a966f4c4a9 100644
--- a/storage/perfschema/pfs_account.h
+++ b/storage/perfschema/pfs_account.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -25,23 +25,26 @@
/**
@file storage/perfschema/pfs_account.h
- Performance schema user@host (declarations).
+ Performance schema account (declarations).
*/
#include "pfs_lock.h"
#include "lf.h"
#include "pfs_con_slice.h"
+#include "mysql_com.h" /* USERNAME_LENGTH */
struct PFS_global_param;
struct PFS_user;
struct PFS_host;
struct PFS_thread;
+struct PFS_memory_stat_delta;
/**
@addtogroup Performance_schema_buffers
@{
*/
+/** Hash key for an account. */
struct PFS_account_key
{
/**
@@ -53,6 +56,7 @@ struct PFS_account_key
uint m_key_length;
};
+/** Per account statistics. */
struct PFS_ALIGNED PFS_account : PFS_connection_slice
{
public:
@@ -76,16 +80,25 @@ public:
PFS_atomic::add_32(& m_refcount, -1);
}
- void aggregate(PFS_user *safe_user, PFS_host *safe_host);
+ void aggregate(bool alive, PFS_user *safe_user, PFS_host *safe_host);
void aggregate_waits(PFS_user *safe_user, PFS_host *safe_host);
void aggregate_stages(PFS_user *safe_user, PFS_host *safe_host);
void aggregate_statements(PFS_user *safe_user, PFS_host *safe_host);
+ void aggregate_transactions(PFS_user *safe_user, PFS_host *safe_host);
+ void aggregate_memory(bool alive, PFS_user *safe_user, PFS_host *safe_host);
+ void aggregate_status(PFS_user *safe_user, PFS_host *safe_host);
void aggregate_stats(PFS_user *safe_user, PFS_host *safe_host);
void release(void);
+ void carry_memory_stat_delta(PFS_memory_stat_delta *delta, uint index);
+
/** Internal lock. */
pfs_lock m_lock;
PFS_account_key m_key;
+ /** True if this account is enabled, per rules in table SETUP_ACTORS. */
+ bool m_enabled;
+ /** True if this account has history enabled, per rules in table SETUP_ACTORS. */
+ bool m_history;
const char *m_username;
uint m_username_length;
const char *m_hostname;
@@ -101,7 +114,7 @@ private:
int init_account(const PFS_global_param *param);
void cleanup_account(void);
-int init_account_hash(void);
+int init_account_hash(const PFS_global_param *param);
void cleanup_account_hash(void);
PFS_account *
@@ -112,15 +125,9 @@ find_or_create_account(PFS_thread *thread,
PFS_account *sanitize_account(PFS_account *unsafe);
void purge_all_account(void);
+void update_accounts_derived_flags(PFS_thread *thread);
-/* For iterators and show status. */
-
-extern ulong account_max;
-extern ulong account_lost;
-
-/* Exposing the data directly, for iterators. */
-
-extern PFS_account *account_array;
+/* For show status. */
extern LF_HASH account_hash;
diff --git a/storage/perfschema/pfs_atomic.h b/storage/perfschema/pfs_atomic.h
index 00d1197970b..959b66dccb2 100644
--- a/storage/perfschema/pfs_atomic.h
+++ b/storage/perfschema/pfs_atomic.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2009, 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, version 2.0,
@@ -35,101 +35,101 @@ class PFS_atomic
{
public:
/** Atomic load. */
- static inline int32 load_32(volatile int32 *ptr)
+ static inline int32 load_32(int32 *ptr)
{
return my_atomic_load32(ptr);
}
/** Atomic load. */
- static inline int64 load_64(volatile int64 *ptr)
+ static inline int64 load_64(int64 *ptr)
{
return my_atomic_load64(ptr);
}
/** Atomic load. */
- static inline uint32 load_u32(volatile uint32 *ptr)
+ static inline uint32 load_u32(uint32 *ptr)
{
return (uint32) my_atomic_load32((int32*) ptr);
}
/** Atomic load. */
- static inline uint64 load_u64(volatile uint64 *ptr)
+ static inline uint64 load_u64(uint64 *ptr)
{
return (uint64) my_atomic_load64((int64*) ptr);
}
/** Atomic store. */
- static inline void store_32(volatile int32 *ptr, int32 value)
+ static inline void store_32(int32 *ptr, int32 value)
{
my_atomic_store32(ptr, value);
}
/** Atomic store. */
- static inline void store_64(volatile int64 *ptr, int64 value)
+ static inline void store_64(int64 *ptr, int64 value)
{
my_atomic_store64(ptr, value);
}
/** Atomic store. */
- static inline void store_u32(volatile uint32 *ptr, uint32 value)
+ static inline void store_u32(uint32 *ptr, uint32 value)
{
my_atomic_store32((int32*) ptr, (int32) value);
}
/** Atomic store. */
- static inline void store_u64(volatile uint64 *ptr, uint64 value)
+ static inline void store_u64(uint64 *ptr, uint64 value)
{
my_atomic_store64((int64*) ptr, (int64) value);
}
/** Atomic add. */
- static inline int32 add_32(volatile int32 *ptr, int32 value)
+ static inline int32 add_32(int32 *ptr, int32 value)
{
return my_atomic_add32(ptr, value);
}
/** Atomic add. */
- static inline int64 add_64(volatile int64 *ptr, int64 value)
+ static inline int64 add_64(int64 *ptr, int64 value)
{
return my_atomic_add64(ptr, value);
}
/** Atomic add. */
- static inline uint32 add_u32(volatile uint32 *ptr, uint32 value)
+ static inline uint32 add_u32(uint32 *ptr, uint32 value)
{
return (uint32) my_atomic_add32((int32*) ptr, (int32) value);
}
/** Atomic add. */
- static inline uint64 add_u64(volatile uint64 *ptr, uint64 value)
+ static inline uint64 add_u64(uint64 *ptr, uint64 value)
{
return (uint64) my_atomic_add64((int64*) ptr, (int64) value);
}
/** Atomic compare and swap. */
- static inline bool cas_32(volatile int32 *ptr, int32 *old_value,
+ static inline bool cas_32(int32 *ptr, int32 *old_value,
int32 new_value)
{
return my_atomic_cas32(ptr, old_value, new_value);
}
/** Atomic compare and swap. */
- static inline bool cas_64(volatile int64 *ptr, int64 *old_value,
+ static inline bool cas_64(int64 *ptr, int64 *old_value,
int64 new_value)
{
return my_atomic_cas64(ptr, old_value, new_value);
}
/** Atomic compare and swap. */
- static inline bool cas_u32(volatile uint32 *ptr, uint32 *old_value,
+ static inline bool cas_u32(uint32 *ptr, uint32 *old_value,
uint32 new_value)
{
return my_atomic_cas32((int32*) ptr, (int32*) old_value,
- (uint32) new_value);
+ (uint32) new_value);
}
/** Atomic compare and swap. */
- static inline bool cas_u64(volatile uint64 *ptr, uint64 *old_value,
+ static inline bool cas_u64(uint64 *ptr, uint64 *old_value,
uint64 new_value)
{
return my_atomic_cas64((int64*) ptr, (int64*) old_value,
diff --git a/storage/perfschema/pfs_autosize.cc b/storage/perfschema/pfs_autosize.cc
index e15a85fe2d6..024f5519c0e 100644
--- a/storage/perfschema/pfs_autosize.cc
+++ b/storage/perfschema/pfs_autosize.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2012, 2015, 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, version 2.0,
@@ -30,47 +30,17 @@
#include "pfs_server.h"
#include "set_var.h"
+#include "my_thread.h" /* For pthread_t */
+/* Make sure HAVE_PSI_XXX_INTERFACE flags are set */
+#include "mysql/psi/psi.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;
-
+/** Performance schema sizing heuristics. */
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. */
@@ -83,103 +53,46 @@ struct PFS_sizing_data
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_events_transactions_history_sizing. */
+ ulong m_events_transactions_history_sizing;
+ /** Default value for @c PFS_param.m_events_transactions_history_long_sizing. */
+ ulong m_events_transactions_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 */
- 10, 100, 10, 100, 10, 100,
+ 5, 100, 5, 100, 5, 100, 5, 100,
/* Digests */
1000,
/* Session connect attrs. */
- 512,
- /* Min tables */
- 200,
- /* Load factors */
- 0.90f, 0.90f, 0.90f
+ 512
};
PFS_sizing_data medium_data=
{
- /* Account / user / host */
- 100, 100, 100,
/* History sizes */
- 20, 1000, 20, 1000, 20, 1000,
+ 10, 1000, 10, 1000, 10, 1000, 10, 1000,
/* Digests */
5000,
/* Session connect attrs. */
- 512,
- /* Min tables */
- 500,
- /* Load factors */
- 0.70f, 0.80f, 0.90f
+ 512
};
PFS_sizing_data large_data=
{
- /* Account / user / host */
- 100, 100, 100,
/* History sizes */
- 20, 10000, 20, 10000, 20, 10000,
+ 10, 10000, 10, 10000, 10, 10000, 10, 10000,
/* Digests */
10000,
/* Session connect attrs. */
- 512,
- /* Min tables */
- 10000,
- /* Load factors */
- 0.50f, 0.65f, 0.80f
+ 512
};
-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) &&
@@ -204,47 +117,6 @@ PFS_sizing_data *estimate_hints(PFS_global_param *param)
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;
-
- SYSVAR_AUTOSIZE(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);
- SYSVAR_AUTOSIZE(p->m_table_share_sizing,
- apply_load_factor(count, h->m_load_factor_static));
- }
-
- if (p->m_account_sizing < 0)
- {
- SYSVAR_AUTOSIZE(p->m_account_sizing,
- h->m_account_sizing);
- }
-
- if (p->m_user_sizing < 0)
- {
- SYSVAR_AUTOSIZE(p->m_user_sizing,
- h->m_user_sizing);
- }
-
- if (p->m_host_sizing < 0)
- {
- SYSVAR_AUTOSIZE(p->m_host_sizing,
- h->m_host_sizing);
- }
-
if (p->m_events_waits_history_sizing < 0)
{
SYSVAR_AUTOSIZE(p->m_events_waits_history_sizing,
@@ -287,107 +159,157 @@ static void apply_heuristic(PFS_global_param *p, PFS_sizing_data *h)
h->m_digest_sizing);
}
- if (p->m_session_connect_attrs_sizing < 0)
+ if (p->m_events_transactions_history_sizing < 0)
{
- SYSVAR_AUTOSIZE(p->m_session_connect_attrs_sizing,
- h->m_session_connect_attrs_sizing);
+ SYSVAR_AUTOSIZE(p->m_events_transactions_history_sizing,
+ h->m_events_transactions_history_sizing);
}
- if (p->m_mutex_sizing < 0)
+ if (p->m_events_transactions_history_long_sizing < 0)
{
- count= fixed_mutex_instances
- + con * mutex_per_connection
- + handle * mutex_per_handle
- + share * mutex_per_share;
-
- SYSVAR_AUTOSIZE(p->m_mutex_sizing,
- apply_load_factor(count, h->m_load_factor_volatile));
+ SYSVAR_AUTOSIZE(p->m_events_transactions_history_long_sizing,
+ h->m_events_transactions_history_long_sizing);
}
- if (p->m_rwlock_sizing < 0)
- {
- count= fixed_rwlock_instances
- + con * rwlock_per_connection
- + handle * rwlock_per_handle
- + share * rwlock_per_share;
-
- SYSVAR_AUTOSIZE(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;
-
- SYSVAR_AUTOSIZE(p->m_cond_sizing,
- apply_load_factor(count, h->m_load_factor_volatile));
- }
-
- if (p->m_file_sizing < 0)
+ if (p->m_session_connect_attrs_sizing < 0)
{
- count= fixed_file_instances
- + con * file_per_connection
- + handle * file_per_handle
- + share * file_per_share;
-
- count= max<ulong>(count, file);
- SYSVAR_AUTOSIZE(p->m_file_sizing,
- apply_load_factor(count, h->m_load_factor_normal));
+ SYSVAR_AUTOSIZE(p->m_session_connect_attrs_sizing,
+ h->m_session_connect_attrs_sizing);
}
+}
- if (p->m_socket_sizing < 0)
+void pfs_automated_sizing(PFS_global_param *param)
+{
+ if (param->m_enabled)
{
- count= fixed_socket_instances
- + con * socket_per_connection
- + handle * socket_per_handle
- + share * socket_per_share;
-
- SYSVAR_AUTOSIZE(p->m_socket_sizing,
- apply_load_factor(count, h->m_load_factor_volatile));
+#ifndef HAVE_PSI_MUTEX_INTERFACE
+ param->m_mutex_class_sizing= 0;
+ param->m_mutex_sizing= 0;
+#endif
+
+#ifndef HAVE_PSI_RWLOCK_INTERFACE
+ param->m_rwlock_class_sizing= 0;
+ param->m_rwlock_sizing= 0;
+#endif
+
+#ifndef HAVE_PSI_COND_INTERFACE
+ param->m_cond_class_sizing= 0;
+ param->m_cond_sizing= 0;
+#endif
+
+#ifndef HAVE_PSI_FILE_INTERFACE
+ param->m_file_class_sizing= 0;
+ param->m_file_sizing= 0;
+ param->m_file_handle_sizing= 0;
+#endif
+
+#ifndef HAVE_PSI_TABLE_INTERFACE
+ param->m_table_share_sizing= 0;
+ param->m_table_sizing= 0;
+ param->m_table_lock_stat_sizing= 0;
+ param->m_index_stat_sizing= 0;
+#endif
+
+#ifndef HAVE_PSI_SOCKET_INTERFACE
+ param->m_socket_class_sizing= 0;
+ param->m_socket_sizing= 0;
+#endif
+
+#ifndef HAVE_PSI_STAGE_INTERFACE
+ param->m_stage_class_sizing= 0;
+ param->m_events_stages_history_sizing= 0;
+ param->m_events_stages_history_long_sizing= 0;
+#endif
+
+#ifndef HAVE_PSI_STATEMENT_INTERFACE
+ param->m_statement_class_sizing= 0;
+ param->m_events_statements_history_sizing= 0;
+ param->m_events_statements_history_long_sizing= 0;
+#endif
+
+#ifndef HAVE_PSI_SP_INTERFACE
+ param->m_program_sizing= 0;
+ if (param->m_statement_stack_sizing > 1)
+ param->m_statement_stack_sizing= 1;
+#endif
+
+#ifndef HAVE_PSI_PS_INTERFACE
+ param->m_prepared_stmt_sizing= 0;
+#endif
+
+#ifndef HAVE_PSI_STATEMENT_DIGEST_INTERFACE
+ param->m_digest_sizing= 0;
+#endif
+
+#ifndef HAVE_PSI_METADATA_INTERFACE
+ param->m_metadata_lock_sizing= 0;
+#endif
+
+#ifndef HAVE_PSI_MEMORY_INTERFACE
+ param->m_memory_class_sizing= 0;
+#endif
+
+ PFS_sizing_data *heuristic;
+ heuristic= estimate_hints(param);
+ apply_heuristic(param, heuristic);
+
+ 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_events_transactions_history_sizing >= 0);
+ DBUG_ASSERT(param->m_events_transactions_history_long_sizing >= 0);
+ DBUG_ASSERT(param->m_session_connect_attrs_sizing >= 0);
}
-
- if (p->m_thread_sizing < 0)
+ else
{
- count= fixed_thread_instances
- + con * thread_per_connection
- + handle * thread_per_handle
- + share * thread_per_share;
-
- SYSVAR_AUTOSIZE(p->m_thread_sizing,
- apply_load_factor(count, h->m_load_factor_volatile));
+ /*
+ The Performance Schema is disabled. Set the instrument sizings to zero to
+ disable all instrumentation while retaining support for the status and
+ system variable tables, the host cache table and the replication tables.
+ */
+ SYSVAR_AUTOSIZE(param->m_mutex_class_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_rwlock_class_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_cond_class_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_thread_class_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_table_share_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_table_lock_stat_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_index_stat_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_file_class_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_mutex_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_rwlock_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_cond_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_thread_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_table_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_file_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_file_handle_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_socket_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_socket_class_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_events_waits_history_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_events_waits_history_long_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_setup_actor_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_setup_object_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_host_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_user_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_account_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_stage_class_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_events_stages_history_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_events_stages_history_long_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_statement_class_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_events_statements_history_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_events_statements_history_long_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_digest_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_program_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_prepared_stmt_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_events_transactions_history_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_events_transactions_history_long_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_session_connect_attrs_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_statement_stack_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_memory_class_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_metadata_lock_sizing, 0);
+ SYSVAR_AUTOSIZE(param->m_max_digest_length, 0);
+ SYSVAR_AUTOSIZE(param->m_max_sql_text_length, 0);
}
}
-
-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_buffer_container.cc b/storage/perfschema/pfs_buffer_container.cc
new file mode 100644
index 00000000000..cd87cb247e2
--- /dev/null
+++ b/storage/perfschema/pfs_buffer_container.cc
@@ -0,0 +1,883 @@
+/* Copyright (c) 2014, 2016, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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 "pfs_global.h"
+#include "pfs_lock.h"
+#include "pfs_account.h"
+#include "pfs_user.h"
+#include "pfs_host.h"
+#include "pfs_buffer_container.h"
+#include "pfs_builtin_memory.h"
+
+PFS_buffer_default_allocator<PFS_mutex> default_mutex_allocator(& builtin_memory_mutex);
+PFS_mutex_container global_mutex_container(& default_mutex_allocator);
+
+PFS_buffer_default_allocator<PFS_rwlock> default_rwlock_allocator(& builtin_memory_rwlock);
+PFS_rwlock_container global_rwlock_container(& default_rwlock_allocator);
+
+PFS_buffer_default_allocator<PFS_cond> default_cond_allocator(& builtin_memory_cond);
+PFS_cond_container global_cond_container(& default_cond_allocator);
+
+PFS_buffer_default_allocator<PFS_file> default_file_allocator(& builtin_memory_file);
+PFS_file_container global_file_container(& default_file_allocator);
+
+PFS_buffer_default_allocator<PFS_socket> default_socket_allocator(& builtin_memory_socket);
+PFS_socket_container global_socket_container(& default_socket_allocator);
+
+PFS_buffer_default_allocator<PFS_metadata_lock> default_mdl_allocator(& builtin_memory_mdl);
+PFS_mdl_container global_mdl_container(& default_mdl_allocator);
+
+PFS_buffer_default_allocator<PFS_setup_actor> default_setup_actor_allocator(& builtin_memory_setup_actor);
+PFS_setup_actor_container global_setup_actor_container(& default_setup_actor_allocator);
+
+PFS_buffer_default_allocator<PFS_setup_object> default_setup_object_allocator(& builtin_memory_setup_object);
+PFS_setup_object_container global_setup_object_container(& default_setup_object_allocator);
+
+PFS_buffer_default_allocator<PFS_table> default_table_allocator(& builtin_memory_table);
+PFS_table_container global_table_container(& default_table_allocator);
+
+PFS_buffer_default_allocator<PFS_table_share> default_table_share_allocator(& builtin_memory_table_share);
+PFS_table_share_container global_table_share_container(& default_table_share_allocator);
+
+PFS_buffer_default_allocator<PFS_table_share_index> default_table_share_index_allocator(& builtin_memory_table_share_index);
+PFS_table_share_index_container global_table_share_index_container(& default_table_share_index_allocator);
+
+PFS_buffer_default_allocator<PFS_table_share_lock> default_table_share_lock_allocator(& builtin_memory_table_share_lock);
+PFS_table_share_lock_container global_table_share_lock_container(& default_table_share_lock_allocator);
+
+PFS_buffer_default_allocator<PFS_program> default_program_allocator(& builtin_memory_program);
+PFS_program_container global_program_container(& default_program_allocator);
+
+PFS_buffer_default_allocator<PFS_prepared_stmt> default_prepared_stmt_allocator(& builtin_memory_prepared_stmt);
+PFS_prepared_stmt_container global_prepared_stmt_container(& default_prepared_stmt_allocator);
+
+int PFS_account_allocator::alloc_array(PFS_account_array *array)
+{
+ size_t size= array->m_max;
+ size_t index;
+ size_t waits_sizing= size * wait_class_max;
+ size_t stages_sizing= size * stage_class_max;
+ size_t statements_sizing= size * statement_class_max;
+ size_t transactions_sizing= size * transaction_class_max;
+ size_t memory_sizing= size * memory_class_max;
+
+ array->m_ptr= NULL;
+ array->m_full= true;
+ array->m_instr_class_waits_array= NULL;
+ array->m_instr_class_stages_array= NULL;
+ array->m_instr_class_statements_array= NULL;
+ array->m_instr_class_transactions_array= NULL;
+ array->m_instr_class_memory_array= NULL;
+
+ if (size > 0)
+ {
+ array->m_ptr=
+ PFS_MALLOC_ARRAY(& builtin_memory_account,
+ size, sizeof(PFS_account), PFS_account, MYF(MY_ZEROFILL));
+ if (array->m_ptr == NULL)
+ return 1;
+ }
+
+ if (waits_sizing > 0)
+ {
+ array->m_instr_class_waits_array=
+ PFS_MALLOC_ARRAY(& builtin_memory_account_waits,
+ waits_sizing, sizeof(PFS_single_stat), PFS_single_stat, MYF(MY_ZEROFILL));
+ if (array->m_instr_class_waits_array == NULL)
+ return 1;
+
+ for (index=0; index < waits_sizing; index++)
+ array->m_instr_class_waits_array[index].reset();
+ }
+
+ if (stages_sizing > 0)
+ {
+ array->m_instr_class_stages_array=
+ PFS_MALLOC_ARRAY(& builtin_memory_account_stages,
+ stages_sizing, sizeof(PFS_stage_stat), PFS_stage_stat, MYF(MY_ZEROFILL));
+ if (array->m_instr_class_stages_array == NULL)
+ return 1;
+
+ for (index=0; index < stages_sizing; index++)
+ array->m_instr_class_stages_array[index].reset();
+ }
+
+ if (statements_sizing > 0)
+ {
+ array->m_instr_class_statements_array=
+ PFS_MALLOC_ARRAY(& builtin_memory_account_statements,
+ statements_sizing, sizeof(PFS_statement_stat), PFS_statement_stat, MYF(MY_ZEROFILL));
+ if (array->m_instr_class_statements_array == NULL)
+ return 1;
+
+ for (index=0; index < statements_sizing; index++)
+ array->m_instr_class_statements_array[index].reset();
+ }
+
+ if (transactions_sizing > 0)
+ {
+ array->m_instr_class_transactions_array=
+ PFS_MALLOC_ARRAY(& builtin_memory_account_transactions,
+ transactions_sizing, sizeof(PFS_transaction_stat), PFS_transaction_stat, MYF(MY_ZEROFILL));
+ if (array->m_instr_class_transactions_array == NULL)
+ return 1;
+
+ for (index=0; index < transactions_sizing; index++)
+ array->m_instr_class_transactions_array[index].reset();
+ }
+
+ if (memory_sizing > 0)
+ {
+ array->m_instr_class_memory_array=
+ PFS_MALLOC_ARRAY(& builtin_memory_account_memory,
+ memory_sizing, sizeof(PFS_memory_stat), PFS_memory_stat, MYF(MY_ZEROFILL));
+ if (array->m_instr_class_memory_array == NULL)
+ return 1;
+
+ for (index=0; index < memory_sizing; index++)
+ array->m_instr_class_memory_array[index].reset();
+ }
+
+ for (index= 0; index < size; index++)
+ {
+ array->m_ptr[index].set_instr_class_waits_stats(
+ & array->m_instr_class_waits_array[index * wait_class_max]);
+ array->m_ptr[index].set_instr_class_stages_stats(
+ & array->m_instr_class_stages_array[index * stage_class_max]);
+ array->m_ptr[index].set_instr_class_statements_stats(
+ & array->m_instr_class_statements_array[index * statement_class_max]);
+ array->m_ptr[index].set_instr_class_transactions_stats(
+ & array->m_instr_class_transactions_array[index * transaction_class_max]);
+ array->m_ptr[index].set_instr_class_memory_stats(
+ & array->m_instr_class_memory_array[index * memory_class_max]);
+ }
+
+ array->m_full= false;
+ return 0;
+}
+
+void PFS_account_allocator::free_array(PFS_account_array *array)
+{
+ size_t size= array->m_max;
+ size_t waits_sizing= size * wait_class_max;
+ size_t stages_sizing= size * stage_class_max;
+ size_t statements_sizing= size * statement_class_max;
+ size_t transactions_sizing= size * transaction_class_max;
+ size_t memory_sizing= size * memory_class_max;
+
+ PFS_FREE_ARRAY(& builtin_memory_account,
+ size, sizeof(PFS_account), array->m_ptr);
+ array->m_ptr= NULL;
+
+ PFS_FREE_ARRAY(& builtin_memory_account_waits,
+ waits_sizing, sizeof(PFS_single_stat),
+ array->m_instr_class_waits_array);
+ array->m_instr_class_waits_array= NULL;
+
+ PFS_FREE_ARRAY(& builtin_memory_account_stages,
+ stages_sizing, sizeof(PFS_stage_stat),
+ array->m_instr_class_stages_array);
+ array->m_instr_class_stages_array= NULL;
+
+ PFS_FREE_ARRAY(& builtin_memory_account_statements,
+ statements_sizing, sizeof(PFS_statement_stat),
+ array->m_instr_class_statements_array);
+ array->m_instr_class_statements_array= NULL;
+
+ PFS_FREE_ARRAY(& builtin_memory_account_transactions,
+ transactions_sizing, sizeof(PFS_transaction_stat),
+ array->m_instr_class_transactions_array);
+ array->m_instr_class_transactions_array= NULL;
+
+ PFS_FREE_ARRAY(& builtin_memory_account_memory,
+ memory_sizing, sizeof(PFS_memory_stat),
+ array->m_instr_class_memory_array);
+ array->m_instr_class_memory_array= NULL;
+}
+
+PFS_account_allocator account_allocator;
+PFS_account_container global_account_container(& account_allocator);
+
+int PFS_host_allocator::alloc_array(PFS_host_array *array)
+{
+ size_t size= array->m_max;
+ PFS_host *pfs;
+ size_t index;
+ size_t waits_sizing= size * wait_class_max;
+ size_t stages_sizing= size * stage_class_max;
+ size_t statements_sizing= size * statement_class_max;
+ size_t transactions_sizing= size * transaction_class_max;
+ size_t memory_sizing= size * memory_class_max;
+
+ array->m_ptr= NULL;
+ array->m_full= true;
+ array->m_instr_class_waits_array= NULL;
+ array->m_instr_class_stages_array= NULL;
+ array->m_instr_class_statements_array= NULL;
+ array->m_instr_class_transactions_array= NULL;
+ array->m_instr_class_memory_array= NULL;
+
+ if (size > 0)
+ {
+ array->m_ptr=
+ PFS_MALLOC_ARRAY(& builtin_memory_host,
+ size, sizeof(PFS_host), PFS_host, MYF(MY_ZEROFILL));
+ if (array->m_ptr == NULL)
+ return 1;
+ }
+
+ if (waits_sizing > 0)
+ {
+ array->m_instr_class_waits_array=
+ PFS_MALLOC_ARRAY(& builtin_memory_host_waits,
+ waits_sizing, sizeof(PFS_single_stat), PFS_single_stat, MYF(MY_ZEROFILL));
+ if (array->m_instr_class_waits_array == NULL)
+ return 1;
+
+ for (index=0; index < waits_sizing; index++)
+ array->m_instr_class_waits_array[index].reset();
+ }
+
+ if (stages_sizing > 0)
+ {
+ array->m_instr_class_stages_array=
+ PFS_MALLOC_ARRAY(& builtin_memory_host_stages,
+ stages_sizing, sizeof(PFS_stage_stat), PFS_stage_stat, MYF(MY_ZEROFILL));
+ if (array->m_instr_class_stages_array == NULL)
+ return 1;
+
+ for (index=0; index < stages_sizing; index++)
+ array->m_instr_class_stages_array[index].reset();
+ }
+
+ if (statements_sizing > 0)
+ {
+ array->m_instr_class_statements_array=
+ PFS_MALLOC_ARRAY(& builtin_memory_host_statements,
+ statements_sizing, sizeof(PFS_statement_stat), PFS_statement_stat, MYF(MY_ZEROFILL));
+ if (array->m_instr_class_statements_array == NULL)
+ return 1;
+
+ for (index=0; index < statements_sizing; index++)
+ array->m_instr_class_statements_array[index].reset();
+ }
+
+ if (transactions_sizing > 0)
+ {
+ array->m_instr_class_transactions_array=
+ PFS_MALLOC_ARRAY(& builtin_memory_host_transactions,
+ transactions_sizing, sizeof(PFS_transaction_stat), PFS_transaction_stat, MYF(MY_ZEROFILL));
+ if (array->m_instr_class_transactions_array == NULL)
+ return 1;
+
+ for (index=0; index < transactions_sizing; index++)
+ array->m_instr_class_transactions_array[index].reset();
+ }
+
+ if (memory_sizing > 0)
+ {
+ array->m_instr_class_memory_array=
+ PFS_MALLOC_ARRAY(& builtin_memory_host_memory,
+ memory_sizing, sizeof(PFS_memory_stat), PFS_memory_stat, MYF(MY_ZEROFILL));
+ if (array->m_instr_class_memory_array == NULL)
+ return 1;
+
+ for (index=0; index < memory_sizing; index++)
+ array->m_instr_class_memory_array[index].reset();
+ }
+
+ for (index= 0; index < size; index++)
+ {
+ pfs= & array->m_ptr[index];
+
+ pfs->set_instr_class_waits_stats(
+ & array->m_instr_class_waits_array[index * wait_class_max]);
+ pfs->set_instr_class_stages_stats(
+ & array->m_instr_class_stages_array[index * stage_class_max]);
+ pfs->set_instr_class_statements_stats(
+ & array->m_instr_class_statements_array[index * statement_class_max]);
+ pfs->set_instr_class_transactions_stats(
+ & array->m_instr_class_transactions_array[index * transaction_class_max]);
+ pfs->set_instr_class_memory_stats(
+ & array->m_instr_class_memory_array[index * memory_class_max]);
+ }
+
+ array->m_full= false;
+ return 0;
+}
+
+void PFS_host_allocator::free_array(PFS_host_array *array)
+{
+ size_t size= array->m_max;
+ size_t waits_sizing= size * wait_class_max;
+ size_t stages_sizing= size * stage_class_max;
+ size_t statements_sizing= size * statement_class_max;
+ size_t transactions_sizing= size * transaction_class_max;
+ size_t memory_sizing= size * memory_class_max;
+
+ PFS_FREE_ARRAY(& builtin_memory_host,
+ size, sizeof(PFS_host), array->m_ptr);
+ array->m_ptr= NULL;
+
+ PFS_FREE_ARRAY(& builtin_memory_host_waits,
+ waits_sizing, sizeof(PFS_single_stat),
+ array->m_instr_class_waits_array);
+ array->m_instr_class_waits_array= NULL;
+
+ PFS_FREE_ARRAY(& builtin_memory_host_stages,
+ stages_sizing, sizeof(PFS_stage_stat),
+ array->m_instr_class_stages_array);
+ array->m_instr_class_stages_array= NULL;
+
+ PFS_FREE_ARRAY(& builtin_memory_host_statements,
+ statements_sizing, sizeof(PFS_statement_stat),
+ array->m_instr_class_statements_array);
+ array->m_instr_class_statements_array= NULL;
+
+ PFS_FREE_ARRAY(& builtin_memory_host_transactions,
+ transactions_sizing, sizeof(PFS_transaction_stat),
+ array->m_instr_class_transactions_array);
+ array->m_instr_class_transactions_array= NULL;
+
+ PFS_FREE_ARRAY(& builtin_memory_host_memory,
+ memory_sizing, sizeof(PFS_memory_stat),
+ array->m_instr_class_memory_array);
+ array->m_instr_class_memory_array= NULL;
+}
+
+PFS_host_allocator host_allocator;
+PFS_host_container global_host_container(& host_allocator);
+
+int PFS_thread_allocator::alloc_array(PFS_thread_array *array)
+{
+ size_t size= array->m_max;
+ PFS_thread *pfs;
+ PFS_events_statements *pfs_stmt;
+ unsigned char *pfs_tokens;
+
+ size_t index;
+ size_t waits_sizing= size * wait_class_max;
+ size_t stages_sizing= size * stage_class_max;
+ size_t statements_sizing= size * statement_class_max;
+ size_t transactions_sizing= size * transaction_class_max;
+ size_t memory_sizing= size * memory_class_max;
+
+ size_t waits_history_sizing= size * events_waits_history_per_thread;
+ size_t stages_history_sizing= size * events_stages_history_per_thread;
+ size_t statements_history_sizing= size * events_statements_history_per_thread;
+ size_t statements_stack_sizing= size * statement_stack_max;
+ size_t transactions_history_sizing= size * events_transactions_history_per_thread;
+ size_t session_connect_attrs_sizing= size * session_connect_attrs_size_per_thread;
+
+ size_t current_sqltext_sizing= size * pfs_max_sqltext * statement_stack_max;
+ size_t history_sqltext_sizing= size * pfs_max_sqltext * events_statements_history_per_thread;
+ size_t current_digest_tokens_sizing= size * pfs_max_digest_length * statement_stack_max;
+ size_t history_digest_tokens_sizing= size * pfs_max_digest_length * events_statements_history_per_thread;
+
+ array->m_ptr= NULL;
+ array->m_full= true;
+ array->m_instr_class_waits_array= NULL;
+ array->m_instr_class_stages_array= NULL;
+ array->m_instr_class_statements_array= NULL;
+ array->m_instr_class_transactions_array= NULL;
+ array->m_instr_class_memory_array= NULL;
+
+ array->m_waits_history_array= NULL;
+ array->m_stages_history_array= NULL;
+ array->m_statements_history_array= NULL;
+ array->m_statements_stack_array= NULL;
+ array->m_transactions_history_array= NULL;
+ array->m_session_connect_attrs_array= NULL;
+
+ array->m_current_stmts_text_array= NULL;
+ array->m_current_stmts_digest_token_array= NULL;
+ array->m_history_stmts_text_array= NULL;
+ array->m_history_stmts_digest_token_array= NULL;
+
+ if (size > 0)
+ {
+ array->m_ptr=
+ PFS_MALLOC_ARRAY(& builtin_memory_thread,
+ size, sizeof(PFS_thread), PFS_thread, MYF(MY_ZEROFILL));
+ if (array->m_ptr == NULL)
+ return 1;
+ }
+
+ if (waits_sizing > 0)
+ {
+ array->m_instr_class_waits_array=
+ PFS_MALLOC_ARRAY(& builtin_memory_thread_waits,
+ waits_sizing, sizeof(PFS_single_stat), PFS_single_stat, MYF(MY_ZEROFILL));
+ if (array->m_instr_class_waits_array == NULL)
+ return 1;
+
+ for (index=0; index < waits_sizing; index++)
+ array->m_instr_class_waits_array[index].reset();
+ }
+
+ if (stages_sizing > 0)
+ {
+ array->m_instr_class_stages_array=
+ PFS_MALLOC_ARRAY(& builtin_memory_thread_stages,
+ stages_sizing, sizeof(PFS_stage_stat), PFS_stage_stat, MYF(MY_ZEROFILL));
+ if (array->m_instr_class_stages_array == NULL)
+ return 1;
+
+ for (index=0; index < stages_sizing; index++)
+ array->m_instr_class_stages_array[index].reset();
+ }
+
+ if (statements_sizing > 0)
+ {
+ array->m_instr_class_statements_array=
+ PFS_MALLOC_ARRAY(& builtin_memory_thread_statements,
+ statements_sizing, sizeof(PFS_statement_stat), PFS_statement_stat, MYF(MY_ZEROFILL));
+ if (array->m_instr_class_statements_array == NULL)
+ return 1;
+
+ for (index=0; index < statements_sizing; index++)
+ array->m_instr_class_statements_array[index].reset();
+ }
+
+ if (transactions_sizing > 0)
+ {
+ array->m_instr_class_transactions_array=
+ PFS_MALLOC_ARRAY(& builtin_memory_thread_transactions,
+ transactions_sizing, sizeof(PFS_transaction_stat), PFS_transaction_stat, MYF(MY_ZEROFILL));
+ if (array->m_instr_class_transactions_array == NULL)
+ return 1;
+
+ for (index=0; index < transactions_sizing; index++)
+ array->m_instr_class_transactions_array[index].reset();
+ }
+
+ if (memory_sizing > 0)
+ {
+ array->m_instr_class_memory_array=
+ PFS_MALLOC_ARRAY(& builtin_memory_thread_memory,
+ memory_sizing, sizeof(PFS_memory_stat), PFS_memory_stat, MYF(MY_ZEROFILL));
+ if (array->m_instr_class_memory_array == NULL)
+ return 1;
+
+ for (index=0; index < memory_sizing; index++)
+ array->m_instr_class_memory_array[index].reset();
+ }
+
+ if (waits_history_sizing > 0)
+ {
+ array->m_waits_history_array=
+ PFS_MALLOC_ARRAY(& builtin_memory_thread_waits_history,
+ waits_history_sizing, sizeof(PFS_events_waits), PFS_events_waits, MYF(MY_ZEROFILL));
+ if (unlikely(array->m_waits_history_array == NULL))
+ return 1;
+ }
+
+ if (stages_history_sizing > 0)
+ {
+ array->m_stages_history_array=
+ PFS_MALLOC_ARRAY(& builtin_memory_thread_stages_history,
+ stages_history_sizing, sizeof(PFS_events_stages), PFS_events_stages, MYF(MY_ZEROFILL));
+ if (unlikely(array->m_stages_history_array == NULL))
+ return 1;
+ }
+
+ if (statements_history_sizing > 0)
+ {
+ array->m_statements_history_array=
+ PFS_MALLOC_ARRAY(& builtin_memory_thread_statements_history,
+ statements_history_sizing, sizeof(PFS_events_statements), PFS_events_statements, MYF(MY_ZEROFILL));
+ if (unlikely(array->m_statements_history_array == NULL))
+ return 1;
+ }
+
+ if (statements_stack_sizing > 0)
+ {
+ array->m_statements_stack_array=
+ PFS_MALLOC_ARRAY(& builtin_memory_thread_statements_stack,
+ statements_stack_sizing, sizeof(PFS_events_statements), PFS_events_statements, MYF(MY_ZEROFILL));
+ if (unlikely(array->m_statements_stack_array == NULL))
+ return 1;
+ }
+
+ if (transactions_history_sizing > 0)
+ {
+ array->m_transactions_history_array=
+ PFS_MALLOC_ARRAY(& builtin_memory_thread_transaction_history,
+ transactions_history_sizing, sizeof(PFS_events_transactions), PFS_events_transactions, MYF(MY_ZEROFILL));
+ if (unlikely(array->m_transactions_history_array == NULL))
+ return 1;
+ }
+
+ if (session_connect_attrs_sizing > 0)
+ {
+ array->m_session_connect_attrs_array=
+ (char *)pfs_malloc(& builtin_memory_thread_session_connect_attrs,
+ session_connect_attrs_sizing, MYF(MY_ZEROFILL));
+ if (unlikely(array->m_session_connect_attrs_array == NULL))
+ return 1;
+ }
+
+ if (current_sqltext_sizing > 0)
+ {
+ array->m_current_stmts_text_array=
+ (char *)pfs_malloc(& builtin_memory_thread_statements_stack_sqltext,
+ current_sqltext_sizing, MYF(MY_ZEROFILL));
+ if (unlikely(array->m_current_stmts_text_array == NULL))
+ return 1;
+ }
+
+ if (history_sqltext_sizing > 0)
+ {
+ array->m_history_stmts_text_array=
+ (char *)pfs_malloc(& builtin_memory_thread_statements_history_sqltext,
+ history_sqltext_sizing, MYF(MY_ZEROFILL));
+ if (unlikely(array->m_history_stmts_text_array == NULL))
+ return 1;
+ }
+
+ if (current_digest_tokens_sizing > 0)
+ {
+ array->m_current_stmts_digest_token_array=
+ (unsigned char *)pfs_malloc(& builtin_memory_thread_statements_stack_tokens,
+ current_digest_tokens_sizing, MYF(MY_ZEROFILL));
+ if (unlikely(array->m_current_stmts_digest_token_array == NULL))
+ return 1;
+ }
+
+ if (history_digest_tokens_sizing > 0)
+ {
+ array->m_history_stmts_digest_token_array=
+ (unsigned char *)pfs_malloc(& builtin_memory_thread_statements_history_tokens,
+ history_digest_tokens_sizing, MYF(MY_ZEROFILL));
+ if (unlikely(array->m_history_stmts_digest_token_array == NULL))
+ return 1;
+ }
+
+ for (index= 0; index < size; index++)
+ {
+ pfs= & array->m_ptr[index];
+
+ pfs->set_instr_class_waits_stats(
+ & array->m_instr_class_waits_array[index * wait_class_max]);
+ pfs->set_instr_class_stages_stats(
+ & array->m_instr_class_stages_array[index * stage_class_max]);
+ pfs->set_instr_class_statements_stats(
+ & array->m_instr_class_statements_array[index * statement_class_max]);
+ pfs->set_instr_class_transactions_stats(
+ & array->m_instr_class_transactions_array[index * transaction_class_max]);
+ pfs->set_instr_class_memory_stats(
+ & array->m_instr_class_memory_array[index * memory_class_max]);
+
+ pfs->m_waits_history=
+ & array->m_waits_history_array[index * events_waits_history_per_thread];
+ pfs->m_stages_history=
+ & array->m_stages_history_array[index * events_stages_history_per_thread];
+ pfs->m_statements_history=
+ & array->m_statements_history_array[index * events_statements_history_per_thread];
+ pfs->m_statement_stack=
+ & array->m_statements_stack_array[index * statement_stack_max];
+ pfs->m_transactions_history=
+ & array->m_transactions_history_array[index * events_transactions_history_per_thread];
+ pfs->m_session_connect_attrs=
+ & array->m_session_connect_attrs_array[index * session_connect_attrs_size_per_thread];
+ }
+
+ for (index= 0; index < statements_stack_sizing; index++)
+ {
+ pfs_stmt= & array->m_statements_stack_array[index];
+
+ pfs_stmt->m_sqltext= & array->m_current_stmts_text_array[index * pfs_max_sqltext];
+
+ pfs_tokens= & array->m_current_stmts_digest_token_array[index * pfs_max_digest_length];
+ pfs_stmt->m_digest_storage.reset(pfs_tokens, pfs_max_digest_length);
+ }
+
+ for (index= 0; index < statements_history_sizing; index++)
+ {
+ pfs_stmt= & array->m_statements_history_array[index];
+
+ pfs_stmt->m_sqltext= & array->m_history_stmts_text_array[index * pfs_max_sqltext];
+
+ pfs_tokens= & array->m_history_stmts_digest_token_array[index * pfs_max_digest_length];
+ pfs_stmt->m_digest_storage.reset(pfs_tokens, pfs_max_digest_length);
+ }
+
+ array->m_full= false;
+ return 0;
+}
+
+void PFS_thread_allocator::free_array(PFS_thread_array *array)
+{
+ size_t size= array->m_max;
+ size_t waits_sizing= size * wait_class_max;
+ size_t stages_sizing= size * stage_class_max;
+ size_t statements_sizing= size * statement_class_max;
+ size_t transactions_sizing= size * transaction_class_max;
+ size_t memory_sizing= size * memory_class_max;
+
+ size_t waits_history_sizing= size * events_waits_history_per_thread;
+ size_t stages_history_sizing= size * events_stages_history_per_thread;
+ size_t statements_history_sizing= size * events_statements_history_per_thread;
+ size_t statements_stack_sizing= size * statement_stack_max;
+ size_t transactions_history_sizing= size * events_transactions_history_per_thread;
+ size_t session_connect_attrs_sizing= size * session_connect_attrs_size_per_thread;
+
+ size_t current_sqltext_sizing= size * pfs_max_sqltext * statement_stack_max;
+ size_t history_sqltext_sizing= size * pfs_max_sqltext * events_statements_history_per_thread;
+ size_t current_digest_tokens_sizing= size * pfs_max_digest_length * statement_stack_max;
+ size_t history_digest_tokens_sizing= size * pfs_max_digest_length * events_statements_history_per_thread;
+
+ PFS_FREE_ARRAY(& builtin_memory_thread,
+ size, sizeof(PFS_thread), array->m_ptr);
+ array->m_ptr= NULL;
+
+ PFS_FREE_ARRAY(& builtin_memory_thread_waits,
+ waits_sizing, sizeof(PFS_single_stat),
+ array->m_instr_class_waits_array);
+ array->m_instr_class_waits_array= NULL;
+
+ PFS_FREE_ARRAY(& builtin_memory_thread_stages,
+ stages_sizing, sizeof(PFS_stage_stat),
+ array->m_instr_class_stages_array);
+ array->m_instr_class_stages_array= NULL;
+
+ PFS_FREE_ARRAY(& builtin_memory_thread_statements,
+ statements_sizing, sizeof(PFS_statement_stat),
+ array->m_instr_class_statements_array);
+ array->m_instr_class_statements_array= NULL;
+
+ PFS_FREE_ARRAY(& builtin_memory_thread_transactions,
+ transactions_sizing, sizeof(PFS_transaction_stat),
+ array->m_instr_class_transactions_array);
+ array->m_instr_class_transactions_array= NULL;
+
+ PFS_FREE_ARRAY(& builtin_memory_thread_memory,
+ memory_sizing, sizeof(PFS_memory_stat),
+ array->m_instr_class_memory_array);
+ array->m_instr_class_memory_array= NULL;
+
+
+ PFS_FREE_ARRAY(& builtin_memory_thread_waits_history,
+ waits_history_sizing, sizeof(PFS_events_waits),
+ array->m_waits_history_array);
+ array->m_waits_history_array= NULL;
+
+ PFS_FREE_ARRAY(& builtin_memory_thread_stages_history,
+ stages_history_sizing, sizeof(PFS_events_stages),
+ array->m_stages_history_array);
+ array->m_stages_history_array= NULL;
+
+ PFS_FREE_ARRAY(& builtin_memory_thread_statements_history,
+ statements_history_sizing, sizeof(PFS_events_statements),
+ array->m_statements_history_array);
+ array->m_statements_history_array= NULL;
+
+ PFS_FREE_ARRAY(& builtin_memory_thread_statements_stack,
+ statements_stack_sizing, sizeof(PFS_events_statements),
+ array->m_statements_stack_array);
+ array->m_statements_stack_array= NULL;
+
+ PFS_FREE_ARRAY(& builtin_memory_thread_transaction_history,
+ transactions_history_sizing, sizeof(PFS_events_transactions),
+ array->m_transactions_history_array);
+ array->m_transactions_history_array= NULL;
+
+ pfs_free(& builtin_memory_thread_session_connect_attrs,
+ session_connect_attrs_sizing,
+ array->m_session_connect_attrs_array);
+ array->m_session_connect_attrs_array= NULL;
+
+ pfs_free(& builtin_memory_thread_statements_stack_sqltext,
+ current_sqltext_sizing,
+ array->m_current_stmts_text_array);
+ array->m_current_stmts_text_array= NULL;
+
+ pfs_free(& builtin_memory_thread_statements_history_sqltext,
+ history_sqltext_sizing,
+ array->m_history_stmts_text_array);
+ array->m_history_stmts_text_array= NULL;
+
+ pfs_free(& builtin_memory_thread_statements_stack_tokens,
+ current_digest_tokens_sizing,
+ array->m_current_stmts_digest_token_array);
+ array->m_current_stmts_digest_token_array= NULL;
+
+ pfs_free(& builtin_memory_thread_statements_history_tokens,
+ history_digest_tokens_sizing,
+ array->m_history_stmts_digest_token_array);
+ array->m_history_stmts_digest_token_array= NULL;
+}
+
+PFS_thread_allocator thread_allocator;
+PFS_thread_container global_thread_container(& thread_allocator);
+
+int PFS_user_allocator::alloc_array(PFS_user_array *array)
+{
+ size_t size= array->m_max;
+ PFS_user *pfs;
+ size_t index;
+ size_t waits_sizing= size * wait_class_max;
+ size_t stages_sizing= size * stage_class_max;
+ size_t statements_sizing= size * statement_class_max;
+ size_t transactions_sizing= size * transaction_class_max;
+ size_t memory_sizing= size * memory_class_max;
+
+ array->m_ptr= NULL;
+ array->m_full= true;
+ array->m_instr_class_waits_array= NULL;
+ array->m_instr_class_stages_array= NULL;
+ array->m_instr_class_statements_array= NULL;
+ array->m_instr_class_transactions_array= NULL;
+ array->m_instr_class_memory_array= NULL;
+
+ if (size > 0)
+ {
+ array->m_ptr=
+ PFS_MALLOC_ARRAY(& builtin_memory_user,
+ size, sizeof(PFS_user), PFS_user, MYF(MY_ZEROFILL));
+ if (array->m_ptr == NULL)
+ return 1;
+ }
+
+ if (waits_sizing > 0)
+ {
+ array->m_instr_class_waits_array=
+ PFS_MALLOC_ARRAY(& builtin_memory_user_waits,
+ waits_sizing, sizeof(PFS_single_stat), PFS_single_stat, MYF(MY_ZEROFILL));
+ if (array->m_instr_class_waits_array == NULL)
+ return 1;
+
+ for (index=0; index < waits_sizing; index++)
+ array->m_instr_class_waits_array[index].reset();
+ }
+
+ if (stages_sizing > 0)
+ {
+ array->m_instr_class_stages_array=
+ PFS_MALLOC_ARRAY(& builtin_memory_user_stages,
+ stages_sizing, sizeof(PFS_stage_stat), PFS_stage_stat, MYF(MY_ZEROFILL));
+ if (array->m_instr_class_stages_array == NULL)
+ return 1;
+
+ for (index=0; index < stages_sizing; index++)
+ array->m_instr_class_stages_array[index].reset();
+ }
+
+ if (statements_sizing > 0)
+ {
+ array->m_instr_class_statements_array=
+ PFS_MALLOC_ARRAY(& builtin_memory_user_statements,
+ statements_sizing, sizeof(PFS_statement_stat), PFS_statement_stat, MYF(MY_ZEROFILL));
+ if (array->m_instr_class_statements_array == NULL)
+ return 1;
+
+ for (index=0; index < statements_sizing; index++)
+ array->m_instr_class_statements_array[index].reset();
+ }
+
+ if (transactions_sizing > 0)
+ {
+ array->m_instr_class_transactions_array=
+ PFS_MALLOC_ARRAY(& builtin_memory_user_transactions,
+ transactions_sizing, sizeof(PFS_transaction_stat), PFS_transaction_stat, MYF(MY_ZEROFILL));
+ if (array->m_instr_class_transactions_array == NULL)
+ return 1;
+
+ for (index=0; index < transactions_sizing; index++)
+ array->m_instr_class_transactions_array[index].reset();
+ }
+
+ if (memory_sizing > 0)
+ {
+ array->m_instr_class_memory_array=
+ PFS_MALLOC_ARRAY(& builtin_memory_user_memory,
+ memory_sizing, sizeof(PFS_memory_stat), PFS_memory_stat, MYF(MY_ZEROFILL));
+ if (array->m_instr_class_memory_array == NULL)
+ return 1;
+
+ for (index=0; index < memory_sizing; index++)
+ array->m_instr_class_memory_array[index].reset();
+ }
+
+ for (index= 0; index < size; index++)
+ {
+ pfs= & array->m_ptr[index];
+
+ pfs->set_instr_class_waits_stats(
+ & array->m_instr_class_waits_array[index * wait_class_max]);
+ pfs->set_instr_class_stages_stats(
+ & array->m_instr_class_stages_array[index * stage_class_max]);
+ pfs->set_instr_class_statements_stats(
+ & array->m_instr_class_statements_array[index * statement_class_max]);
+ pfs->set_instr_class_transactions_stats(
+ & array->m_instr_class_transactions_array[index * transaction_class_max]);
+ pfs->set_instr_class_memory_stats(
+ & array->m_instr_class_memory_array[index * memory_class_max]);
+ }
+
+ array->m_full= false;
+ return 0;
+}
+
+void PFS_user_allocator::free_array(PFS_user_array *array)
+{
+ size_t size= array->m_max;
+ size_t waits_sizing= size * wait_class_max;
+ size_t stages_sizing= size * stage_class_max;
+ size_t statements_sizing= size * statement_class_max;
+ size_t transactions_sizing= size * transaction_class_max;
+ size_t memory_sizing= size * memory_class_max;
+
+ PFS_FREE_ARRAY(& builtin_memory_user,
+ size, sizeof(PFS_user), array->m_ptr);
+ array->m_ptr= NULL;
+
+ PFS_FREE_ARRAY(& builtin_memory_user_waits,
+ waits_sizing, sizeof(PFS_single_stat),
+ array->m_instr_class_waits_array);
+ array->m_instr_class_waits_array= NULL;
+
+ PFS_FREE_ARRAY(& builtin_memory_user_stages,
+ stages_sizing, sizeof(PFS_stage_stat),
+ array->m_instr_class_stages_array);
+ array->m_instr_class_stages_array= NULL;
+
+ PFS_FREE_ARRAY(& builtin_memory_user_statements,
+ statements_sizing, sizeof(PFS_statement_stat),
+ array->m_instr_class_statements_array);
+ array->m_instr_class_statements_array= NULL;
+
+ PFS_FREE_ARRAY(& builtin_memory_user_transactions,
+ transactions_sizing, sizeof(PFS_transaction_stat),
+ array->m_instr_class_transactions_array);
+ array->m_instr_class_transactions_array= NULL;
+
+ PFS_FREE_ARRAY(& builtin_memory_user_memory,
+ memory_sizing, sizeof(PFS_memory_stat),
+ array->m_instr_class_memory_array);
+ array->m_instr_class_memory_array= NULL;
+}
+
+PFS_user_allocator user_allocator;
+PFS_user_container global_user_container(& user_allocator);
+
diff --git a/storage/perfschema/pfs_buffer_container.h b/storage/perfschema/pfs_buffer_container.h
new file mode 100644
index 00000000000..911e030209a
--- /dev/null
+++ b/storage/perfschema/pfs_buffer_container.h
@@ -0,0 +1,1625 @@
+/* Copyright (c) 2014, 2016, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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 PFS_BUFFER_CONTAINER_H
+#define PFS_BUFFER_CONTAINER_H
+
+#include "my_global.h"
+#include "pfs.h" // PSI_COUNT_VOLATILITY
+#include "pfs_lock.h"
+#include "pfs_instr.h"
+#include "pfs_setup_actor.h"
+#include "pfs_setup_object.h"
+#include "pfs_program.h"
+#include "pfs_prepared_stmt.h"
+#include "pfs_builtin_memory.h"
+
+#define USE_SCALABLE
+
+class PFS_opaque_container_page;
+class PFS_opaque_container;
+
+struct PFS_builtin_memory_class;
+
+template <class T>
+class PFS_buffer_const_iterator;
+
+template <class T>
+class PFS_buffer_processor;
+
+template <class T, class U, class V>
+class PFS_buffer_iterator;
+
+template <class T, int PFS_PAGE_SIZE, int PFS_PAGE_COUNT, class U, class V>
+class PFS_buffer_scalable_iterator;
+
+template <class T>
+class PFS_buffer_default_array;
+
+template <class T>
+class PFS_buffer_default_allocator;
+
+template <class T, class U, class V>
+class PFS_buffer_container;
+
+template <class T, int PFS_PAGE_SIZE, int PFS_PAGE_COUNT, class U, class V>
+class PFS_buffer_scalable_container;
+
+template <class B, int COUNT>
+class PFS_partitioned_buffer_scalable_iterator;
+
+template <class B, int COUNT>
+class PFS_partitioned_buffer_scalable_container;
+
+
+template <class T>
+class PFS_buffer_default_array
+{
+public:
+ typedef T value_type;
+
+ value_type *allocate(pfs_dirty_state *dirty_state)
+ {
+ uint index;
+ uint monotonic;
+ uint monotonic_max;
+ value_type *pfs;
+
+ if (m_full)
+ return NULL;
+
+ monotonic= PFS_atomic::add_u32(& m_monotonic.m_u32, 1);
+ monotonic_max= monotonic + m_max;
+
+ while (monotonic < monotonic_max)
+ {
+ index= monotonic % m_max;
+ pfs= m_ptr + index;
+
+ if (pfs->m_lock.free_to_dirty(dirty_state))
+ {
+ return pfs;
+ }
+ monotonic= PFS_atomic::add_u32(& m_monotonic.m_u32, 1);
+ }
+
+ m_full= true;
+ return NULL;
+ }
+
+ void deallocate(value_type *pfs)
+ {
+ pfs->m_lock.allocated_to_free();
+ m_full= false;
+ }
+
+ T* get_first()
+ {
+ return m_ptr;
+ }
+
+ T* get_last()
+ {
+ return m_ptr + m_max;
+ }
+
+ bool m_full;
+ PFS_cacheline_uint32 m_monotonic;
+ T * m_ptr;
+ size_t m_max;
+ /** Container. */
+ PFS_opaque_container *m_container;
+};
+
+template <class T>
+class PFS_buffer_default_allocator
+{
+public:
+ typedef PFS_buffer_default_array<T> array_type;
+
+ PFS_buffer_default_allocator(PFS_builtin_memory_class *klass)
+ : m_builtin_class(klass)
+ {}
+
+ int alloc_array(array_type *array)
+ {
+ array->m_ptr= NULL;
+ array->m_full= true;
+ array->m_monotonic.m_u32= 0;
+
+ if (array->m_max > 0)
+ {
+ array->m_ptr= PFS_MALLOC_ARRAY(m_builtin_class,
+ array->m_max, sizeof(T), T, MYF(MY_ZEROFILL));
+ if (array->m_ptr == NULL)
+ return 1;
+ array->m_full= false;
+ }
+ return 0;
+ }
+
+ void free_array(array_type *array)
+ {
+ DBUG_ASSERT(array->m_max > 0);
+
+ PFS_FREE_ARRAY(m_builtin_class,
+ array->m_max, sizeof(T), array->m_ptr);
+ array->m_ptr= NULL;
+ }
+
+private:
+ PFS_builtin_memory_class *m_builtin_class;
+};
+
+template <class T,
+ class U = PFS_buffer_default_array<T>,
+ class V = PFS_buffer_default_allocator<T> >
+class PFS_buffer_container
+{
+public:
+ friend class PFS_buffer_iterator<T, U, V>;
+
+ typedef T value_type;
+ typedef U array_type;
+ typedef V allocator_type;
+ typedef PFS_buffer_const_iterator<T> const_iterator_type;
+ typedef PFS_buffer_iterator<T, U, V> iterator_type;
+ typedef PFS_buffer_processor<T> processor_type;
+ typedef void (*function_type)(value_type *);
+
+ PFS_buffer_container(allocator_type *allocator)
+ {
+ m_array.m_full= true;
+ m_array.m_ptr= NULL;
+ m_array.m_max= 0;
+ m_array.m_monotonic.m_u32= 0;
+ m_lost= 0;
+ m_max= 0;
+ m_allocator= allocator;
+ }
+
+ int init(ulong max_size)
+ {
+ if (max_size > 0)
+ {
+ m_array.m_max= max_size;
+ int rc= m_allocator->alloc_array(& m_array);
+ if (rc != 0)
+ {
+ m_allocator->free_array(& m_array);
+ return 1;
+ }
+ m_max= max_size;
+ m_array.m_full= false;
+ }
+ return 0;
+ }
+
+ void cleanup()
+ {
+ m_allocator->free_array(& m_array);
+ }
+
+ ulong get_row_count() const
+ {
+ return m_max;
+ }
+
+ ulong get_row_size() const
+ {
+ return sizeof(value_type);
+ }
+
+ ulong get_memory() const
+ {
+ return get_row_count() * get_row_size();
+ }
+
+ value_type *allocate(pfs_dirty_state *dirty_state)
+ {
+ value_type *pfs;
+
+ pfs= m_array.allocate(dirty_state, m_max);
+ if (pfs == NULL)
+ {
+ m_lost++;
+ }
+
+ return pfs;
+ }
+
+ void deallocate(value_type *pfs)
+ {
+ m_array.deallocate(pfs);
+ }
+
+ iterator_type iterate()
+ {
+ return PFS_buffer_iterator<T, U, V>(this, 0);
+ }
+
+ iterator_type iterate(uint index)
+ {
+ DBUG_ASSERT(index <= m_max);
+ return PFS_buffer_iterator<T, U, V>(this, index);
+ }
+
+ void apply(function_type fct)
+ {
+ value_type *pfs= m_array.get_first();
+ value_type *pfs_last= m_array.get_last();
+
+ while (pfs < pfs_last)
+ {
+ if (pfs->m_lock.is_populated())
+ {
+ fct(pfs);
+ }
+ pfs++;
+ }
+ }
+
+ void apply_all(function_type fct)
+ {
+ value_type *pfs= m_array.get_first();
+ value_type *pfs_last= m_array.get_last();
+
+ while (pfs < pfs_last)
+ {
+ fct(pfs);
+ pfs++;
+ }
+ }
+
+ void apply(processor_type & proc)
+ {
+ value_type *pfs= m_array.get_first();
+ value_type *pfs_last= m_array.get_last();
+
+ while (pfs < pfs_last)
+ {
+ if (pfs->m_lock.is_populated())
+ {
+ proc(pfs);
+ }
+ pfs++;
+ }
+ }
+
+ void apply_all(processor_type & proc)
+ {
+ value_type *pfs= m_array.get_first();
+ value_type *pfs_last= m_array.get_last();
+
+ while (pfs < pfs_last)
+ {
+ proc(pfs);
+ pfs++;
+ }
+ }
+
+ inline value_type* get(uint index)
+ {
+ DBUG_ASSERT(index < m_max);
+
+ value_type *pfs= m_array.m_ptr + index;
+ if (pfs->m_lock.is_populated())
+ {
+ return pfs;
+ }
+
+ return NULL;
+ }
+
+ value_type* get(uint index, bool *has_more)
+ {
+ if (index >= m_max)
+ {
+ *has_more= false;
+ return NULL;
+ }
+
+ *has_more= true;
+ return get(index);
+ }
+
+ value_type *sanitize(value_type *unsafe)
+ {
+ intptr offset;
+ value_type *pfs= m_array.get_first();
+ value_type *pfs_last= m_array.get_last();
+
+ if ((pfs <= unsafe) &&
+ (unsafe < pfs_last))
+ {
+ offset= ((intptr) unsafe - (intptr) pfs) % sizeof(value_type);
+ if (offset == 0)
+ return unsafe;
+ }
+
+ return NULL;
+ }
+
+ ulong m_lost;
+
+private:
+ value_type* scan_next(uint & index, uint * found_index)
+ {
+ DBUG_ASSERT(index <= m_max);
+
+ value_type *pfs_first= m_array.get_first();
+ value_type *pfs= pfs_first + index;
+ value_type *pfs_last= m_array.get_last();
+
+ while (pfs < pfs_last)
+ {
+ if (pfs->m_lock.is_populated())
+ {
+ uint found= pfs - pfs_first;
+ *found_index= found;
+ index= found + 1;
+ return pfs;
+ }
+ pfs++;
+ }
+
+ index= m_max;
+ return NULL;
+ }
+
+ ulong m_max;
+ array_type m_array;
+ allocator_type *m_allocator;
+};
+
+template <class T,
+ int PFS_PAGE_SIZE,
+ int PFS_PAGE_COUNT,
+ class U = PFS_buffer_default_array<T>,
+ class V = PFS_buffer_default_allocator<T> >
+class PFS_buffer_scalable_container
+{
+public:
+ friend class PFS_buffer_scalable_iterator<T, PFS_PAGE_SIZE, PFS_PAGE_COUNT, U, V>;
+
+ /**
+ Type of elements in the buffer.
+ The following attributes are required:
+ - pfs_lock m_lock
+ - PFS_opaque_container_page *m_page
+ */
+ typedef T value_type;
+ /**
+ Type of pages in the buffer.
+ The following attributes are required:
+ - PFS_opaque_container *m_container
+ */
+ typedef U array_type;
+ typedef V allocator_type;
+ /** This container type */
+ typedef PFS_buffer_scalable_container<T, PFS_PAGE_SIZE, PFS_PAGE_COUNT, U, V> container_type;
+ typedef PFS_buffer_const_iterator<T> const_iterator_type;
+ typedef PFS_buffer_scalable_iterator<T, PFS_PAGE_SIZE, PFS_PAGE_COUNT, U, V> iterator_type;
+ typedef PFS_buffer_processor<T> processor_type;
+ typedef void (*function_type)(value_type *);
+
+ static const size_t MAX_SIZE= PFS_PAGE_SIZE*PFS_PAGE_COUNT;
+
+ PFS_buffer_scalable_container(allocator_type *allocator)
+ {
+ m_allocator= allocator;
+ m_initialized= false;
+ }
+
+ int init(long max_size)
+ {
+ int i;
+
+ m_initialized= true;
+ m_full= true;
+ m_max= PFS_PAGE_COUNT * PFS_PAGE_SIZE;
+ m_max_page_count= PFS_PAGE_COUNT;
+ m_last_page_size= PFS_PAGE_SIZE;
+ m_lost= 0;
+ m_monotonic.m_u32= 0;
+ m_max_page_index.m_u32= 0;
+
+ for (i=0 ; i < PFS_PAGE_COUNT; i++)
+ {
+ m_pages[i]= NULL;
+ }
+
+ if (max_size == 0)
+ {
+ /* No allocation. */
+ m_max_page_count= 0;
+ }
+ else if (max_size > 0)
+ {
+ if (max_size % PFS_PAGE_SIZE == 0)
+ {
+ m_max_page_count= max_size / PFS_PAGE_SIZE;
+ }
+ else
+ {
+ m_max_page_count= max_size / PFS_PAGE_SIZE + 1;
+ m_last_page_size= max_size % PFS_PAGE_SIZE;
+ }
+ /* Bounded allocation. */
+ m_full= false;
+
+ if (m_max_page_count > PFS_PAGE_COUNT)
+ {
+ m_max_page_count= PFS_PAGE_COUNT;
+ m_last_page_size= PFS_PAGE_SIZE;
+ }
+ }
+ else
+ {
+ /* max_size = -1 means unbounded allocation */
+ m_full= false;
+ }
+
+ DBUG_ASSERT(m_max_page_count <= PFS_PAGE_COUNT);
+ DBUG_ASSERT(0 < m_last_page_size);
+ DBUG_ASSERT(m_last_page_size <= PFS_PAGE_SIZE);
+
+ pthread_mutex_init(& m_critical_section, NULL);
+ return 0;
+ }
+
+ void cleanup()
+ {
+ int i;
+ array_type *page;
+
+ if (! m_initialized)
+ return;
+
+ pthread_mutex_lock(& m_critical_section);
+
+ for (i=0 ; i < PFS_PAGE_COUNT; i++)
+ {
+ page= m_pages[i];
+ if (page != NULL)
+ {
+ m_allocator->free_array(page);
+ delete page;
+ m_pages[i]= NULL;
+ }
+ }
+ pthread_mutex_unlock(& m_critical_section);
+
+ pthread_mutex_destroy(& m_critical_section);
+
+ m_initialized= false;
+ }
+
+ ulong get_row_count()
+ {
+ ulong page_count= PFS_atomic::load_u32(& m_max_page_index.m_u32);
+
+ return page_count * PFS_PAGE_SIZE;
+ }
+
+ ulong get_row_size() const
+ {
+ return sizeof(value_type);
+ }
+
+ ulong get_memory()
+ {
+ return get_row_count() * get_row_size();
+ }
+
+ value_type *allocate(pfs_dirty_state *dirty_state)
+ {
+ if (m_full)
+ {
+ m_lost++;
+ return NULL;
+ }
+
+ uint index;
+ uint monotonic;
+ uint monotonic_max;
+ uint current_page_count;
+ value_type *pfs;
+ array_type *array;
+
+ void *addr;
+ void * volatile * typed_addr;
+ void *ptr;
+
+ /*
+ 1: Try to find an available record within the existing pages
+ */
+ current_page_count= PFS_atomic::load_u32(& m_max_page_index.m_u32);
+
+ if (current_page_count != 0)
+ {
+ monotonic= PFS_atomic::load_u32(& m_monotonic.m_u32);
+ monotonic_max= monotonic + current_page_count;
+
+ while (monotonic < monotonic_max)
+ {
+ /*
+ Scan in the [0 .. current_page_count - 1] range,
+ in parallel with m_monotonic (see below)
+ */
+ index= monotonic % current_page_count;
+
+ /* Atomic Load, array= m_pages[index] */
+ addr= & m_pages[index];
+ typed_addr= static_cast<void * volatile *>(addr);
+ ptr= my_atomic_loadptr(typed_addr);
+ array= static_cast<array_type *>(ptr);
+
+ if (array != NULL)
+ {
+ pfs= array->allocate(dirty_state);
+ if (pfs != NULL)
+ {
+ /* Keep a pointer to the parent page, for deallocate(). */
+ pfs->m_page= reinterpret_cast<PFS_opaque_container_page *> (array);
+ return pfs;
+ }
+ }
+
+ /*
+ Parallel scans collaborate to increase
+ the common monotonic scan counter.
+
+ Note that when all the existing page are full,
+ one thread will eventually add a new page,
+ and cause m_max_page_index to increase,
+ which fools all the modulo logic for scans already in progress,
+ because the monotonic counter is not folded to the same place
+ (sometime modulo N, sometime modulo N+1).
+
+ This is actually ok: since all the pages are full anyway,
+ there is nothing to miss, so better increase the monotonic
+ counter faster and then move on to the detection of new pages,
+ in part 2: below.
+ */
+ monotonic= PFS_atomic::add_u32(& m_monotonic.m_u32, 1);
+ };
+ }
+
+ /*
+ 2: Try to add a new page, beyond the m_max_page_index limit
+ */
+ while (current_page_count < m_max_page_count)
+ {
+ /* Peek for pages added by collaborating threads */
+
+ /* (2-a) Atomic Load, array= m_pages[current_page_count] */
+ addr= & m_pages[current_page_count];
+ typed_addr= static_cast<void * volatile *>(addr);
+ ptr= my_atomic_loadptr(typed_addr);
+ array= static_cast<array_type *>(ptr);
+
+ if (array == NULL)
+ {
+ // ==================================================================
+ // BEGIN CRITICAL SECTION -- buffer expand
+ // ==================================================================
+
+ /*
+ On a fresh started server, buffers are typically empty.
+ When a sudden load spike is seen by the server,
+ multiple threads may want to expand the buffer at the same time.
+
+ Using a compare and swap to allow multiple pages to be added,
+ possibly freeing duplicate pages on collisions,
+ does not work well because the amount of code involved
+ when creating a new page can be significant (PFS_thread),
+ causing MANY collisions between (2-b) and (2-d).
+
+ A huge number of collisions (which can happen when thousands
+ of new connections hits the server after a restart)
+ leads to a huge memory consumption, and to OOM.
+
+ To mitigate this, we use here a mutex,
+ to enforce that only ONE page is added at a time,
+ so that scaling the buffer happens in a predictable
+ and controlled manner.
+ */
+ pthread_mutex_lock(& m_critical_section);
+
+ /*
+ Peek again for pages added by collaborating threads,
+ this time as the only thread allowed to expand the buffer
+ */
+
+ /* (2-b) Atomic Load, array= m_pages[current_page_count] */
+
+ ptr= my_atomic_loadptr(typed_addr);
+ array= static_cast<array_type *>(ptr);
+
+ if (array == NULL)
+ {
+ /* (2-c) Found no page, allocate a new one */
+ array= new array_type();
+ builtin_memory_scalable_buffer.count_alloc(sizeof (array_type));
+
+ array->m_max= get_page_logical_size(current_page_count);
+ int rc= m_allocator->alloc_array(array);
+ if (rc != 0)
+ {
+ m_allocator->free_array(array);
+ delete array;
+ builtin_memory_scalable_buffer.count_free(sizeof (array_type));
+ m_lost++;
+ pthread_mutex_unlock(& m_critical_section);
+ return NULL;
+ }
+
+ /* Keep a pointer to this container, for static_deallocate(). */
+ array->m_container= reinterpret_cast<PFS_opaque_container *> (this);
+
+ /* (2-d) Atomic STORE, m_pages[current_page_count] = array */
+ ptr= array;
+ my_atomic_storeptr(typed_addr, ptr);
+
+ /* Advertise the new page */
+ PFS_atomic::add_u32(& m_max_page_index.m_u32, 1);
+ }
+
+ pthread_mutex_unlock(& m_critical_section);
+
+ // ==================================================================
+ // END CRITICAL SECTION -- buffer expand
+ // ==================================================================
+ }
+
+ DBUG_ASSERT(array != NULL);
+ pfs= array->allocate(dirty_state);
+ if (pfs != NULL)
+ {
+ /* Keep a pointer to the parent page, for deallocate(). */
+ pfs->m_page= reinterpret_cast<PFS_opaque_container_page *> (array);
+ return pfs;
+ }
+
+ current_page_count++;
+ }
+
+ m_lost++;
+ m_full= true;
+ return NULL;
+ }
+
+ void deallocate(value_type *safe_pfs)
+ {
+ /* Find the containing page */
+ PFS_opaque_container_page *opaque_page= safe_pfs->m_page;
+ array_type *page= reinterpret_cast<array_type *> (opaque_page);
+
+ /* Mark the object free */
+ safe_pfs->m_lock.allocated_to_free();
+
+ /* Flag the containing page as not full. */
+ page->m_full= false;
+
+ /* Flag the overall container as not full. */
+ m_full= false;
+ }
+
+ static void static_deallocate(value_type *safe_pfs)
+ {
+ /* Find the containing page */
+ PFS_opaque_container_page *opaque_page= safe_pfs->m_page;
+ array_type *page= reinterpret_cast<array_type *> (opaque_page);
+
+ /* Mark the object free */
+ safe_pfs->m_lock.allocated_to_free();
+
+ /* Flag the containing page as not full. */
+ page->m_full= false;
+
+ /* Find the containing buffer */
+ PFS_opaque_container *opaque_container= page->m_container;
+ PFS_buffer_scalable_container *container;
+ container= reinterpret_cast<container_type *> (opaque_container);
+
+ /* Flag the overall container as not full. */
+ container->m_full= false;
+ }
+
+ iterator_type iterate()
+ {
+ return PFS_buffer_scalable_iterator<T, PFS_PAGE_SIZE, PFS_PAGE_COUNT, U, V>(this, 0);
+ }
+
+ iterator_type iterate(uint index)
+ {
+ DBUG_ASSERT(index <= m_max);
+ return PFS_buffer_scalable_iterator<T, PFS_PAGE_SIZE, PFS_PAGE_COUNT, U, V>(this, index);
+ }
+
+ void apply(function_type fct)
+ {
+ uint i;
+ array_type *page;
+ value_type *pfs;
+ value_type *pfs_last;
+
+ for (i=0 ; i < PFS_PAGE_COUNT; i++)
+ {
+ page= m_pages[i];
+ if (page != NULL)
+ {
+ pfs= page->get_first();
+ pfs_last= page->get_last();
+
+ while (pfs < pfs_last)
+ {
+ if (pfs->m_lock.is_populated())
+ {
+ fct(pfs);
+ }
+ pfs++;
+ }
+ }
+ }
+ }
+
+ void apply_all(function_type fct)
+ {
+ uint i;
+ array_type *page;
+ value_type *pfs;
+ value_type *pfs_last;
+
+ for (i=0 ; i < PFS_PAGE_COUNT; i++)
+ {
+ page= m_pages[i];
+ if (page != NULL)
+ {
+ pfs= page->get_first();
+ pfs_last= page->get_last();
+
+ while (pfs < pfs_last)
+ {
+ fct(pfs);
+ pfs++;
+ }
+ }
+ }
+ }
+
+ void apply(processor_type & proc)
+ {
+ uint i;
+ array_type *page;
+ value_type *pfs;
+ value_type *pfs_last;
+
+ for (i=0 ; i < PFS_PAGE_COUNT; i++)
+ {
+ page= m_pages[i];
+ if (page != NULL)
+ {
+ pfs= page->get_first();
+ pfs_last= page->get_last();
+
+ while (pfs < pfs_last)
+ {
+ if (pfs->m_lock.is_populated())
+ {
+ proc(pfs);
+ }
+ pfs++;
+ }
+ }
+ }
+ }
+
+ void apply_all(processor_type & proc)
+ {
+ uint i;
+ array_type *page;
+ value_type *pfs;
+ value_type *pfs_last;
+
+ for (i=0 ; i < PFS_PAGE_COUNT; i++)
+ {
+ page= m_pages[i];
+ if (page != NULL)
+ {
+ pfs= page->get_first();
+ pfs_last= page->get_last();
+
+ while (pfs < pfs_last)
+ {
+ proc(pfs);
+ pfs++;
+ }
+ }
+ }
+ }
+
+ value_type* get(uint index)
+ {
+ DBUG_ASSERT(index < m_max);
+
+ uint index_1= index / PFS_PAGE_SIZE;
+ array_type *page= m_pages[index_1];
+ if (page != NULL)
+ {
+ uint index_2= index % PFS_PAGE_SIZE;
+
+ if (index_2 >= page->m_max)
+ {
+ return NULL;
+ }
+
+ value_type *pfs= page->m_ptr + index_2;
+
+ if (pfs->m_lock.is_populated())
+ {
+ return pfs;
+ }
+ }
+
+ return NULL;
+ }
+
+ value_type* get(uint index, bool *has_more)
+ {
+ if (index >= m_max)
+ {
+ *has_more= false;
+ return NULL;
+ }
+
+ uint index_1= index / PFS_PAGE_SIZE;
+ array_type *page= m_pages[index_1];
+
+ if (page == NULL)
+ {
+ *has_more= false;
+ return NULL;
+ }
+
+ uint index_2= index % PFS_PAGE_SIZE;
+
+ if (index_2 >= page->m_max)
+ {
+ *has_more= false;
+ return NULL;
+ }
+
+ *has_more= true;
+ value_type *pfs= page->m_ptr + index_2;
+
+ if (pfs->m_lock.is_populated())
+ {
+ return pfs;
+ }
+
+ return NULL;
+ }
+
+ value_type *sanitize(value_type *unsafe)
+ {
+ intptr offset;
+ uint i;
+ array_type *page;
+ value_type *pfs;
+ value_type *pfs_last;
+
+ for (i=0 ; i < PFS_PAGE_COUNT; i++)
+ {
+ page= m_pages[i];
+ if (page != NULL)
+ {
+ pfs= page->get_first();
+ pfs_last= page->get_last();
+
+ if ((pfs <= unsafe) &&
+ (unsafe < pfs_last))
+ {
+ offset= ((intptr) unsafe - (intptr) pfs) % sizeof(value_type);
+ if (offset == 0)
+ return unsafe;
+ }
+ }
+ }
+
+ return NULL;
+ }
+
+ ulong m_lost;
+
+private:
+
+ uint get_page_logical_size(uint page_index)
+ {
+ if (page_index + 1 < m_max_page_count)
+ return PFS_PAGE_SIZE;
+ DBUG_ASSERT(page_index + 1 == m_max_page_count);
+ return m_last_page_size;
+ }
+
+ value_type* scan_next(uint & index, uint * found_index)
+ {
+ DBUG_ASSERT(index <= m_max);
+
+ uint index_1= index / PFS_PAGE_SIZE;
+ uint index_2= index % PFS_PAGE_SIZE;
+ array_type *page;
+ value_type *pfs_first;
+ value_type *pfs;
+ value_type *pfs_last;
+
+ while (index_1 < PFS_PAGE_COUNT)
+ {
+ page= m_pages[index_1];
+
+ if (page == NULL)
+ {
+ index= m_max;
+ return NULL;
+ }
+
+ pfs_first= page->get_first();
+ pfs= pfs_first + index_2;
+ pfs_last= page->get_last();
+
+ while (pfs < pfs_last)
+ {
+ if (pfs->m_lock.is_populated())
+ {
+ uint found= index_1 * PFS_PAGE_SIZE + (pfs - pfs_first);
+ *found_index= found;
+ index= found + 1;
+ return pfs;
+ }
+ pfs++;
+ }
+
+ index_1++;
+ index_2= 0;
+ }
+
+ index= m_max;
+ return NULL;
+ }
+
+ bool m_initialized;
+ bool m_full;
+ size_t m_max;
+ PFS_cacheline_uint32 m_monotonic;
+ PFS_cacheline_uint32 m_max_page_index;
+ ulong m_max_page_count;
+ ulong m_last_page_size;
+ array_type * m_pages[PFS_PAGE_COUNT];
+ allocator_type *m_allocator;
+ pthread_mutex_t m_critical_section;
+};
+
+template <class T, class U, class V>
+class PFS_buffer_iterator
+{
+ friend class PFS_buffer_container<T, U, V>;
+
+ typedef T value_type;
+ typedef PFS_buffer_container<T, U, V> container_type;
+
+public:
+ value_type* scan_next()
+ {
+ uint unused;
+ return m_container->scan_next(m_index, & unused);
+ }
+
+ value_type* scan_next(uint * found_index)
+ {
+ return m_container->scan_next(m_index, found_index);
+ }
+
+private:
+ PFS_buffer_iterator(container_type *container, uint index)
+ : m_container(container),
+ m_index(index)
+ {}
+
+ container_type *m_container;
+ uint m_index;
+};
+
+template <class T, int page_size, int page_count, class U, class V>
+class PFS_buffer_scalable_iterator
+{
+ friend class PFS_buffer_scalable_container<T, page_size, page_count, U, V>;
+
+ typedef T value_type;
+ typedef PFS_buffer_scalable_container<T, page_size, page_count, U, V> container_type;
+
+public:
+ value_type* scan_next()
+ {
+ uint unused;
+ return m_container->scan_next(m_index, & unused);
+ }
+
+ value_type* scan_next(uint * found_index)
+ {
+ return m_container->scan_next(m_index, found_index);
+ }
+
+private:
+ PFS_buffer_scalable_iterator(container_type *container, uint index)
+ : m_container(container),
+ m_index(index)
+ {}
+
+ container_type *m_container;
+ uint m_index;
+};
+
+template <class T>
+class PFS_buffer_processor
+{
+public:
+ virtual ~PFS_buffer_processor<T> ()
+ {}
+ virtual void operator()(T *element) = 0;
+};
+
+template <class B, int PFS_PARTITION_COUNT>
+class PFS_partitioned_buffer_scalable_container
+{
+public:
+ friend class PFS_partitioned_buffer_scalable_iterator<B, PFS_PARTITION_COUNT>;
+
+ typedef typename B::value_type value_type;
+ typedef typename B::allocator_type allocator_type;
+ typedef PFS_partitioned_buffer_scalable_iterator<B, PFS_PARTITION_COUNT> iterator_type;
+ typedef typename B::iterator_type sub_iterator_type;
+ typedef typename B::processor_type processor_type;
+ typedef typename B::function_type function_type;
+
+ PFS_partitioned_buffer_scalable_container(allocator_type *allocator)
+ {
+ for (int i=0 ; i < PFS_PARTITION_COUNT; i++)
+ {
+ m_partitions[i]= new B(allocator);
+ }
+ }
+
+ ~PFS_partitioned_buffer_scalable_container()
+ {
+ for (int i=0 ; i < PFS_PARTITION_COUNT; i++)
+ {
+ delete m_partitions[i];
+ }
+ }
+
+ int init(long max_size)
+ {
+ int rc= 0;
+ // FIXME: we have max_size * PFS_PARTITION_COUNT here
+ for (int i=0 ; i < PFS_PARTITION_COUNT; i++)
+ {
+ rc|= m_partitions[i]->init(max_size);
+ }
+ return rc;
+ }
+
+ void cleanup()
+ {
+ for (int i=0 ; i < PFS_PARTITION_COUNT; i++)
+ {
+ m_partitions[i]->cleanup();
+ }
+ }
+
+ ulong get_row_count() const
+ {
+ ulong sum= 0;
+
+ for (int i=0; i < PFS_PARTITION_COUNT; i++)
+ {
+ sum += m_partitions[i]->get_row_count();
+ }
+
+ return sum;
+ }
+
+ ulong get_row_size() const
+ {
+ return sizeof(value_type);
+ }
+
+ ulong get_memory() const
+ {
+ ulong sum= 0;
+
+ for (int i=0; i < PFS_PARTITION_COUNT; i++)
+ {
+ sum += m_partitions[i]->get_memory();
+ }
+
+ return sum;
+ }
+
+ long get_lost_counter()
+ {
+ long sum= 0;
+
+ for (int i=0; i < PFS_PARTITION_COUNT; i++)
+ {
+ sum += m_partitions[i]->m_lost;
+ }
+
+ return sum;
+ }
+
+ value_type *allocate(pfs_dirty_state *dirty_state, uint partition)
+ {
+ DBUG_ASSERT(partition < PFS_PARTITION_COUNT);
+
+ return m_partitions[partition]->allocate(dirty_state);
+ }
+
+ void deallocate(value_type *safe_pfs)
+ {
+ /*
+ One issue here is that we do not know which partition
+ the record belongs to.
+ Each record points to the parent page,
+ and each page points to the parent buffer,
+ so using static_deallocate here,
+ which will find the correct partition by itself.
+ */
+ B::static_deallocate(safe_pfs);
+ }
+
+ iterator_type iterate()
+ {
+ return iterator_type(this, 0, 0);
+ }
+
+ iterator_type iterate(uint user_index)
+ {
+ uint partition_index;
+ uint sub_index;
+ unpack_index(user_index, &partition_index, &sub_index);
+ return iterator_type(this, partition_index, sub_index);
+ }
+
+ void apply(function_type fct)
+ {
+ for (int i=0; i < PFS_PARTITION_COUNT; i++)
+ {
+ m_partitions[i]->apply(fct);
+ }
+ }
+
+ void apply_all(function_type fct)
+ {
+ for (int i=0; i < PFS_PARTITION_COUNT; i++)
+ {
+ m_partitions[i]->apply_all(fct);
+ }
+ }
+
+ void apply(processor_type & proc)
+ {
+ for (int i=0; i < PFS_PARTITION_COUNT; i++)
+ {
+ m_partitions[i]->apply(proc);
+ }
+ }
+
+ void apply_all(processor_type & proc)
+ {
+ for (int i=0; i < PFS_PARTITION_COUNT; i++)
+ {
+ m_partitions[i]->apply_all(proc);
+ }
+ }
+
+ value_type* get(uint user_index)
+ {
+ uint partition_index;
+ uint sub_index;
+ unpack_index(user_index, &partition_index, &sub_index);
+
+ if (partition_index >= PFS_PARTITION_COUNT)
+ {
+ return NULL;
+ }
+
+ return m_partitions[partition_index]->get(sub_index);
+ }
+
+ value_type* get(uint user_index, bool *has_more)
+ {
+ uint partition_index;
+ uint sub_index;
+ unpack_index(user_index, &partition_index, &sub_index);
+
+ if (partition_index >= PFS_PARTITION_COUNT)
+ {
+ *has_more= false;
+ return NULL;
+ }
+
+ *has_more= true;
+ return m_partitions[partition_index]->get(sub_index);
+ }
+
+ value_type *sanitize(value_type *unsafe)
+ {
+ value_type *safe= NULL;
+
+ for (int i=0; i < PFS_PARTITION_COUNT; i++)
+ {
+ safe= m_partitions[i]->sanitize(unsafe);
+ if (safe != NULL)
+ {
+ return safe;
+ }
+ }
+
+ return safe;
+ }
+
+private:
+ static void pack_index(uint partition_index, uint sub_index, uint *user_index)
+ {
+ /* 2^8 = 256 partitions max */
+ compile_time_assert(PFS_PARTITION_COUNT <= (1 << 8));
+ /* 2^24 = 16777216 max per partitioned buffer. */
+ compile_time_assert((B::MAX_SIZE) <= (1 << 24));
+
+ *user_index= (partition_index << 24) + sub_index;
+ }
+
+ static void unpack_index(uint user_index, uint *partition_index, uint *sub_index)
+ {
+ *partition_index= user_index >> 24;
+ *sub_index= user_index & 0x00FFFFFF;
+ }
+
+ value_type* scan_next(uint & partition_index, uint & sub_index, uint * found_partition, uint * found_sub_index)
+ {
+ value_type *record= NULL;
+ DBUG_ASSERT(partition_index < PFS_PARTITION_COUNT);
+
+ while (partition_index < PFS_PARTITION_COUNT)
+ {
+ sub_iterator_type sub_iterator= m_partitions[partition_index]->iterate(sub_index);
+ record= sub_iterator.scan_next(found_sub_index);
+ if (record != NULL)
+ {
+ *found_partition= partition_index;
+ sub_index= *found_sub_index + 1;
+ return record;
+ }
+
+ partition_index++;
+ sub_index= 0;
+ }
+
+ *found_partition= PFS_PARTITION_COUNT;
+ *found_sub_index= 0;
+ sub_index= 0;
+ return NULL;
+ }
+
+ B *m_partitions[PFS_PARTITION_COUNT];
+};
+
+template <class B, int PFS_PARTITION_COUNT>
+class PFS_partitioned_buffer_scalable_iterator
+{
+public:
+ friend class PFS_partitioned_buffer_scalable_container<B, PFS_PARTITION_COUNT>;
+
+ typedef typename B::value_type value_type;
+ typedef PFS_partitioned_buffer_scalable_container<B, PFS_PARTITION_COUNT> container_type;
+
+ value_type* scan_next()
+ {
+ uint unused_partition;
+ uint unused_sub_index;
+ return m_container->scan_next(m_partition, m_sub_index, & unused_partition, & unused_sub_index);
+ }
+
+ value_type* scan_next(uint *found_user_index)
+ {
+ uint found_partition;
+ uint found_sub_index;
+ value_type *record;
+ record= m_container->scan_next(m_partition, m_sub_index, &found_partition, &found_sub_index);
+ container_type::pack_index(found_partition, found_sub_index, found_user_index);
+ return record;
+ }
+
+private:
+ PFS_partitioned_buffer_scalable_iterator(container_type *container, uint partition, uint sub_index)
+ : m_container(container),
+ m_partition(partition),
+ m_sub_index(sub_index)
+ {}
+
+ container_type *m_container;
+ uint m_partition;
+ uint m_sub_index;
+};
+
+#ifdef USE_SCALABLE
+typedef PFS_buffer_scalable_container<PFS_mutex, 1024, 1024> PFS_mutex_basic_container;
+typedef PFS_partitioned_buffer_scalable_container<PFS_mutex_basic_container, PSI_COUNT_VOLATILITY> PFS_mutex_container;
+#else
+typedef PFS_buffer_container<PFS_mutex> PFS_mutex_container;
+#endif
+typedef PFS_mutex_container::iterator_type PFS_mutex_iterator;
+extern PFS_mutex_container global_mutex_container;
+
+#ifdef USE_SCALABLE
+typedef PFS_buffer_scalable_container<PFS_rwlock, 1024, 1024> PFS_rwlock_container;
+#else
+typedef PFS_buffer_container<PFS_rwlock> PFS_rwlock_container;
+#endif
+typedef PFS_rwlock_container::iterator_type PFS_rwlock_iterator;
+extern PFS_rwlock_container global_rwlock_container;
+
+#ifdef USE_SCALABLE
+typedef PFS_buffer_scalable_container<PFS_cond, 256, 256> PFS_cond_container;
+#else
+typedef PFS_buffer_container<PFS_cond> PFS_cond_container;
+#endif
+typedef PFS_cond_container::iterator_type PFS_cond_iterator;
+extern PFS_cond_container global_cond_container;
+
+#ifdef USE_SCALABLE
+typedef PFS_buffer_scalable_container<PFS_file, 4 * 1024, 4 * 1024> PFS_file_container;
+#else
+typedef PFS_buffer_container<PFS_file> PFS_file_container;
+#endif
+typedef PFS_file_container::iterator_type PFS_file_iterator;
+extern PFS_file_container global_file_container;
+
+#ifdef USE_SCALABLE
+typedef PFS_buffer_scalable_container<PFS_socket, 256, 256> PFS_socket_container;
+#else
+typedef PFS_buffer_container<PFS_socket> PFS_socket_container;
+#endif
+typedef PFS_socket_container::iterator_type PFS_socket_iterator;
+extern PFS_socket_container global_socket_container;
+
+#ifdef USE_SCALABLE
+typedef PFS_buffer_scalable_container<PFS_metadata_lock, 1024, 1024> PFS_mdl_container;
+#else
+typedef PFS_buffer_container<PFS_metadata_lock> PFS_mdl_container;
+#endif
+typedef PFS_mdl_container::iterator_type PFS_mdl_iterator;
+extern PFS_mdl_container global_mdl_container;
+
+#ifdef USE_SCALABLE
+typedef PFS_buffer_scalable_container<PFS_setup_actor, 128, 1024> PFS_setup_actor_container;
+#else
+typedef PFS_buffer_container<PFS_setup_actor> PFS_setup_actor_container;
+#endif
+typedef PFS_setup_actor_container::iterator_type PFS_setup_actor_iterator;
+extern PFS_setup_actor_container global_setup_actor_container;
+
+#ifdef USE_SCALABLE
+typedef PFS_buffer_scalable_container<PFS_setup_object, 128, 1024> PFS_setup_object_container;
+#else
+typedef PFS_buffer_container<PFS_setup_object> PFS_setup_object_container;
+#endif
+typedef PFS_setup_object_container::iterator_type PFS_setup_object_iterator;
+extern PFS_setup_object_container global_setup_object_container;
+
+#ifdef USE_SCALABLE
+typedef PFS_buffer_scalable_container<PFS_table, 1024, 1024> PFS_table_container;
+#else
+typedef PFS_buffer_container<PFS_table> PFS_table_container;
+#endif
+typedef PFS_table_container::iterator_type PFS_table_iterator;
+extern PFS_table_container global_table_container;
+
+#ifdef USE_SCALABLE
+typedef PFS_buffer_scalable_container<PFS_table_share, 4 * 1024, 4 * 1024> PFS_table_share_container;
+#else
+typedef PFS_buffer_container<PFS_table_share> PFS_table_share_container;
+#endif
+typedef PFS_table_share_container::iterator_type PFS_table_share_iterator;
+extern PFS_table_share_container global_table_share_container;
+
+#ifdef USE_SCALABLE
+typedef PFS_buffer_scalable_container<PFS_table_share_index, 8 * 1024, 8 * 1024> PFS_table_share_index_container;
+#else
+typedef PFS_buffer_container<PFS_table_share_index> PFS_table_share_index_container;
+#endif
+typedef PFS_table_share_index_container::iterator_type PFS_table_share_index_iterator;
+extern PFS_table_share_index_container global_table_share_index_container;
+
+#ifdef USE_SCALABLE
+typedef PFS_buffer_scalable_container<PFS_table_share_lock, 4 * 1024, 4 * 1024> PFS_table_share_lock_container;
+#else
+typedef PFS_buffer_container<PFS_table_share_lock> PFS_table_share_lock_container;
+#endif
+typedef PFS_table_share_lock_container::iterator_type PFS_table_share_lock_iterator;
+extern PFS_table_share_lock_container global_table_share_lock_container;
+
+#ifdef USE_SCALABLE
+typedef PFS_buffer_scalable_container<PFS_program, 1024, 1024> PFS_program_container;
+#else
+typedef PFS_buffer_container<PFS_program> PFS_program_container;
+#endif
+typedef PFS_program_container::iterator_type PFS_program_iterator;
+extern PFS_program_container global_program_container;
+
+#ifdef USE_SCALABLE
+typedef PFS_buffer_scalable_container<PFS_prepared_stmt, 1024, 1024> PFS_prepared_stmt_container;
+#else
+typedef PFS_buffer_container<PFS_prepared_stmt> PFS_prepared_stmt_container;
+#endif
+typedef PFS_prepared_stmt_container::iterator_type PFS_prepared_stmt_iterator;
+extern PFS_prepared_stmt_container global_prepared_stmt_container;
+
+class PFS_account_array : public PFS_buffer_default_array<PFS_account>
+{
+public:
+ PFS_single_stat *m_instr_class_waits_array;
+ PFS_stage_stat *m_instr_class_stages_array;
+ PFS_statement_stat *m_instr_class_statements_array;
+ PFS_transaction_stat *m_instr_class_transactions_array;
+ PFS_memory_stat *m_instr_class_memory_array;
+};
+
+class PFS_account_allocator
+{
+public:
+ int alloc_array(PFS_account_array *array);
+ void free_array(PFS_account_array *array);
+};
+
+#ifdef USE_SCALABLE
+typedef PFS_buffer_scalable_container<PFS_account,
+ 128,
+ 128,
+ PFS_account_array,
+ PFS_account_allocator> PFS_account_container;
+#else
+typedef PFS_buffer_container<PFS_account,
+ PFS_account_array,
+ PFS_account_allocator> PFS_account_container;
+#endif
+typedef PFS_account_container::iterator_type PFS_account_iterator;
+extern PFS_account_container global_account_container;
+
+class PFS_host_array : public PFS_buffer_default_array<PFS_host>
+{
+public:
+ PFS_single_stat *m_instr_class_waits_array;
+ PFS_stage_stat *m_instr_class_stages_array;
+ PFS_statement_stat *m_instr_class_statements_array;
+ PFS_transaction_stat *m_instr_class_transactions_array;
+ PFS_memory_stat *m_instr_class_memory_array;
+};
+
+class PFS_host_allocator
+{
+public:
+ int alloc_array(PFS_host_array *array);
+ void free_array(PFS_host_array *array);
+};
+
+#ifdef USE_SCALABLE
+typedef PFS_buffer_scalable_container<PFS_host,
+ 128,
+ 128,
+ PFS_host_array,
+ PFS_host_allocator> PFS_host_container;
+#else
+typedef PFS_buffer_container<PFS_host,
+ PFS_host_array,
+ PFS_host_allocator> PFS_host_container;
+#endif
+typedef PFS_host_container::iterator_type PFS_host_iterator;
+extern PFS_host_container global_host_container;
+
+class PFS_thread_array : public PFS_buffer_default_array<PFS_thread>
+{
+public:
+ PFS_single_stat *m_instr_class_waits_array;
+ PFS_stage_stat *m_instr_class_stages_array;
+ PFS_statement_stat *m_instr_class_statements_array;
+ PFS_transaction_stat *m_instr_class_transactions_array;
+ PFS_memory_stat *m_instr_class_memory_array;
+
+ PFS_events_waits *m_waits_history_array;
+ PFS_events_stages *m_stages_history_array;
+ PFS_events_statements *m_statements_history_array;
+ PFS_events_statements *m_statements_stack_array;
+ PFS_events_transactions *m_transactions_history_array;
+ char *m_session_connect_attrs_array;
+
+ char *m_current_stmts_text_array;
+ char *m_history_stmts_text_array;
+ unsigned char *m_current_stmts_digest_token_array;
+ unsigned char *m_history_stmts_digest_token_array;
+};
+
+class PFS_thread_allocator
+{
+public:
+ int alloc_array(PFS_thread_array *array);
+ void free_array(PFS_thread_array *array);
+};
+
+#ifdef USE_SCALABLE
+typedef PFS_buffer_scalable_container<PFS_thread,
+ 256,
+ 256,
+ PFS_thread_array,
+ PFS_thread_allocator> PFS_thread_container;
+#else
+typedef PFS_buffer_container<PFS_thread,
+ PFS_thread_array,
+ PFS_thread_allocator> PFS_thread_container;
+#endif
+typedef PFS_thread_container::iterator_type PFS_thread_iterator;
+extern PFS_thread_container global_thread_container;
+
+class PFS_user_array : public PFS_buffer_default_array<PFS_user>
+{
+public:
+ PFS_single_stat *m_instr_class_waits_array;
+ PFS_stage_stat *m_instr_class_stages_array;
+ PFS_statement_stat *m_instr_class_statements_array;
+ PFS_transaction_stat *m_instr_class_transactions_array;
+ PFS_memory_stat *m_instr_class_memory_array;
+};
+
+class PFS_user_allocator
+{
+public:
+ int alloc_array(PFS_user_array *array);
+ void free_array(PFS_user_array *array);
+};
+
+#ifdef USE_SCALABLE
+typedef PFS_buffer_scalable_container<PFS_user,
+ 128,
+ 128,
+ PFS_user_array,
+ PFS_user_allocator> PFS_user_container;
+#else
+typedef PFS_buffer_container<PFS_user,
+ PFS_user_array,
+ PFS_user_allocator> PFS_user_container;
+#endif
+typedef PFS_user_container::iterator_type PFS_user_iterator;
+extern PFS_user_container global_user_container;
+
+#endif
+
diff --git a/storage/perfschema/pfs_builtin_memory.cc b/storage/perfschema/pfs_builtin_memory.cc
new file mode 100644
index 00000000000..6955f1a8ec3
--- /dev/null
+++ b/storage/perfschema/pfs_builtin_memory.cc
@@ -0,0 +1,382 @@
+/* Copyright (c) 2014, 2019, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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 "m_string.h"
+#include "pfs_global.h"
+#include "pfs_builtin_memory.h"
+
+PFS_builtin_memory_class builtin_memory_mutex;
+PFS_builtin_memory_class builtin_memory_rwlock;
+PFS_builtin_memory_class builtin_memory_cond;
+PFS_builtin_memory_class builtin_memory_file;
+PFS_builtin_memory_class builtin_memory_socket;
+PFS_builtin_memory_class builtin_memory_mdl;
+PFS_builtin_memory_class builtin_memory_file_handle;
+
+PFS_builtin_memory_class builtin_memory_account;
+PFS_builtin_memory_class builtin_memory_account_waits;
+PFS_builtin_memory_class builtin_memory_account_stages;
+PFS_builtin_memory_class builtin_memory_account_statements;
+PFS_builtin_memory_class builtin_memory_account_transactions;
+PFS_builtin_memory_class builtin_memory_account_memory;
+
+PFS_builtin_memory_class builtin_memory_global_stages;
+PFS_builtin_memory_class builtin_memory_global_statements;
+PFS_builtin_memory_class builtin_memory_global_memory;
+
+PFS_builtin_memory_class builtin_memory_host;
+PFS_builtin_memory_class builtin_memory_host_waits;
+PFS_builtin_memory_class builtin_memory_host_stages;
+PFS_builtin_memory_class builtin_memory_host_statements;
+PFS_builtin_memory_class builtin_memory_host_transactions;
+PFS_builtin_memory_class builtin_memory_host_memory;
+
+PFS_builtin_memory_class builtin_memory_thread;
+PFS_builtin_memory_class builtin_memory_thread_waits;
+PFS_builtin_memory_class builtin_memory_thread_stages;
+PFS_builtin_memory_class builtin_memory_thread_statements;
+PFS_builtin_memory_class builtin_memory_thread_transactions;
+PFS_builtin_memory_class builtin_memory_thread_memory;
+
+PFS_builtin_memory_class builtin_memory_thread_waits_history;
+PFS_builtin_memory_class builtin_memory_thread_stages_history;
+PFS_builtin_memory_class builtin_memory_thread_statements_history;
+PFS_builtin_memory_class builtin_memory_thread_statements_history_tokens;
+PFS_builtin_memory_class builtin_memory_thread_statements_history_sqltext;
+PFS_builtin_memory_class builtin_memory_thread_statements_stack;
+PFS_builtin_memory_class builtin_memory_thread_statements_stack_tokens;
+PFS_builtin_memory_class builtin_memory_thread_statements_stack_sqltext;
+PFS_builtin_memory_class builtin_memory_thread_transaction_history;
+PFS_builtin_memory_class builtin_memory_thread_session_connect_attrs;
+
+PFS_builtin_memory_class builtin_memory_user;
+PFS_builtin_memory_class builtin_memory_user_waits;
+PFS_builtin_memory_class builtin_memory_user_stages;
+PFS_builtin_memory_class builtin_memory_user_statements;
+PFS_builtin_memory_class builtin_memory_user_transactions;
+PFS_builtin_memory_class builtin_memory_user_memory;
+
+PFS_builtin_memory_class builtin_memory_mutex_class;
+PFS_builtin_memory_class builtin_memory_rwlock_class;
+PFS_builtin_memory_class builtin_memory_cond_class;
+PFS_builtin_memory_class builtin_memory_thread_class;
+PFS_builtin_memory_class builtin_memory_file_class;
+PFS_builtin_memory_class builtin_memory_socket_class;
+PFS_builtin_memory_class builtin_memory_stage_class;
+PFS_builtin_memory_class builtin_memory_statement_class;
+PFS_builtin_memory_class builtin_memory_memory_class;
+
+PFS_builtin_memory_class builtin_memory_setup_actor;
+PFS_builtin_memory_class builtin_memory_setup_object;
+
+PFS_builtin_memory_class builtin_memory_digest;
+PFS_builtin_memory_class builtin_memory_digest_tokens;
+
+PFS_builtin_memory_class builtin_memory_stages_history_long;
+PFS_builtin_memory_class builtin_memory_statements_history_long;
+PFS_builtin_memory_class builtin_memory_statements_history_long_tokens;
+PFS_builtin_memory_class builtin_memory_statements_history_long_sqltext;
+PFS_builtin_memory_class builtin_memory_transactions_history_long;
+PFS_builtin_memory_class builtin_memory_waits_history_long;
+
+PFS_builtin_memory_class builtin_memory_table;
+PFS_builtin_memory_class builtin_memory_table_share;
+PFS_builtin_memory_class builtin_memory_table_share_index;
+PFS_builtin_memory_class builtin_memory_table_share_lock;
+
+PFS_builtin_memory_class builtin_memory_program;
+PFS_builtin_memory_class builtin_memory_prepared_stmt;
+
+PFS_builtin_memory_class builtin_memory_scalable_buffer;
+
+static void init_builtin_memory_class(PFS_builtin_memory_class *klass, const char* name)
+{
+ klass->m_class.m_type= PFS_CLASS_MEMORY;
+ klass->m_class.m_enabled= true; /* Immutable */
+ klass->m_class.m_timed= false; /* Immutable */
+ klass->m_class.m_flags= PSI_FLAG_GLOBAL;
+ klass->m_class.m_event_name_index= 0;
+ my_snprintf(klass->m_class.m_name, sizeof(klass->m_class.m_name), "%.*s",
+ PFS_MAX_INFO_NAME_LENGTH - 1, name);
+ klass->m_class.m_name_length= strlen(name);
+ DBUG_ASSERT(klass->m_class.m_name_length < sizeof(klass->m_class.m_name));
+ klass->m_class.m_timer= NULL;
+
+ klass->m_stat.reset();
+}
+
+void init_all_builtin_memory_class()
+{
+ init_builtin_memory_class( & builtin_memory_mutex,
+ "memory/performance_schema/mutex_instances");
+ init_builtin_memory_class( & builtin_memory_rwlock,
+ "memory/performance_schema/rwlock_instances");
+ init_builtin_memory_class( & builtin_memory_cond,
+ "memory/performance_schema/cond_instances");
+ init_builtin_memory_class( & builtin_memory_file,
+ "memory/performance_schema/file_instances");
+ init_builtin_memory_class( & builtin_memory_socket,
+ "memory/performance_schema/socket_instances");
+ init_builtin_memory_class( & builtin_memory_mdl,
+ "memory/performance_schema/metadata_locks");
+ init_builtin_memory_class( & builtin_memory_file_handle,
+ "memory/performance_schema/file_handle");
+
+ init_builtin_memory_class( & builtin_memory_account,
+ "memory/performance_schema/accounts");
+ init_builtin_memory_class( & builtin_memory_account_waits,
+ "memory/performance_schema/events_waits_summary_by_account_by_event_name");
+ init_builtin_memory_class( & builtin_memory_account_stages,
+ "memory/performance_schema/events_stages_summary_by_account_by_event_name");
+ init_builtin_memory_class( & builtin_memory_account_statements,
+ "memory/performance_schema/events_statements_summary_by_account_by_event_name");
+ init_builtin_memory_class( & builtin_memory_account_transactions,
+ "memory/performance_schema/events_transactions_summary_by_account_by_event_name");
+ init_builtin_memory_class( & builtin_memory_account_memory,
+ "memory/performance_schema/memory_summary_by_account_by_event_name");
+
+ init_builtin_memory_class( & builtin_memory_global_stages,
+ "memory/performance_schema/events_stages_summary_global_by_event_name");
+ init_builtin_memory_class( & builtin_memory_global_statements,
+ "memory/performance_schema/events_statements_summary_global_by_event_name");
+ init_builtin_memory_class( & builtin_memory_global_memory,
+ "memory/performance_schema/memory_summary_global_by_event_name");
+
+ init_builtin_memory_class( & builtin_memory_host,
+ "memory/performance_schema/hosts");
+ init_builtin_memory_class( & builtin_memory_host_waits,
+ "memory/performance_schema/events_waits_summary_by_host_by_event_name");
+ init_builtin_memory_class( & builtin_memory_host_stages,
+ "memory/performance_schema/events_stages_summary_by_host_by_event_name");
+ init_builtin_memory_class( & builtin_memory_host_statements,
+ "memory/performance_schema/events_statements_summary_by_host_by_event_name");
+ init_builtin_memory_class( & builtin_memory_host_transactions,
+ "memory/performance_schema/events_transactions_summary_by_host_by_event_name");
+ init_builtin_memory_class( & builtin_memory_host_memory,
+ "memory/performance_schema/memory_summary_by_host_by_event_name");
+
+ init_builtin_memory_class( & builtin_memory_thread,
+ "memory/performance_schema/threads");
+ init_builtin_memory_class( & builtin_memory_thread_waits,
+ "memory/performance_schema/events_waits_summary_by_thread_by_event_name");
+ init_builtin_memory_class( & builtin_memory_thread_stages,
+ "memory/performance_schema/events_stages_summary_by_thread_by_event_name");
+ init_builtin_memory_class( & builtin_memory_thread_statements,
+ "memory/performance_schema/events_statements_summary_by_thread_by_event_name");
+ init_builtin_memory_class( & builtin_memory_thread_transactions,
+ "memory/performance_schema/events_transactions_summary_by_thread_by_event_name");
+ init_builtin_memory_class( & builtin_memory_thread_memory,
+ "memory/performance_schema/memory_summary_by_thread_by_event_name");
+
+ init_builtin_memory_class( & builtin_memory_thread_waits_history,
+ "memory/performance_schema/events_waits_history");
+ init_builtin_memory_class( & builtin_memory_thread_stages_history,
+ "memory/performance_schema/events_stages_history");
+ init_builtin_memory_class( & builtin_memory_thread_statements_history,
+ "memory/performance_schema/events_statements_history");
+ init_builtin_memory_class( & builtin_memory_thread_statements_history_tokens,
+ "memory/performance_schema/events_statements_history.tokens");
+ init_builtin_memory_class( & builtin_memory_thread_statements_history_sqltext,
+ "memory/performance_schema/events_statements_history.sqltext");
+ init_builtin_memory_class( & builtin_memory_thread_statements_stack,
+ "memory/performance_schema/events_statements_current");
+ init_builtin_memory_class( & builtin_memory_thread_statements_stack_tokens,
+ "memory/performance_schema/events_statements_current.tokens");
+ init_builtin_memory_class( & builtin_memory_thread_statements_stack_sqltext,
+ "memory/performance_schema/events_statements_current.sqltext");
+ init_builtin_memory_class( & builtin_memory_thread_transaction_history,
+ "memory/performance_schema/events_transactions_history");
+ init_builtin_memory_class( & builtin_memory_thread_session_connect_attrs,
+ "memory/performance_schema/session_connect_attrs");
+
+ init_builtin_memory_class( & builtin_memory_user,
+ "memory/performance_schema/users");
+ init_builtin_memory_class( & builtin_memory_user_waits,
+ "memory/performance_schema/events_waits_summary_by_user_by_event_name");
+ init_builtin_memory_class( & builtin_memory_user_stages,
+ "memory/performance_schema/events_stages_summary_by_user_by_event_name");
+ init_builtin_memory_class( & builtin_memory_user_statements,
+ "memory/performance_schema/events_statements_summary_by_user_by_event_name");
+ init_builtin_memory_class( & builtin_memory_user_transactions,
+ "memory/performance_schema/events_transactions_summary_by_user_by_event_name");
+ init_builtin_memory_class( & builtin_memory_user_memory,
+ "memory/performance_schema/memory_summary_by_user_by_event_name");
+
+ init_builtin_memory_class( & builtin_memory_mutex_class,
+ "memory/performance_schema/mutex_class");
+ init_builtin_memory_class( & builtin_memory_rwlock_class,
+ "memory/performance_schema/rwlock_class");
+ init_builtin_memory_class( & builtin_memory_cond_class,
+ "memory/performance_schema/cond_class");
+ init_builtin_memory_class( & builtin_memory_thread_class,
+ "memory/performance_schema/thread_class");
+ init_builtin_memory_class( & builtin_memory_file_class,
+ "memory/performance_schema/file_class");
+ init_builtin_memory_class( & builtin_memory_socket_class,
+ "memory/performance_schema/socket_class");
+ init_builtin_memory_class( & builtin_memory_stage_class,
+ "memory/performance_schema/stage_class");
+ init_builtin_memory_class( & builtin_memory_statement_class,
+ "memory/performance_schema/statement_class");
+ init_builtin_memory_class( & builtin_memory_memory_class,
+ "memory/performance_schema/memory_class");
+
+ init_builtin_memory_class( & builtin_memory_setup_actor,
+ "memory/performance_schema/setup_actors");
+ init_builtin_memory_class( & builtin_memory_setup_object,
+ "memory/performance_schema/setup_objects");
+
+ init_builtin_memory_class( & builtin_memory_digest,
+ "memory/performance_schema/events_statements_summary_by_digest");
+ init_builtin_memory_class( & builtin_memory_digest_tokens,
+ "memory/performance_schema/events_statements_summary_by_digest.tokens");
+
+ init_builtin_memory_class( & builtin_memory_stages_history_long,
+ "memory/performance_schema/events_stages_history_long");
+ init_builtin_memory_class( & builtin_memory_statements_history_long,
+ "memory/performance_schema/events_statements_history_long");
+ init_builtin_memory_class( & builtin_memory_statements_history_long_tokens,
+ "memory/performance_schema/events_statements_history_long.tokens");
+ init_builtin_memory_class( & builtin_memory_statements_history_long_sqltext,
+ "memory/performance_schema/events_statements_history_long.sqltext");
+ init_builtin_memory_class( & builtin_memory_transactions_history_long,
+ "memory/performance_schema/events_transactions_history_long");
+ init_builtin_memory_class( & builtin_memory_waits_history_long,
+ "memory/performance_schema/events_waits_history_long");
+
+ init_builtin_memory_class( & builtin_memory_table,
+ "memory/performance_schema/table_handles");
+ init_builtin_memory_class( & builtin_memory_table_share,
+ "memory/performance_schema/table_shares");
+ init_builtin_memory_class( & builtin_memory_table_share_index,
+ "memory/performance_schema/table_io_waits_summary_by_index_usage");
+ init_builtin_memory_class( & builtin_memory_table_share_lock,
+ "memory/performance_schema/table_lock_waits_summary_by_table");
+
+ init_builtin_memory_class( & builtin_memory_program,
+ "memory/performance_schema/events_statements_summary_by_program");
+ init_builtin_memory_class( & builtin_memory_prepared_stmt,
+ "memory/performance_schema/prepared_statements_instances");
+
+ init_builtin_memory_class( & builtin_memory_scalable_buffer,
+ "memory/performance_schema/scalable_buffer");
+}
+
+static PFS_builtin_memory_class* all_builtin_memory[]=
+{
+ & builtin_memory_mutex,
+ & builtin_memory_rwlock,
+ & builtin_memory_cond,
+ & builtin_memory_file,
+ & builtin_memory_socket,
+ & builtin_memory_mdl,
+ & builtin_memory_file_handle,
+
+ & builtin_memory_account,
+ & builtin_memory_account_waits,
+ & builtin_memory_account_stages,
+ & builtin_memory_account_statements,
+ & builtin_memory_account_transactions,
+ & builtin_memory_account_memory,
+
+ & builtin_memory_global_stages,
+ & builtin_memory_global_statements,
+ & builtin_memory_global_memory,
+
+ & builtin_memory_host,
+ & builtin_memory_host_waits,
+ & builtin_memory_host_stages,
+ & builtin_memory_host_statements,
+ & builtin_memory_host_transactions,
+ & builtin_memory_host_memory,
+
+ & builtin_memory_thread,
+ & builtin_memory_thread_waits,
+ & builtin_memory_thread_stages,
+ & builtin_memory_thread_statements,
+ & builtin_memory_thread_transactions,
+ & builtin_memory_thread_memory,
+
+ & builtin_memory_thread_waits_history,
+ & builtin_memory_thread_stages_history,
+ & builtin_memory_thread_statements_history,
+ & builtin_memory_thread_statements_history_tokens,
+ & builtin_memory_thread_statements_history_sqltext,
+ & builtin_memory_thread_statements_stack,
+ & builtin_memory_thread_statements_stack_tokens,
+ & builtin_memory_thread_statements_stack_sqltext,
+ & builtin_memory_thread_transaction_history,
+ & builtin_memory_thread_session_connect_attrs,
+
+ & builtin_memory_user,
+ & builtin_memory_user_waits,
+ & builtin_memory_user_stages,
+ & builtin_memory_user_statements,
+ & builtin_memory_user_transactions,
+ & builtin_memory_user_memory,
+
+ & builtin_memory_mutex_class,
+ & builtin_memory_rwlock_class,
+ & builtin_memory_cond_class,
+ & builtin_memory_thread_class,
+ & builtin_memory_file_class,
+ & builtin_memory_socket_class,
+ & builtin_memory_stage_class,
+ & builtin_memory_statement_class,
+ & builtin_memory_memory_class,
+
+ & builtin_memory_setup_actor,
+ & builtin_memory_setup_object,
+
+ & builtin_memory_digest,
+ & builtin_memory_digest_tokens,
+
+ & builtin_memory_stages_history_long,
+ & builtin_memory_statements_history_long,
+ & builtin_memory_statements_history_long_tokens,
+ & builtin_memory_statements_history_long_sqltext,
+ & builtin_memory_transactions_history_long,
+ & builtin_memory_waits_history_long,
+
+ & builtin_memory_table,
+ & builtin_memory_table_share,
+ & builtin_memory_table_share_index,
+ & builtin_memory_table_share_lock,
+
+ & builtin_memory_program,
+ & builtin_memory_prepared_stmt,
+
+ & builtin_memory_scalable_buffer,
+
+ NULL
+};
+
+
+PFS_builtin_memory_class *find_builtin_memory_class(PFS_builtin_memory_key key)
+{
+ if (key == 0)
+ return NULL;
+
+ return all_builtin_memory[key - 1];
+}
+
diff --git a/storage/perfschema/pfs_builtin_memory.h b/storage/perfschema/pfs_builtin_memory.h
new file mode 100644
index 00000000000..1c00275d5b9
--- /dev/null
+++ b/storage/perfschema/pfs_builtin_memory.h
@@ -0,0 +1,143 @@
+/* Copyright (c) 2014, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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 PFS_BUILTIN_MEMORY_H
+#define PFS_BUILTIN_MEMORY_H
+
+#include "my_global.h"
+#include "pfs_global.h"
+#include "pfs_instr_class.h"
+
+/**
+ @file storage/perfschema/pfs_builtin_memory.h
+ Performance schema instruments meta data (declarations).
+*/
+
+typedef uint PFS_builtin_memory_key;
+
+struct PFS_builtin_memory_class
+{
+ PFS_memory_class m_class;
+ PFS_memory_stat m_stat;
+
+ inline void count_alloc(size_t size)
+ {
+ m_stat.count_builtin_alloc(size);
+ }
+
+ inline void count_free(size_t size)
+ {
+ m_stat.count_builtin_free(size);
+ }
+};
+
+void init_all_builtin_memory_class();
+
+PFS_builtin_memory_class *find_builtin_memory_class(PFS_builtin_memory_key);
+
+extern PFS_builtin_memory_class builtin_memory_mutex;
+extern PFS_builtin_memory_class builtin_memory_rwlock;
+extern PFS_builtin_memory_class builtin_memory_cond;
+extern PFS_builtin_memory_class builtin_memory_file;
+extern PFS_builtin_memory_class builtin_memory_socket;
+extern PFS_builtin_memory_class builtin_memory_mdl;
+extern PFS_builtin_memory_class builtin_memory_file_handle;
+
+extern PFS_builtin_memory_class builtin_memory_account;
+extern PFS_builtin_memory_class builtin_memory_account_waits;
+extern PFS_builtin_memory_class builtin_memory_account_stages;
+extern PFS_builtin_memory_class builtin_memory_account_statements;
+extern PFS_builtin_memory_class builtin_memory_account_transactions;
+extern PFS_builtin_memory_class builtin_memory_account_memory;
+
+extern PFS_builtin_memory_class builtin_memory_global_stages;
+extern PFS_builtin_memory_class builtin_memory_global_statements;
+extern PFS_builtin_memory_class builtin_memory_global_memory;
+
+extern PFS_builtin_memory_class builtin_memory_host;
+extern PFS_builtin_memory_class builtin_memory_host_waits;
+extern PFS_builtin_memory_class builtin_memory_host_stages;
+extern PFS_builtin_memory_class builtin_memory_host_statements;
+extern PFS_builtin_memory_class builtin_memory_host_transactions;
+extern PFS_builtin_memory_class builtin_memory_host_memory;
+
+extern PFS_builtin_memory_class builtin_memory_thread;
+extern PFS_builtin_memory_class builtin_memory_thread_waits;
+extern PFS_builtin_memory_class builtin_memory_thread_stages;
+extern PFS_builtin_memory_class builtin_memory_thread_statements;
+extern PFS_builtin_memory_class builtin_memory_thread_transactions;
+extern PFS_builtin_memory_class builtin_memory_thread_memory;
+
+extern PFS_builtin_memory_class builtin_memory_thread_waits_history;
+extern PFS_builtin_memory_class builtin_memory_thread_stages_history;
+extern PFS_builtin_memory_class builtin_memory_thread_statements_history;
+extern PFS_builtin_memory_class builtin_memory_thread_statements_history_tokens;
+extern PFS_builtin_memory_class builtin_memory_thread_statements_history_sqltext;
+extern PFS_builtin_memory_class builtin_memory_thread_statements_stack;
+extern PFS_builtin_memory_class builtin_memory_thread_statements_stack_tokens;
+extern PFS_builtin_memory_class builtin_memory_thread_statements_stack_sqltext;
+extern PFS_builtin_memory_class builtin_memory_thread_transaction_history;
+extern PFS_builtin_memory_class builtin_memory_thread_session_connect_attrs;
+
+extern PFS_builtin_memory_class builtin_memory_user;
+extern PFS_builtin_memory_class builtin_memory_user_waits;
+extern PFS_builtin_memory_class builtin_memory_user_stages;
+extern PFS_builtin_memory_class builtin_memory_user_statements;
+extern PFS_builtin_memory_class builtin_memory_user_transactions;
+extern PFS_builtin_memory_class builtin_memory_user_memory;
+
+extern PFS_builtin_memory_class builtin_memory_mutex_class;
+extern PFS_builtin_memory_class builtin_memory_rwlock_class;
+extern PFS_builtin_memory_class builtin_memory_cond_class;
+extern PFS_builtin_memory_class builtin_memory_thread_class;
+extern PFS_builtin_memory_class builtin_memory_file_class;
+extern PFS_builtin_memory_class builtin_memory_socket_class;
+extern PFS_builtin_memory_class builtin_memory_stage_class;
+extern PFS_builtin_memory_class builtin_memory_statement_class;
+extern PFS_builtin_memory_class builtin_memory_memory_class;
+
+extern PFS_builtin_memory_class builtin_memory_setup_actor;
+extern PFS_builtin_memory_class builtin_memory_setup_object;
+
+extern PFS_builtin_memory_class builtin_memory_digest;
+extern PFS_builtin_memory_class builtin_memory_digest_tokens;
+
+extern PFS_builtin_memory_class builtin_memory_stages_history_long;
+extern PFS_builtin_memory_class builtin_memory_statements_history_long;
+extern PFS_builtin_memory_class builtin_memory_statements_history_long_tokens;
+extern PFS_builtin_memory_class builtin_memory_statements_history_long_sqltext;
+extern PFS_builtin_memory_class builtin_memory_transactions_history_long;
+extern PFS_builtin_memory_class builtin_memory_waits_history_long;
+
+extern PFS_builtin_memory_class builtin_memory_table;
+extern PFS_builtin_memory_class builtin_memory_table_share;
+extern PFS_builtin_memory_class builtin_memory_table_share_index;
+extern PFS_builtin_memory_class builtin_memory_table_share_lock;
+
+extern PFS_builtin_memory_class builtin_memory_program;
+extern PFS_builtin_memory_class builtin_memory_prepared_stmt;
+
+extern PFS_builtin_memory_class builtin_memory_scalable_buffer;
+
+/** @} */
+#endif
+
diff --git a/storage/perfschema/pfs_column_types.h b/storage/perfschema/pfs_column_types.h
index 09fce551402..b47f9ab938f 100644
--- a/storage/perfschema/pfs_column_types.h
+++ b/storage/perfschema/pfs_column_types.h
@@ -63,9 +63,6 @@
/** Size of the DIGEST columns. */
#define COL_DIGEST_SIZE 64
-/** Size of the DIGEST_TEXT columns. */
-#define COL_DIGEST_TEXT_SIZE 1024
-
/**
Enum values for the TIMER_NAME columns.
This enum is found in the following tables:
@@ -114,78 +111,88 @@ enum enum_operation_type
OPERATION_TYPE_LOCK= 1,
OPERATION_TYPE_TRYLOCK= 2,
- /* Rwlock operations */
+ /* Rwlock operations (RW-lock) */
OPERATION_TYPE_READLOCK= 3,
OPERATION_TYPE_WRITELOCK= 4,
OPERATION_TYPE_TRYREADLOCK= 5,
OPERATION_TYPE_TRYWRITELOCK= 6,
+ /* Rwlock operations (SX-lock) */
+ OPERATION_TYPE_SHAREDLOCK= 7,
+ OPERATION_TYPE_SHAREDEXCLUSIVELOCK= 8,
+ OPERATION_TYPE_EXCLUSIVELOCK= 9,
+ OPERATION_TYPE_TRYSHAREDLOCK= 10,
+ OPERATION_TYPE_TRYSHAREDEXCLUSIVELOCK= 11,
+ OPERATION_TYPE_TRYEXCLUSIVELOCK= 12,
+
/* Cond operations */
- OPERATION_TYPE_WAIT= 7,
- OPERATION_TYPE_TIMEDWAIT= 8,
+ OPERATION_TYPE_WAIT= 13,
+ OPERATION_TYPE_TIMEDWAIT= 14,
/* File operations */
- OPERATION_TYPE_FILECREATE= 9,
- OPERATION_TYPE_FILECREATETMP= 10,
- OPERATION_TYPE_FILEOPEN= 11,
- OPERATION_TYPE_FILESTREAMOPEN= 12,
- OPERATION_TYPE_FILECLOSE= 13,
- OPERATION_TYPE_FILESTREAMCLOSE= 14,
- OPERATION_TYPE_FILEREAD= 15,
- OPERATION_TYPE_FILEWRITE= 16,
- OPERATION_TYPE_FILESEEK= 17,
- OPERATION_TYPE_FILETELL= 18,
- OPERATION_TYPE_FILEFLUSH= 19,
- OPERATION_TYPE_FILESTAT= 20,
- OPERATION_TYPE_FILEFSTAT= 21,
- OPERATION_TYPE_FILECHSIZE= 22,
- OPERATION_TYPE_FILEDELETE= 23,
- OPERATION_TYPE_FILERENAME= 24,
- OPERATION_TYPE_FILESYNC= 25,
+ OPERATION_TYPE_FILECREATE= 15,
+ OPERATION_TYPE_FILECREATETMP= 16,
+ OPERATION_TYPE_FILEOPEN= 17,
+ OPERATION_TYPE_FILESTREAMOPEN= 18,
+ OPERATION_TYPE_FILECLOSE= 19,
+ OPERATION_TYPE_FILESTREAMCLOSE= 20,
+ OPERATION_TYPE_FILEREAD= 21,
+ OPERATION_TYPE_FILEWRITE= 22,
+ OPERATION_TYPE_FILESEEK= 23,
+ OPERATION_TYPE_FILETELL= 24,
+ OPERATION_TYPE_FILEFLUSH= 25,
+ OPERATION_TYPE_FILESTAT= 26,
+ OPERATION_TYPE_FILEFSTAT= 27,
+ OPERATION_TYPE_FILECHSIZE= 28,
+ OPERATION_TYPE_FILEDELETE= 29,
+ OPERATION_TYPE_FILERENAME= 30,
+ OPERATION_TYPE_FILESYNC= 31,
/* Table io operations */
- OPERATION_TYPE_TABLE_FETCH= 26,
- OPERATION_TYPE_TABLE_WRITE_ROW= 27,
- OPERATION_TYPE_TABLE_UPDATE_ROW= 28,
- OPERATION_TYPE_TABLE_DELETE_ROW= 29,
+ OPERATION_TYPE_TABLE_FETCH= 32,
+ OPERATION_TYPE_TABLE_WRITE_ROW= 33,
+ OPERATION_TYPE_TABLE_UPDATE_ROW= 34,
+ OPERATION_TYPE_TABLE_DELETE_ROW= 35,
/* Table lock operations */
- OPERATION_TYPE_TL_READ_NORMAL= 30,
- OPERATION_TYPE_TL_READ_WITH_SHARED_LOCKS= 31,
- OPERATION_TYPE_TL_READ_HIGH_PRIORITY= 32,
- OPERATION_TYPE_TL_READ_NO_INSERTS= 33,
- OPERATION_TYPE_TL_WRITE_ALLOW_WRITE= 34,
- OPERATION_TYPE_TL_WRITE_CONCURRENT_INSERT= 35,
- OPERATION_TYPE_TL_WRITE_DELAYED= 36,
- OPERATION_TYPE_TL_WRITE_LOW_PRIORITY= 37,
- OPERATION_TYPE_TL_WRITE_NORMAL= 38,
- OPERATION_TYPE_TL_READ_EXTERNAL= 39,
- OPERATION_TYPE_TL_WRITE_EXTERNAL= 40,
+ OPERATION_TYPE_TL_READ_NORMAL= 36,
+ OPERATION_TYPE_TL_READ_WITH_SHARED_LOCKS= 37,
+ OPERATION_TYPE_TL_READ_HIGH_PRIORITY= 38,
+ OPERATION_TYPE_TL_READ_NO_INSERTS= 39,
+ OPERATION_TYPE_TL_WRITE_ALLOW_WRITE= 40,
+ OPERATION_TYPE_TL_WRITE_CONCURRENT_INSERT= 41,
+ OPERATION_TYPE_TL_WRITE_LOW_PRIORITY= 42,
+ OPERATION_TYPE_TL_WRITE_NORMAL= 43,
+ OPERATION_TYPE_TL_READ_EXTERNAL= 44,
+ OPERATION_TYPE_TL_WRITE_EXTERNAL= 45,
/* Socket operations */
- OPERATION_TYPE_SOCKETCREATE = 41,
- OPERATION_TYPE_SOCKETCONNECT = 42,
- OPERATION_TYPE_SOCKETBIND = 43,
- OPERATION_TYPE_SOCKETCLOSE = 44,
- OPERATION_TYPE_SOCKETSEND = 45,
- OPERATION_TYPE_SOCKETRECV = 46,
- OPERATION_TYPE_SOCKETSENDTO = 47,
- OPERATION_TYPE_SOCKETRECVFROM = 48,
- OPERATION_TYPE_SOCKETSENDMSG = 49,
- OPERATION_TYPE_SOCKETRECVMSG = 50,
- OPERATION_TYPE_SOCKETSEEK = 51,
- OPERATION_TYPE_SOCKETOPT = 52,
- OPERATION_TYPE_SOCKETSTAT = 53,
- OPERATION_TYPE_SOCKETSHUTDOWN = 54,
- OPERATION_TYPE_SOCKETSELECT = 55,
+ OPERATION_TYPE_SOCKETCREATE = 46,
+ OPERATION_TYPE_SOCKETCONNECT = 47,
+ OPERATION_TYPE_SOCKETBIND = 48,
+ OPERATION_TYPE_SOCKETCLOSE = 49,
+ OPERATION_TYPE_SOCKETSEND = 50,
+ OPERATION_TYPE_SOCKETRECV = 51,
+ OPERATION_TYPE_SOCKETSENDTO = 52,
+ OPERATION_TYPE_SOCKETRECVFROM = 53,
+ OPERATION_TYPE_SOCKETSENDMSG = 54,
+ OPERATION_TYPE_SOCKETRECVMSG = 55,
+ OPERATION_TYPE_SOCKETSEEK = 56,
+ OPERATION_TYPE_SOCKETOPT = 57,
+ OPERATION_TYPE_SOCKETSTAT = 58,
+ OPERATION_TYPE_SOCKETSHUTDOWN = 59,
+ OPERATION_TYPE_SOCKETSELECT = 60,
/* Idle operation */
- OPERATION_TYPE_IDLE= 56
+ OPERATION_TYPE_IDLE= 61,
+
+ /* Metadata lock operation */
+ OPERATION_TYPE_METADATA= 62
};
/** Integer, first value of @sa enum_operation_type. */
#define FIRST_OPERATION_TYPE (static_cast<int> (OPERATION_TYPE_LOCK))
/** Integer, last value of @sa enum_operation_type. */
-#define LAST_OPERATION_TYPE (static_cast<int> (OPERATION_TYPE_IDLE))
+#define LAST_OPERATION_TYPE (static_cast<int> (OPERATION_TYPE_METADATA))
/** Integer, number of values of @sa enum_operation_type. */
#define COUNT_OPERATION_TYPE (LAST_OPERATION_TYPE - FIRST_OPERATION_TYPE + 1)
@@ -194,13 +201,30 @@ enum enum_operation_type
*/
enum enum_object_type
{
- OBJECT_TYPE_TABLE= 1,
- OBJECT_TYPE_TEMPORARY_TABLE= 2
+ NO_OBJECT_TYPE= 0,
+
+ /* Advertised in SQL ENUM */
+
+ OBJECT_TYPE_EVENT= 1,
+ OBJECT_TYPE_FUNCTION= 2,
+ OBJECT_TYPE_PROCEDURE= 3,
+ OBJECT_TYPE_TABLE= 4,
+ OBJECT_TYPE_TRIGGER= 5,
+
+ /* Not advertised in SQL ENUM, only displayed as VARCHAR */
+
+ OBJECT_TYPE_TEMPORARY_TABLE= 6,
+ OBJECT_TYPE_GLOBAL= 7,
+ OBJECT_TYPE_SCHEMA= 8,
+ OBJECT_TYPE_COMMIT= 9,
+ OBJECT_TYPE_USER_LEVEL_LOCK= 10,
+ OBJECT_TYPE_TABLESPACE= 11,
+ OBJECT_TYPE_LOCKING_SERVICE= 12
};
/** Integer, first value of @sa enum_object_type. */
-#define FIRST_OBJECT_TYPE (static_cast<int> (OBJECT_TYPE_TABLE))
+#define FIRST_OBJECT_TYPE (static_cast<int> (OBJECT_TYPE_EVENT))
/** Integer, last value of @sa enum_object_type. */
-#define LAST_OBJECT_TYPE (static_cast<int> (OBJECT_TYPE_TEMPORARY_TABLE))
+#define LAST_OBJECT_TYPE (static_cast<int> (OBJECT_TYPE_LOCKING_SERVICE))
/** Integer, number of values of @sa enum_object_type. */
#define COUNT_OBJECT_TYPE (LAST_OBJECT_TYPE - FIRST_OBJECT_TYPE + 1)
@@ -213,17 +237,92 @@ enum enum_object_type
*/
enum enum_event_type
{
- EVENT_TYPE_STATEMENT= 1,
- EVENT_TYPE_STAGE= 2,
- EVENT_TYPE_WAIT= 3
+ EVENT_TYPE_TRANSACTION= 1,
+ EVENT_TYPE_STATEMENT= 2,
+ EVENT_TYPE_STAGE= 3,
+ EVENT_TYPE_WAIT= 4
};
/** Integer, first value of @sa enum_event_type. */
-#define FIRST_EVENT_TYPE (static_cast<int> (EVENT_TYPE_STATEMENT))
+#define FIRST_EVENT_TYPE (static_cast<int> (EVENT_TYPE_TRANSACTION))
/** Integer, last value of @sa enum_event_type. */
#define LAST_EVENT_TYPE (static_cast<int> (EVENT_TYPE_WAIT))
/** Integer, number of values of @sa enum_event_type. */
#define COUNT_EVENT_TYPE (LAST_EVENT_TYPE - FIRST_EVENT_TYPE + 1)
+/**
+ Enum values for transaction state columns.
+*/
+enum enum_transaction_state
+{
+ TRANS_STATE_ACTIVE= 1,
+ TRANS_STATE_COMMITTED= 2,
+ TRANS_STATE_ROLLED_BACK= 3
+};
+
+/** Integer, first value of @sa enum_transaction_state. */
+#define FIRST_TRANS_STATE (static_cast<int> (TRANS_STATE_ACTIVE))
+/** Integer, last value of @sa enum_transaction_state. */
+#define LAST_TRANS_STATE (static_cast<int> (TRANS_STATE_ROLLED_BACK))
+/** Integer, number of values of @sa enum_transaction_state. */
+#define COUNT_TRANS_STATE (LAST_TRANS_STATE - FIRST_TRANS_STATE + 1)
+
+/**
+ Enum values for XA transaction state columns. Enums 1-5 match those used by
+ the server. See XID_STATE::enum xa_states in xa.h.
+*/
+enum enum_xa_transaction_state
+{
+ TRANS_STATE_XA_NOTR,
+ TRANS_STATE_XA_ACTIVE,
+ TRANS_STATE_XA_IDLE,
+ TRANS_STATE_XA_PREPARED,
+ TRANS_STATE_XA_ROLLBACK_ONLY,
+ TRANS_STATE_XA_COMMITTED
+};
+
+/** Integer, first value of @sa enum_xa_transaction_state. */
+#define FIRST_TRANS_STATE_XA (static_cast<int> (TRANS_STATE_XA_NOTR))
+/** Integer, last value of @sa enum_xa_transaction_state. */
+#define LAST_TRANS_STATE_XA (static_cast<int> (TRANS_STATE_XA_COMMITTED))
+/** Integer, number of values of @sa enum_xa_transaction_state. */
+#define COUNT_TRANS_STATE_XA (LAST_TRANS_STATE_XA - FIRST_TRANS_STATE_XA + 1)
+
+/**
+ Enum values for transaction isolation level columns.
+ See enum_tx_isolation in handler.h.
+*/
+enum enum_isolation_level
+{
+ TRANS_LEVEL_READ_UNCOMMITTED,
+ TRANS_LEVEL_READ_COMMITTED,
+ TRANS_LEVEL_REPEATABLE_READ,
+ TRANS_LEVEL_SERIALIZABLE
+};
+
+/** Integer, first value of @sa enum_isolation_level. */
+#define FIRST_TRANS_LEVEL (static_cast<int> (TRANS_LEVEL_READ_UNCOMMITTED))
+/** Integer, last value of @sa enum_isolation_level. */
+#define LAST_TRANS_LEVEL (static_cast<int> (TRANS_LEVEL_SERIALIZABLE))
+/** Integer, number of values of @sa enum_isolation_level. */
+#define COUNT_TRANS_LEVEL (LAST_TRANS_LEVEL - FIRST_TRANS_LEVEL + 1)
+
+/**
+ Enum values for transaction acces mode columns.
+*/
+enum enum_transaction_mode
+{
+ TRANS_MODE_READ_ONLY= 1,
+ TRANS_MODE_READ_WRITE= 2
+};
+
+/** Integer, first value of @sa enum_transaction_mode. */
+#define FIRST_TRANS_MODE (static_cast<int> (TRANS_MODE_READ_WRITE))
+/** Integer, last value of @sa enum_transaction_mode. */
+#define LAST_TRANS_MODE (static_cast<int> (TRANS_MODE_READ_ONLY))
+/** Integer, number of values of @sa enum_transaction_mode. */
+#define COUNT_TRANS_MODE (LAST_TRANS_MODE - FIRST_TRANS_MODE + 1)
+
+
#endif
diff --git a/storage/perfschema/pfs_column_values.cc b/storage/perfschema/pfs_column_values.cc
index 043c8fd2f38..9ce9b3b416d 100644
--- a/storage/perfschema/pfs_column_values.cc
+++ b/storage/perfschema/pfs_column_values.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -38,8 +38,11 @@ LEX_CSTRING mutex_instrument_prefix=
LEX_CSTRING rwlock_instrument_prefix=
{ STRING_WITH_LEN("wait/synch/rwlock/") };
+LEX_CSTRING sxlock_instrument_prefix=
+{ C_STRING_WITH_LEN("wait/synch/sxlock/") };
+
LEX_CSTRING cond_instrument_prefix=
-{ STRING_WITH_LEN("wait/synch/cond/") };
+{ C_STRING_WITH_LEN("wait/synch/cond/") };
LEX_CSTRING thread_instrument_prefix=
{ STRING_WITH_LEN("thread/") };
@@ -53,5 +56,12 @@ LEX_CSTRING stage_instrument_prefix=
LEX_CSTRING statement_instrument_prefix=
{ STRING_WITH_LEN("statement/") };
+LEX_CSTRING transaction_instrument_prefix=
+{ C_STRING_WITH_LEN("transaction") };
+
LEX_CSTRING socket_instrument_prefix=
-{ STRING_WITH_LEN("wait/io/socket/") };
+{ C_STRING_WITH_LEN("wait/io/socket/") };
+
+LEX_CSTRING memory_instrument_prefix=
+{ C_STRING_WITH_LEN("memory/") };
+
diff --git a/storage/perfschema/pfs_column_values.h b/storage/perfschema/pfs_column_values.h
index 44f23527881..ea3d9eb97c3 100644
--- a/storage/perfschema/pfs_column_values.h
+++ b/storage/perfschema/pfs_column_values.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -23,7 +23,7 @@
#ifndef PFS_COLUMN_VALUES_H
#define PFS_COLUMN_VALUES_H
-#include "m_string.h" /* LEX_STRING */
+#include "m_string.h" /* LEX_CSTRING */
/**
@file storage/perfschema/pfs_column_values.h
@@ -38,6 +38,8 @@ extern LEX_CSTRING PERFORMANCE_SCHEMA_str;
extern LEX_CSTRING mutex_instrument_prefix;
/** String prefix for all rwlock instruments. */
extern LEX_CSTRING rwlock_instrument_prefix;
+/** String prefix for all sxlock instruments. */
+extern LEX_CSTRING sxlock_instrument_prefix;
/** String prefix for all cond instruments. */
extern LEX_CSTRING cond_instrument_prefix;
/** String prefix for all thread instruments. */
@@ -48,7 +50,12 @@ extern LEX_CSTRING file_instrument_prefix;
extern LEX_CSTRING stage_instrument_prefix;
/** String prefix for all statement instruments. */
extern LEX_CSTRING statement_instrument_prefix;
+/** String prefix for all transaction instruments. */
+extern LEX_CSTRING transaction_instrument_prefix;
+/** String prefix for all socket instruments. */
extern LEX_CSTRING socket_instrument_prefix;
+/** String prefix for all memory instruments. */
+extern LEX_CSTRING memory_instrument_prefix;
#endif
diff --git a/storage/perfschema/pfs_con_slice.cc b/storage/perfschema/pfs_con_slice.cc
index 9f9deb0919c..3733ad9e3d0 100644
--- a/storage/perfschema/pfs_con_slice.cc
+++ b/storage/perfschema/pfs_con_slice.cc
@@ -22,7 +22,7 @@
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_con_slice.h"
#include "pfs_stat.h"
#include "pfs_global.h"
@@ -38,66 +38,6 @@
@{
*/
-PFS_single_stat *
-PFS_connection_slice::alloc_waits_slice(uint sizing)
-{
- PFS_single_stat *slice= NULL;
- uint index;
-
- if (sizing > 0)
- {
- slice= PFS_MALLOC_ARRAY(sizing, sizeof(PFS_single_stat), PFS_single_stat,
- MYF(MY_ZEROFILL));
- if (unlikely(slice == NULL))
- return NULL;
-
- for (index= 0; index < sizing; index++)
- slice[index].reset();
- }
-
- return slice;
-}
-
-PFS_stage_stat *
-PFS_connection_slice::alloc_stages_slice(uint sizing)
-{
- PFS_stage_stat *slice= NULL;
- uint index;
-
- if (sizing > 0)
- {
- slice= PFS_MALLOC_ARRAY(sizing, sizeof(PFS_stage_stat), PFS_stage_stat,
- MYF(MY_ZEROFILL));
- if (unlikely(slice == NULL))
- return NULL;
-
- for (index= 0; index < sizing; index++)
- slice[index].reset();
- }
-
- return slice;
-}
-
-PFS_statement_stat *
-PFS_connection_slice::alloc_statements_slice(uint sizing)
-{
- PFS_statement_stat *slice= NULL;
- uint index;
-
- if (sizing > 0)
- {
- slice= PFS_MALLOC_ARRAY(sizing, sizeof(PFS_statement_stat), PFS_statement_stat,
- MYF(MY_ZEROFILL));
- if (unlikely(slice == NULL))
- return NULL;
-
- for (index= 0; index < sizing; index++)
- slice[index].reset();
- }
-
- return slice;
-}
-
void PFS_connection_slice::reset_waits_stats()
{
PFS_single_stat *stat= m_instr_class_waits_stats;
@@ -122,5 +62,21 @@ void PFS_connection_slice::reset_statements_stats()
stat->reset();
}
+void PFS_connection_slice::reset_transactions_stats()
+{
+ PFS_transaction_stat *stat=
+ &m_instr_class_transactions_stats[GLOBAL_TRANSACTION_INDEX];
+ if (stat)
+ stat->reset();
+}
+
+void PFS_connection_slice::rebase_memory_stats()
+{
+ PFS_memory_stat *stat= m_instr_class_memory_stats;
+ PFS_memory_stat *stat_last= stat + memory_class_max;
+ for ( ; stat < stat_last; stat++)
+ stat->reset();
+}
+
/** @} */
diff --git a/storage/perfschema/pfs_con_slice.h b/storage/perfschema/pfs_con_slice.h
index ed17de5f2b0..56497ffe771 100644
--- a/storage/perfschema/pfs_con_slice.h
+++ b/storage/perfschema/pfs_con_slice.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2016, 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, version 2.0,
@@ -28,12 +28,17 @@
Performance schema connection slice (declarations).
*/
+#include "sql_class.h"
#include "pfs_lock.h"
#include "lf.h"
+#include "pfs_status.h"
struct PFS_single_stat;
struct PFS_stage_stat;
struct PFS_statement_stat;
+struct PFS_transaction_stat;
+struct PFS_memory_stat;
+class PFS_opaque_container_page;
/**
@addtogroup Performance_schema_buffers
@@ -46,31 +51,15 @@ struct PFS_statement_stat;
*/
struct PFS_connection_slice
{
- /**
- Allocate memory for waits statistics.
- @param sizing the number of wait classes.
- @return wait statistics for this slice.
- */
- static PFS_single_stat *alloc_waits_slice(uint sizing);
- /**
- Allocate memory for stages statistics.
- @param sizing the number of stage classes.
- @return stage statistics for this slice.
- */
- static PFS_stage_stat *alloc_stages_slice(uint sizing);
- /**
- Allocate memory for statement statistics.
- @param sizing the number of statement classes.
- @return statement statistics for this slice.
- */
- static PFS_statement_stat *alloc_statements_slice(uint sizing);
-
/** Reset all statistics. */
inline void reset_stats()
{
- reset_waits_stats();
- reset_stages_stats();
- reset_statements_stats();
+ m_has_waits_stats= false;
+ m_has_stages_stats= false;
+ m_has_statements_stats= false;
+ m_has_transactions_stats= false;
+ m_has_memory_stats= false;
+ reset_status_stats();
}
/** Reset all wait statistics. */
@@ -79,6 +68,137 @@ struct PFS_connection_slice
void reset_stages_stats();
/** Reset all statements statistics. */
void reset_statements_stats();
+ /** Reset all transactions statistics. */
+ void reset_transactions_stats();
+ /** Reset all memory statistics. */
+ void rebase_memory_stats();
+ /** Reset all status variable statistics. */
+ void reset_status_stats()
+ {
+ m_status_stats.reset();
+ }
+
+ void set_instr_class_waits_stats(PFS_single_stat *array)
+ {
+ m_has_waits_stats= false;
+ m_instr_class_waits_stats= array;
+ }
+
+ const PFS_single_stat* read_instr_class_waits_stats() const
+ {
+ if (! m_has_waits_stats)
+ return NULL;
+ return m_instr_class_waits_stats;
+ }
+
+ PFS_single_stat* write_instr_class_waits_stats()
+ {
+ if (! m_has_waits_stats)
+ {
+ reset_waits_stats();
+ m_has_waits_stats= true;
+ }
+ return m_instr_class_waits_stats;
+ }
+
+ void set_instr_class_stages_stats(PFS_stage_stat *array)
+ {
+ m_has_stages_stats= false;
+ m_instr_class_stages_stats= array;
+ }
+
+ const PFS_stage_stat* read_instr_class_stages_stats() const
+ {
+ if (! m_has_stages_stats)
+ return NULL;
+ return m_instr_class_stages_stats;
+ }
+
+ PFS_stage_stat* write_instr_class_stages_stats()
+ {
+ if (! m_has_stages_stats)
+ {
+ reset_stages_stats();
+ m_has_stages_stats= true;
+ }
+ return m_instr_class_stages_stats;
+ }
+
+ void set_instr_class_statements_stats(PFS_statement_stat *array)
+ {
+ m_has_statements_stats= false;
+ m_instr_class_statements_stats= array;
+ }
+
+ const PFS_statement_stat* read_instr_class_statements_stats() const
+ {
+ if (! m_has_statements_stats)
+ return NULL;
+ return m_instr_class_statements_stats;
+ }
+
+ PFS_statement_stat* write_instr_class_statements_stats()
+ {
+ if (! m_has_statements_stats)
+ {
+ reset_statements_stats();
+ m_has_statements_stats= true;
+ }
+ return m_instr_class_statements_stats;
+ }
+
+ void set_instr_class_transactions_stats(PFS_transaction_stat *array)
+ {
+ m_has_transactions_stats= false;
+ m_instr_class_transactions_stats= array;
+ }
+
+ const PFS_transaction_stat* read_instr_class_transactions_stats() const
+ {
+ if (! m_has_transactions_stats)
+ return NULL;
+ return m_instr_class_transactions_stats;
+ }
+
+ PFS_transaction_stat* write_instr_class_transactions_stats()
+ {
+ if (! m_has_transactions_stats)
+ {
+ reset_transactions_stats();
+ m_has_transactions_stats= true;
+ }
+ return m_instr_class_transactions_stats;
+ }
+
+ void set_instr_class_memory_stats(PFS_memory_stat *array)
+ {
+ m_has_memory_stats= false;
+ m_instr_class_memory_stats= array;
+ }
+
+ const PFS_memory_stat* read_instr_class_memory_stats() const
+ {
+ if (! m_has_memory_stats)
+ return NULL;
+ return m_instr_class_memory_stats;
+ }
+
+ PFS_memory_stat* write_instr_class_memory_stats()
+ {
+ if (! m_has_memory_stats)
+ {
+ rebase_memory_stats();
+ m_has_memory_stats= true;
+ }
+ return m_instr_class_memory_stats;
+ }
+
+private:
+ bool m_has_waits_stats;
+ bool m_has_stages_stats;
+ bool m_has_statements_stats;
+ bool m_has_transactions_stats;
+ bool m_has_memory_stats;
/**
Per connection slice waits aggregated statistics.
@@ -103,6 +223,37 @@ struct PFS_connection_slice
Immutable, safe to use without internal lock.
*/
PFS_statement_stat *m_instr_class_statements_stats;
+
+ /**
+ Per connection slice transactions aggregated statistics.
+ This member holds the data for the table
+ PERFORMANCE_SCHEMA.EVENTS_TRANSACTIONS_SUMMARY_BY_*_BY_EVENT_NAME.
+ Immutable, safe to use without internal lock.
+ */
+ PFS_transaction_stat *m_instr_class_transactions_stats;
+
+ /**
+ Per connection slice memory aggregated statistics.
+ This member holds the data for the table
+ PERFORMANCE_SCHEMA.MEMORY_SUMMARY_BY_*_BY_EVENT_NAME.
+ Immutable, safe to use without internal lock.
+ */
+ PFS_memory_stat *m_instr_class_memory_stats;
+
+public:
+
+ void aggregate_status_stats(const STATUS_VAR *status_vars)
+ {
+ m_status_stats.aggregate_from(status_vars);
+ }
+
+ /**
+ Aggregated status variables.
+ */
+ PFS_status_stats m_status_stats;
+
+ /** Container page. */
+ PFS_opaque_container_page *m_page;
};
/** @} */
diff --git a/storage/perfschema/pfs_defaults.cc b/storage/perfschema/pfs_defaults.cc
index f6183349884..0b615773089 100644
--- a/storage/perfschema/pfs_defaults.cc
+++ b/storage/perfschema/pfs_defaults.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -28,12 +28,15 @@
#include <my_global.h>
#include "pfs.h"
#include "pfs_defaults.h"
+#include "pfs_instr_class.h"
#include "pfs_instr.h"
#include "pfs_setup_actor.h"
#include "pfs_setup_object.h"
-static PSI_thread_key key;
-static PSI_thread_info info= { &key, "setup", PSI_FLAG_GLOBAL };
+static PSI_thread_key thread_key;
+static PSI_thread_info thread_info= { &thread_key, "setup", PSI_FLAG_GLOBAL };
+
+const char* pfs_category= "performance_schema";
void install_default_setup(PSI_bootstrap *boot)
{
@@ -41,30 +44,62 @@ void install_default_setup(PSI_bootstrap *boot)
if (psi == NULL)
return;
- psi->register_thread("performance_schema", &info, 1);
- PSI_thread *psi_thread= psi->new_thread(key, NULL, 0);
- if (psi_thread == NULL)
- return;
-
- /* LF_HASH needs a thread, for PINS */
- psi->set_thread(psi_thread);
-
- String percent("%", 1, &my_charset_utf8mb3_bin);
- /* Enable all users on all hosts by default */
- insert_setup_actor(&percent, &percent, &percent);
-
- /* Disable system tables by default */
- String mysql_db("mysql", 5, &my_charset_utf8mb3_bin);
- insert_setup_object(OBJECT_TYPE_TABLE, &mysql_db, &percent, false, false);
-
- /* Disable performance/information schema tables. */
- String PS_db("performance_schema", 18, &my_charset_utf8mb3_bin);
- String IS_db("information_schema", 18, &my_charset_utf8mb3_bin);
- insert_setup_object(OBJECT_TYPE_TABLE, &PS_db, &percent, false, false);
- insert_setup_object(OBJECT_TYPE_TABLE, &IS_db, &percent, false, false);
-
- /* Enable every other tables */
- insert_setup_object(OBJECT_TYPE_TABLE, &percent, &percent, true, true);
+ psi->register_thread(pfs_category, &thread_info, 1);
+ PSI_thread *psi_thread= psi->new_thread(thread_key, NULL, 0);
+
+ if (psi_thread != NULL)
+ {
+ /* LF_HASH needs a thread, for PINS */
+ psi->set_thread(psi_thread);
+
+ String percent("%", 1, &my_charset_utf8mb3_bin);
+ /* Enable all users on all hosts by default */
+ insert_setup_actor(&percent, &percent, &percent, true, true);
+
+ String mysql_db("mysql", 5, &my_charset_utf8mb3_bin);
+ String PS_db("performance_schema", 18, &my_charset_utf8mb3_bin);
+ String IS_db("information_schema", 18, &my_charset_utf8mb3_bin);
+
+ /* Disable sp by default in mysql. */
+ insert_setup_object(OBJECT_TYPE_EVENT, &mysql_db, &percent, false, false);
+ /* Disable sp in performance/information schema. */
+ insert_setup_object(OBJECT_TYPE_EVENT, &PS_db, &percent, false, false);
+ insert_setup_object(OBJECT_TYPE_EVENT, &IS_db, &percent, false, false);
+ /* Enable every other sp. */
+ insert_setup_object(OBJECT_TYPE_EVENT, &percent, &percent, true, true);
+
+ /* Disable sp by default in mysql. */
+ insert_setup_object(OBJECT_TYPE_FUNCTION, &mysql_db, &percent, false, false);
+ /* Disable sp in performance/information schema. */
+ insert_setup_object(OBJECT_TYPE_FUNCTION, &PS_db, &percent, false, false);
+ insert_setup_object(OBJECT_TYPE_FUNCTION, &IS_db, &percent, false, false);
+ /* Enable every other sp. */
+ insert_setup_object(OBJECT_TYPE_FUNCTION, &percent, &percent, true, true);
+
+ /* Disable sp by default in mysql. */
+ insert_setup_object(OBJECT_TYPE_PROCEDURE, &mysql_db, &percent, false, false);
+ /* Disable sp in performance/information schema. */
+ insert_setup_object(OBJECT_TYPE_PROCEDURE, &PS_db, &percent, false, false);
+ insert_setup_object(OBJECT_TYPE_PROCEDURE, &IS_db, &percent, false, false);
+ /* Enable every other sp. */
+ insert_setup_object(OBJECT_TYPE_PROCEDURE, &percent, &percent, true, true);
+
+ /* Disable system tables by default */
+ insert_setup_object(OBJECT_TYPE_TABLE, &mysql_db, &percent, false, false);
+ /* Disable performance/information schema tables. */
+ insert_setup_object(OBJECT_TYPE_TABLE, &PS_db, &percent, false, false);
+ insert_setup_object(OBJECT_TYPE_TABLE, &IS_db, &percent, false, false);
+ /* Enable every other tables */
+ insert_setup_object(OBJECT_TYPE_TABLE, &percent, &percent, true, true);
+
+ /* Disable sp by default in mysql. */
+ insert_setup_object(OBJECT_TYPE_TRIGGER, &mysql_db, &percent, false, false);
+ /* Disable sp in performance/information schema. */
+ insert_setup_object(OBJECT_TYPE_TRIGGER, &PS_db, &percent, false, false);
+ insert_setup_object(OBJECT_TYPE_TRIGGER, &IS_db, &percent, false, false);
+ /* Enable every other sp. */
+ insert_setup_object(OBJECT_TYPE_TRIGGER, &percent, &percent, true, true);
+ }
psi->delete_current_thread();
}
diff --git a/storage/perfschema/pfs_digest.cc b/storage/perfschema/pfs_digest.cc
index 0ddb4c90eb3..6f0b93f9393 100644
--- a/storage/perfschema/pfs_digest.cc
+++ b/storage/perfschema/pfs_digest.cc
@@ -36,8 +36,10 @@
#include "pfs_instr.h"
#include "pfs_digest.h"
#include "pfs_global.h"
+#include "pfs_builtin_memory.h"
#include "table_helper.h"
#include "sql_lex.h"
+#include "sql_signal.h"
#include "sql_get_diagnostics.h"
#include "sql_string.h"
#include <string.h>
@@ -54,7 +56,8 @@ bool flag_statements_digest= true;
Current index in Stat array where new record is to be inserted.
index 0 is reserved for "all else" case when entire array is full.
*/
-volatile uint32 PFS_ALIGNED digest_monotonic_index;
+static PFS_ALIGNED PFS_cacheline_uint32 digest_monotonic_index;
+
bool digest_full= false;
LF_HASH digest_hash;
@@ -72,16 +75,16 @@ int init_digest(const PFS_global_param *param)
*/
digest_max= param->m_digest_sizing;
digest_lost= 0;
- PFS_atomic::store_u32(& digest_monotonic_index, 1);
+ PFS_atomic::store_u32(& digest_monotonic_index.m_u32, 1);
digest_full= false;
if (digest_max == 0)
return 0;
statements_digest_stat_array=
- PFS_MALLOC_ARRAY(digest_max,
- sizeof(PFS_statements_digest_stat),
- PFS_statements_digest_stat,
+ PFS_MALLOC_ARRAY(& builtin_memory_digest,
+ digest_max,
+ sizeof(PFS_statements_digest_stat), PFS_statements_digest_stat,
MYF(MY_ZEROFILL));
if (unlikely(statements_digest_stat_array == NULL))
@@ -96,7 +99,8 @@ int init_digest(const PFS_global_param *param)
size_t digest_memory_size= pfs_max_digest_length * sizeof(unsigned char);
statements_digest_token_array=
- PFS_MALLOC_ARRAY(digest_max,
+ PFS_MALLOC_ARRAY(& builtin_memory_digest_tokens,
+ digest_max,
digest_memory_size,
unsigned char,
MYF(MY_ZEROFILL));
@@ -117,15 +121,25 @@ int init_digest(const PFS_global_param *param)
/* Set record[0] as allocated. */
statements_digest_stat_array[0].m_lock.set_allocated();
+ /* Set record[0] as allocated. */
+ statements_digest_stat_array[0].m_lock.set_allocated();
+
return 0;
}
/** Cleanup table EVENTS_STATEMENTS_SUMMARY_BY_DIGEST. */
void cleanup_digest(void)
{
- /* Free memory allocated to statements_digest_stat_array. */
- pfs_free(statements_digest_stat_array);
- pfs_free(statements_digest_token_array);
+ PFS_FREE_ARRAY(& builtin_memory_digest,
+ digest_max,
+ sizeof(PFS_statements_digest_stat),
+ statements_digest_stat_array);
+
+ PFS_FREE_ARRAY(& builtin_memory_digest_tokens,
+ digest_max,
+ (pfs_max_digest_length * sizeof(unsigned char)),
+ statements_digest_token_array);
+
statements_digest_stat_array= NULL;
statements_digest_token_array= NULL;
}
@@ -152,14 +166,13 @@ C_MODE_END
Initialize the digest hash.
@return 0 on success
*/
-int init_digest_hash(void)
+int init_digest_hash(const PFS_global_param *param)
{
- if ((! digest_hash_inited) && (digest_max > 0))
+ if ((! digest_hash_inited) && (param->m_digest_sizing != 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;
@@ -225,6 +238,7 @@ find_or_create_digest(PFS_thread *thread,
size_t attempts= 0;
PFS_statements_digest_stat **entry;
PFS_statements_digest_stat *pfs= NULL;
+ pfs_dirty_state dirty_state;
ulonglong now= my_hrtime().val;
@@ -248,7 +262,7 @@ search:
if (digest_full)
{
- /* digest_stat array is full. Add stat at index 0 and return. */
+ /* digest_stat array is full. Add stat at index 0 and return. */
pfs= &statements_digest_stat_array[0];
digest_lost++;
@@ -260,7 +274,7 @@ search:
while (++attempts <= digest_max)
{
- safe_index= PFS_atomic::add_u32(& digest_monotonic_index, 1) % digest_max;
+ safe_index= PFS_atomic::add_u32(& digest_monotonic_index.m_u32, 1) % digest_max;
if (safe_index == 0)
{
/* Record [0] is reserved. */
@@ -273,7 +287,7 @@ search:
if (pfs->m_lock.is_free())
{
- if (pfs->m_lock.free_to_dirty())
+ if (pfs->m_lock.free_to_dirty(& dirty_state))
{
/* Copy digest hash/LF Hash search key. */
memcpy(& pfs->m_digest_key, &hash_key, sizeof(PFS_digest_key));
@@ -290,11 +304,11 @@ search:
res= lf_hash_insert(&digest_hash, pins, &pfs);
if (likely(res == 0))
{
- pfs->m_lock.dirty_to_allocated();
+ pfs->m_lock.dirty_to_allocated(& dirty_state);
return & pfs->m_stat;
}
- pfs->m_lock.dirty_to_free();
+ pfs->m_lock.dirty_to_free(& dirty_state);
if (res > 0)
{
@@ -349,12 +363,13 @@ void purge_digest(PFS_thread* thread, PFS_digest_key *hash_key)
void PFS_statements_digest_stat::reset_data(unsigned char *token_array, size_t length)
{
- m_lock.set_dirty();
+ pfs_dirty_state dirty_state;
+ m_lock.set_dirty(& dirty_state);
m_digest_storage.reset(token_array, length);
m_stat.reset();
m_first_seen= 0;
m_last_seen= 0;
- m_lock.dirty_to_free();
+ m_lock.dirty_to_free(& dirty_state);
}
void PFS_statements_digest_stat::reset_index(PFS_thread *thread)
@@ -368,6 +383,8 @@ void PFS_statements_digest_stat::reset_index(PFS_thread *thread)
void reset_esms_by_digest()
{
+ uint index;
+
if (statements_digest_stat_array == NULL)
return;
@@ -376,7 +393,7 @@ void reset_esms_by_digest()
return;
/* Reset statements_digest_stat_array. */
- for (size_t index= 0; index < digest_max; index++)
+ for (index= 0; index < digest_max; index++)
{
statements_digest_stat_array[index].reset_index(thread);
statements_digest_stat_array[index].reset_data(statements_digest_token_array + index * pfs_max_digest_length, pfs_max_digest_length);
@@ -389,7 +406,7 @@ void reset_esms_by_digest()
Reset index which indicates where the next calculated digest information
to be inserted in statements_digest_stat_array.
*/
- PFS_atomic::store_u32(& digest_monotonic_index, 1);
+ PFS_atomic::store_u32(& digest_monotonic_index.m_u32, 1);
digest_full= false;
}
diff --git a/storage/perfschema/pfs_digest.h b/storage/perfschema/pfs_digest.h
index c11852a1510..39fe6109c20 100644
--- a/storage/perfschema/pfs_digest.h
+++ b/storage/perfschema/pfs_digest.h
@@ -76,7 +76,7 @@ struct PFS_ALIGNED PFS_statements_digest_stat
int init_digest(const PFS_global_param *param);
void cleanup_digest();
-int init_digest_hash(void);
+int init_digest_hash(const PFS_global_param *param);
void cleanup_digest_hash(void);
PFS_statement_stat* find_or_create_digest(PFS_thread *thread,
const sql_digest_storage *digest_storage,
@@ -91,3 +91,4 @@ extern PFS_statements_digest_stat *statements_digest_stat_array;
extern LF_HASH digest_hash;
#endif
+
diff --git a/storage/perfschema/pfs_engine_table.cc b/storage/perfschema/pfs_engine_table.cc
index 9a18879bc62..98028e38024 100644
--- a/storage/perfschema/pfs_engine_table.cc
+++ b/storage/perfschema/pfs_engine_table.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2019, 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, version 2.0,
@@ -26,9 +26,10 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "hostname.h" /* For Host_entry */
#include "pfs_engine_table.h"
+#include "pfs_buffer_container.h"
#include "table_events_waits.h"
#include "table_setup_actors.h"
@@ -69,6 +70,14 @@
#include "table_esms_by_account_by_event_name.h"
#include "table_esms_global_by_event_name.h"
#include "table_esms_by_digest.h"
+#include "table_esms_by_program.h"
+
+#include "table_events_transactions.h"
+#include "table_ets_by_thread_by_event_name.h"
+#include "table_ets_by_host_by_event_name.h"
+#include "table_ets_by_user_by_event_name.h"
+#include "table_ets_by_account_by_event_name.h"
+#include "table_ets_global_by_event_name.h"
#include "table_users.h"
#include "table_accounts.h"
@@ -79,6 +88,39 @@
#include "table_socket_summary_by_event_name.h"
#include "table_session_connect_attrs.h"
#include "table_session_account_connect_attrs.h"
+#include "table_mems_global_by_event_name.h"
+#include "table_mems_by_account_by_event_name.h"
+#include "table_mems_by_host_by_event_name.h"
+#include "table_mems_by_thread_by_event_name.h"
+#include "table_mems_by_user_by_event_name.h"
+
+/* For replication related perfschema tables. */
+#include "table_replication_connection_configuration.h"
+#include "table_replication_group_members.h"
+#include "table_replication_connection_status.h"
+#include "table_replication_applier_configuration.h"
+#include "table_replication_applier_status.h"
+#include "table_replication_applier_status_by_coordinator.h"
+#include "table_replication_applier_status_by_worker.h"
+#include "table_replication_group_member_stats.h"
+
+#include "table_prepared_stmt_instances.h"
+
+#include "table_md_locks.h"
+#include "table_table_handles.h"
+
+#include "table_uvar_by_thread.h"
+
+#include "table_status_by_account.h"
+#include "table_status_by_host.h"
+#include "table_status_by_thread.h"
+#include "table_status_by_user.h"
+#include "table_global_status.h"
+#include "table_session_status.h"
+
+#include "table_variables_by_thread.h"
+#include "table_global_variables.h"
+#include "table_session_variables.h"
/* For show status */
#include "pfs_column_values.h"
@@ -91,12 +133,105 @@
#include "sql_base.h" // close_thread_tables
#include "lock.h" // MYSQL_LOCK_IGNORE_TIMEOUT
+#include "log.h"
/**
@addtogroup Performance_schema_engine
@{
*/
+bool PFS_table_context::initialize(void)
+{
+ if (m_restore)
+ {
+ /* Restore context from TLS. */
+ PFS_table_context *context= static_cast<PFS_table_context *>(my_get_thread_local(m_thr_key));
+ DBUG_ASSERT(context != NULL);
+
+ if(context)
+ {
+ m_last_version= context->m_current_version;
+ m_map= context->m_map;
+ DBUG_ASSERT(m_map_size == context->m_map_size);
+ m_map_size= context->m_map_size;
+ m_word_size= context->m_word_size;
+ }
+ }
+ else
+ {
+ /* Check that TLS is not in use. */
+ PFS_table_context *context= static_cast<PFS_table_context *>(my_get_thread_local(m_thr_key));
+ //DBUG_ASSERT(context == NULL);
+
+ context= this;
+
+ /* Initialize a new context, store in TLS. */
+ m_last_version= m_current_version;
+ m_map= NULL;
+ m_word_size= sizeof(ulong) * 8;
+
+ /* Allocate a bitmap to record which threads are materialized. */
+ if (m_map_size > 0)
+ {
+ THD *thd= current_thd;
+ ulong words= m_map_size / m_word_size + (m_map_size % m_word_size > 0);
+ m_map= (ulong *)thd->calloc(words * m_word_size);
+ }
+
+ /* Write to TLS. */
+ my_set_thread_local(m_thr_key, static_cast<void *>(context));
+ }
+
+ m_initialized= (m_map_size > 0) ? (m_map != NULL) : true;
+
+ return m_initialized;
+}
+
+/* Constructor for global or single thread tables, map size = 0. */
+PFS_table_context::PFS_table_context(ulonglong current_version, bool restore, thread_local_key_t key) :
+ m_thr_key(key), m_current_version(current_version), m_last_version(0),
+ m_map(NULL), m_map_size(0), m_word_size(sizeof(ulong)),
+ m_restore(restore), m_initialized(false), m_last_item(0)
+{
+ initialize();
+}
+
+/* Constructor for by-thread or aggregate tables, map size = max thread/user/host/account. */
+PFS_table_context::PFS_table_context(ulonglong current_version, ulong map_size, bool restore, thread_local_key_t key) :
+ m_thr_key(key), m_current_version(current_version), m_last_version(0),
+ m_map(NULL), m_map_size(map_size), m_word_size(sizeof(ulong)),
+ m_restore(restore), m_initialized(false), m_last_item(0)
+{
+ initialize();
+}
+
+PFS_table_context::~PFS_table_context(void)
+{
+ /* Clear TLS after final use. */ // TODO: How is that determined?
+// if (m_restore)
+// {
+// my_set_thread_local(m_thr_key, NULL);
+// }
+}
+
+void PFS_table_context::set_item(ulong n)
+{
+ if (n == m_last_item)
+ return;
+ ulong word= n / m_word_size;
+ ulong bit= n % m_word_size;
+ m_map[word] |= (1 << bit);
+ m_last_item= n;
+}
+
+bool PFS_table_context::is_item_set(ulong n)
+{
+ ulong word= n / m_word_size;
+ ulong bit= n % m_word_size;
+ return (m_map[word] & (1 << bit));
+}
+
+
static PFS_engine_table_share *all_shares[]=
{
&table_cond_instances::m_share,
@@ -145,6 +280,16 @@ static PFS_engine_table_share *all_shares[]=
&table_esms_by_host_by_event_name::m_share,
&table_esms_global_by_event_name::m_share,
&table_esms_by_digest::m_share,
+ &table_esms_by_program::m_share,
+
+ &table_events_transactions_current::m_share,
+ &table_events_transactions_history::m_share,
+ &table_events_transactions_history_long::m_share,
+ &table_ets_by_thread_by_event_name::m_share,
+ &table_ets_by_account_by_event_name::m_share,
+ &table_ets_by_user_by_event_name::m_share,
+ &table_ets_by_host_by_event_name::m_share,
+ &table_ets_global_by_event_name::m_share,
&table_users::m_share,
&table_accounts::m_share,
@@ -153,8 +298,41 @@ 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,
+
+ &table_mems_global_by_event_name::m_share,
+ &table_mems_by_account_by_event_name::m_share,
+ &table_mems_by_host_by_event_name::m_share,
+ &table_mems_by_thread_by_event_name::m_share,
+ &table_mems_by_user_by_event_name::m_share,
+ &table_table_handles::m_share,
+ &table_metadata_locks::m_share,
+
+ &table_replication_connection_configuration::m_share,
+ &table_replication_group_members::m_share,
+ &table_replication_connection_status::m_share,
+ &table_replication_applier_configuration::m_share,
+ &table_replication_applier_status::m_share,
+ &table_replication_applier_status_by_coordinator::m_share,
+ &table_replication_applier_status_by_worker::m_share,
+ &table_replication_group_member_stats::m_share,
+
+ &table_prepared_stmt_instances::m_share,
+
+ &table_uvar_by_thread::m_share,
+ &table_status_by_account::m_share,
+ &table_status_by_host::m_share,
+ &table_status_by_thread::m_share,
+ &table_status_by_user::m_share,
+ &table_global_status::m_share,
+ &table_session_status::m_share,
+
+ &table_variables_by_thread::m_share,
+ &table_global_variables::m_share,
+ &table_session_variables::m_share,
+
NULL
};
@@ -178,11 +356,7 @@ void PFS_engine_table_share::delete_all_locks(void)
ha_rows PFS_engine_table_share::get_row_count(void) const
{
- /* If available, count the exact number or records */
- if (m_get_row_count)
- return m_get_row_count();
- /* Otherwise, return an estimate */
- return m_records;
+ return m_get_row_count();
}
int PFS_engine_table_share::write_row(TABLE *table, const unsigned char *buf,
@@ -356,6 +530,13 @@ void PFS_engine_table::get_normalizer(PFS_instr_class *instr_class)
}
}
+void PFS_engine_table::set_field_long(Field *f, long value)
+{
+ DBUG_ASSERT(f->real_type() == MYSQL_TYPE_LONG);
+ Field_long *f2= (Field_long*) f;
+ f2->store(value, false);
+}
+
void PFS_engine_table::set_field_ulong(Field *f, ulong value)
{
DBUG_ASSERT(f->real_type() == MYSQL_TYPE_LONG);
@@ -363,6 +544,13 @@ void PFS_engine_table::set_field_ulong(Field *f, ulong value)
f2->store(value, true);
}
+void PFS_engine_table::set_field_longlong(Field *f, longlong value)
+{
+ DBUG_ASSERT(f->real_type() == MYSQL_TYPE_LONGLONG);
+ Field_longlong *f2= (Field_longlong*) f;
+ f2->store(value, false);
+}
+
void PFS_engine_table::set_field_ulonglong(Field *f, ulonglong value)
{
DBUG_ASSERT(f->real_type() == MYSQL_TYPE_LONGLONG);
@@ -378,6 +566,16 @@ void PFS_engine_table::set_field_char_utf8(Field *f, const char* str,
f2->store(str, len, &my_charset_utf8mb3_bin);
}
+void PFS_engine_table::set_field_varchar(Field *f,
+ const CHARSET_INFO *cs,
+ const char* str,
+ uint len)
+{
+ DBUG_ASSERT(f->real_type() == MYSQL_TYPE_VARCHAR);
+ Field_varstring *f2= (Field_varstring*) f;
+ f2->store(str, len, cs);
+}
+
void PFS_engine_table::set_field_varchar_utf8(Field *f, const char* str,
uint len)
{
@@ -394,6 +592,14 @@ void PFS_engine_table::set_field_longtext_utf8(Field *f, const char* str,
f2->store(str, len, &my_charset_utf8mb3_bin);
}
+void PFS_engine_table::set_field_blob(Field *f, const char* val,
+ uint len)
+{
+ DBUG_ASSERT(f->real_type() == MYSQL_TYPE_BLOB);
+ Field_blob *f2= (Field_blob*) f;
+ f2->store(val, len, &my_charset_utf8_bin);
+}
+
void PFS_engine_table::set_field_enum(Field *f, ulonglong value)
{
DBUG_ASSERT(f->real_type() == MYSQL_TYPE_ENUM);
@@ -408,6 +614,13 @@ void PFS_engine_table::set_field_timestamp(Field *f, ulonglong value)
f2->store_TIME((long)(value / 1000000), (value % 1000000));
}
+void PFS_engine_table::set_field_double(Field *f, double value)
+{
+ DBUG_ASSERT(f->real_type() == MYSQL_TYPE_DOUBLE);
+ Field_double *f2= (Field_double*) f;
+ f2->store(value);
+}
+
ulonglong PFS_engine_table::get_field_enum(Field *f)
{
DBUG_ASSERT(f->real_type() == MYSQL_TYPE_ENUM);
@@ -508,6 +721,31 @@ void initialize_performance_schema_acl(bool bootstrap)
}
}
+static bool allow_drop_table_privilege() {
+ /*
+ The same DROP_ACL privilege is used for different statements,
+ in particular:
+ - TRUNCATE TABLE
+ - DROP TABLE
+ - ALTER TABLE
+ Here, we want to prevent DROP / ALTER while allowing TRUNCATE.
+ Note that we must also allow GRANT to transfer the truncate privilege.
+ */
+ THD *thd= current_thd;
+ if (thd == NULL) {
+ return false;
+ }
+
+ DBUG_ASSERT(thd->lex != NULL);
+ if ((thd->lex->sql_command != SQLCOM_TRUNCATE) &&
+ (thd->lex->sql_command != SQLCOM_GRANT)) {
+ return false;
+ }
+
+ return true;
+}
+
+
PFS_readonly_acl pfs_readonly_acl;
ACL_internal_access_result
@@ -523,6 +761,22 @@ PFS_readonly_acl::check(privilege_t want_access, privilege_t *save_priv) const
return ACL_INTERNAL_ACCESS_CHECK_GRANT;
}
+
+PFS_readonly_world_acl pfs_readonly_world_acl;
+
+ACL_internal_access_result
+PFS_readonly_world_acl::check(ulong want_access, ulong *save_priv) const
+{
+ ACL_internal_access_result res= PFS_readonly_acl::check(want_access, save_priv);
+ if (res == ACL_INTERNAL_ACCESS_CHECK_GRANT)
+ {
+ if (want_access == SELECT_ACL)
+ res= ACL_INTERNAL_ACCESS_GRANTED;
+ }
+ return res;
+}
+
+
PFS_truncatable_acl pfs_truncatable_acl;
ACL_internal_access_result
@@ -538,6 +792,27 @@ PFS_truncatable_acl::check(privilege_t want_access, privilege_t *save_priv) cons
return ACL_INTERNAL_ACCESS_CHECK_GRANT;
}
+
+PFS_truncatable_world_acl pfs_truncatable_world_acl;
+
+ACL_internal_access_result
+PFS_truncatable_world_acl::check(ulong want_access, ulong *save_priv) const
+{
+ ACL_internal_access_result res= PFS_truncatable_acl::check(want_access, save_priv);
+ if (res == ACL_INTERNAL_ACCESS_CHECK_GRANT)
+ {
+ if (want_access == DROP_ACL)
+ {
+ if (allow_drop_table_privilege())
+ res= ACL_INTERNAL_ACCESS_GRANTED;
+ }
+ else if (want_access == SELECT_ACL)
+ res= ACL_INTERNAL_ACCESS_GRANTED;
+ }
+ return res;
+}
+
+
PFS_updatable_acl pfs_updatable_acl;
ACL_internal_access_result
@@ -626,33 +901,33 @@ bool pfs_show_status(handlerton *hton, THD *thd,
{
switch (i){
case 0:
- name= "events_waits_current.row_size";
+ name= "events_waits_current.size";
size= sizeof(PFS_events_waits);
break;
case 1:
- name= "events_waits_current.row_count";
- size= WAIT_STACK_SIZE * thread_max;
+ name= "events_waits_current.count";
+ size= WAIT_STACK_SIZE * global_thread_container.get_row_count();
break;
case 2:
- name= "events_waits_history.row_size";
+ name= "events_waits_history.size";
size= sizeof(PFS_events_waits);
break;
case 3:
- name= "events_waits_history.row_count";
- size= events_waits_history_per_thread * thread_max;
+ name= "events_waits_history.count";
+ size= events_waits_history_per_thread * global_thread_container.get_row_count();
break;
case 4:
name= "events_waits_history.memory";
- size= events_waits_history_per_thread * thread_max
+ size= events_waits_history_per_thread * global_thread_container.get_row_count()
* sizeof(PFS_events_waits);
total_memory+= size;
break;
case 5:
- name= "events_waits_history_long.row_size";
+ name= "events_waits_history_long.size";
size= sizeof(PFS_events_waits);
break;
case 6:
- name= "events_waits_history_long.row_count";
+ name= "events_waits_history_long.count";
size= events_waits_history_long_size;
break;
case 7:
@@ -661,11 +936,11 @@ bool pfs_show_status(handlerton *hton, THD *thd,
total_memory+= size;
break;
case 8:
- name= "(pfs_mutex_class).row_size";
+ name= "(pfs_mutex_class).size";
size= sizeof(PFS_mutex_class);
break;
case 9:
- name= "(pfs_mutex_class).row_count";
+ name= "(pfs_mutex_class).count";
size= mutex_class_max;
break;
case 10:
@@ -674,11 +949,11 @@ bool pfs_show_status(handlerton *hton, THD *thd,
total_memory+= size;
break;
case 11:
- name= "(pfs_rwlock_class).row_size";
+ name= "(pfs_rwlock_class).size";
size= sizeof(PFS_rwlock_class);
break;
case 12:
- name= "(pfs_rwlock_class).row_count";
+ name= "(pfs_rwlock_class).count";
size= rwlock_class_max;
break;
case 13:
@@ -687,11 +962,11 @@ bool pfs_show_status(handlerton *hton, THD *thd,
total_memory+= size;
break;
case 14:
- name= "(pfs_cond_class).row_size";
+ name= "(pfs_cond_class).size";
size= sizeof(PFS_cond_class);
break;
case 15:
- name= "(pfs_cond_class).row_count";
+ name= "(pfs_cond_class).count";
size= cond_class_max;
break;
case 16:
@@ -700,11 +975,11 @@ bool pfs_show_status(handlerton *hton, THD *thd,
total_memory+= size;
break;
case 17:
- name= "(pfs_thread_class).row_size";
+ name= "(pfs_thread_class).size";
size= sizeof(PFS_thread_class);
break;
case 18:
- name= "(pfs_thread_class).row_count";
+ name= "(pfs_thread_class).count";
size= thread_class_max;
break;
case 19:
@@ -713,11 +988,11 @@ bool pfs_show_status(handlerton *hton, THD *thd,
total_memory+= size;
break;
case 20:
- name= "(pfs_file_class).row_size";
+ name= "(pfs_file_class).size";
size= sizeof(PFS_file_class);
break;
case 21:
- name= "(pfs_file_class).row_count";
+ name= "(pfs_file_class).count";
size= file_class_max;
break;
case 22:
@@ -726,76 +1001,76 @@ bool pfs_show_status(handlerton *hton, THD *thd,
total_memory+= size;
break;
case 23:
- name= "mutex_instances.row_size";
- size= sizeof(PFS_mutex);
+ name= "mutex_instances.size";
+ size= global_mutex_container.get_row_size();
break;
case 24:
- name= "mutex_instances.row_count";
- size= mutex_max;
+ name= "mutex_instances.count";
+ size= global_mutex_container.get_row_count();
break;
case 25:
name= "mutex_instances.memory";
- size= mutex_max * sizeof(PFS_mutex);
+ size= global_mutex_container.get_memory();
total_memory+= size;
break;
case 26:
- name= "rwlock_instances.row_size";
- size= sizeof(PFS_rwlock);
+ name= "rwlock_instances.size";
+ size= global_rwlock_container.get_row_size();
break;
case 27:
- name= "rwlock_instances.row_count";
- size= rwlock_max;
+ name= "rwlock_instances.count";
+ size= global_rwlock_container.get_row_count();
break;
case 28:
name= "rwlock_instances.memory";
- size= rwlock_max * sizeof(PFS_rwlock);
+ size= global_rwlock_container.get_memory();
total_memory+= size;
break;
case 29:
- name= "cond_instances.row_size";
- size= sizeof(PFS_cond);
+ name= "cond_instances.size";
+ size= global_cond_container.get_row_size();
break;
case 30:
- name= "cond_instances.row_count";
- size= cond_max;
+ name= "cond_instances.count";
+ size= global_cond_container.get_row_count();
break;
case 31:
name= "cond_instances.memory";
- size= cond_max * sizeof(PFS_cond);
+ size= global_cond_container.get_memory();
total_memory+= size;
break;
case 32:
- name= "threads.row_size";
- size= sizeof(PFS_thread);
+ name= "threads.size";
+ size= global_thread_container.get_row_size();
break;
case 33:
- name= "threads.row_count";
- size= thread_max;
+ name= "threads.count";
+ size= global_thread_container.get_row_count();
break;
case 34:
name= "threads.memory";
- size= thread_max * sizeof(PFS_thread);
+ size= global_thread_container.get_memory();
total_memory+= size;
break;
case 35:
- name= "file_instances.row_size";
- size= sizeof(PFS_file);
+ name= "file_instances.size";
+ size= global_file_container.get_row_size();
break;
case 36:
- name= "file_instances.row_count";
- size= file_max;
+ name= "file_instances.count";
+ size= global_file_container.get_row_count();
break;
case 37:
name= "file_instances.memory";
- size= file_max * sizeof(PFS_file);
+ size= global_file_container.get_memory();
total_memory+= size;
break;
case 38:
- name= "(pfs_file_handle).row_size";
+ name= "(pfs_file_handle).size";
size= sizeof(PFS_file*);
break;
case 39:
- name= "(pfs_file_handle).row_count";
+ name= "(pfs_file_handle).count";
size= file_handle_max;
break;
case 40:
@@ -804,154 +1079,154 @@ bool pfs_show_status(handlerton *hton, THD *thd,
total_memory+= size;
break;
case 41:
- name= "events_waits_summary_by_thread_by_event_name.row_size";
+ name= "events_waits_summary_by_thread_by_event_name.size";
size= sizeof(PFS_single_stat);
break;
case 42:
- name= "events_waits_summary_by_thread_by_event_name.row_count";
- size= thread_max * wait_class_max;
+ name= "events_waits_summary_by_thread_by_event_name.count";
+ size= global_thread_container.get_row_count() * wait_class_max;
break;
case 43:
name= "events_waits_summary_by_thread_by_event_name.memory";
- size= thread_max * wait_class_max * sizeof(PFS_single_stat);
+ size= global_thread_container.get_row_count() * wait_class_max * sizeof(PFS_single_stat);
total_memory+= size;
break;
case 44:
- name= "(pfs_table_share).row_size";
- size= sizeof(PFS_table_share);
+ name= "(pfs_table_share).size";
+ size= global_table_share_container.get_row_size();
break;
case 45:
- name= "(pfs_table_share).row_count";
- size= table_share_max;
+ name= "(pfs_table_share).count";
+ size= global_table_share_container.get_row_count();
break;
case 46:
name= "(pfs_table_share).memory";
- size= table_share_max * sizeof(PFS_table_share);
+ size= global_table_share_container.get_memory();
total_memory+= size;
break;
case 47:
- name= "(pfs_table).row_size";
- size= sizeof(PFS_table);
+ name= "(pfs_table).size";
+ size= global_table_container.get_row_size();
break;
case 48:
- name= "(pfs_table).row_count";
- size= table_max;
+ name= "(pfs_table).count";
+ size= global_table_container.get_row_count();
break;
case 49:
name= "(pfs_table).memory";
- size= table_max * sizeof(PFS_table);
+ size= global_table_container.get_memory();
total_memory+= size;
break;
case 50:
- name= "setup_actors.row_size";
- size= sizeof(PFS_setup_actor);
+ name= "setup_actors.size";
+ size= global_setup_actor_container.get_row_size();
break;
case 51:
- name= "setup_actors.row_count";
- size= setup_actor_max;
+ name= "setup_actors.count";
+ size= global_setup_actor_container.get_row_count();
break;
case 52:
name= "setup_actors.memory";
- size= setup_actor_max * sizeof(PFS_setup_actor);
+ size= global_setup_actor_container.get_memory();
total_memory+= size;
break;
case 53:
- name= "setup_objects.row_size";
- size= sizeof(PFS_setup_object);
+ name= "setup_objects.size";
+ size= global_setup_object_container.get_row_size();
break;
case 54:
- name= "setup_objects.row_count";
- size= setup_object_max;
+ name= "setup_objects.count";
+ size= global_setup_object_container.get_row_count();
break;
case 55:
name= "setup_objects.memory";
- size= setup_object_max * sizeof(PFS_setup_object);
+ size= global_setup_object_container.get_memory();
total_memory+= size;
break;
case 56:
- name= "(pfs_account).row_size";
- size= sizeof(PFS_account);
+ name= "(pfs_account).size";
+ size= global_account_container.get_row_size();
break;
case 57:
- name= "(pfs_account).row_count";
- size= account_max;
+ name= "(pfs_account).count";
+ size= global_account_container.get_row_count();
break;
case 58:
name= "(pfs_account).memory";
- size= account_max * sizeof(PFS_account);
+ size= global_account_container.get_memory();
total_memory+= size;
break;
case 59:
- name= "events_waits_summary_by_account_by_event_name.row_size";
+ name= "events_waits_summary_by_account_by_event_name.size";
size= sizeof(PFS_single_stat);
break;
case 60:
- name= "events_waits_summary_by_account_by_event_name.row_count";
- size= account_max * wait_class_max;
+ name= "events_waits_summary_by_account_by_event_name.count";
+ size= global_account_container.get_row_count() * wait_class_max;
break;
case 61:
name= "events_waits_summary_by_account_by_event_name.memory";
- size= account_max * wait_class_max * sizeof(PFS_single_stat);
+ size= global_account_container.get_row_count() * wait_class_max * sizeof(PFS_single_stat);
total_memory+= size;
break;
case 62:
- name= "events_waits_summary_by_user_by_event_name.row_size";
+ name= "events_waits_summary_by_user_by_event_name.size";
size= sizeof(PFS_single_stat);
break;
case 63:
- name= "events_waits_summary_by_user_by_event_name.row_count";
- size= user_max * wait_class_max;
+ name= "events_waits_summary_by_user_by_event_name.count";
+ size= global_user_container.get_row_count() * wait_class_max;
break;
case 64:
name= "events_waits_summary_by_user_by_event_name.memory";
- size= user_max * wait_class_max * sizeof(PFS_single_stat);
+ size= global_user_container.get_row_count() * wait_class_max * sizeof(PFS_single_stat);
total_memory+= size;
break;
case 65:
- name= "events_waits_summary_by_host_by_event_name.row_size";
+ name= "events_waits_summary_by_host_by_event_name.size";
size= sizeof(PFS_single_stat);
break;
case 66:
- name= "events_waits_summary_by_host_by_event_name.row_count";
- size= host_max * wait_class_max;
+ name= "events_waits_summary_by_host_by_event_name.count";
+ size= global_host_container.get_row_count() * wait_class_max;
break;
case 67:
name= "events_waits_summary_by_host_by_event_name.memory";
- size= host_max * wait_class_max * sizeof(PFS_single_stat);
+ size= global_host_container.get_row_count() * wait_class_max * sizeof(PFS_single_stat);
total_memory+= size;
break;
case 68:
- name= "(pfs_user).row_size";
- size= sizeof(PFS_user);
+ name= "(pfs_user).size";
+ size= global_user_container.get_row_size();
break;
case 69:
- name= "(pfs_user).row_count";
- size= user_max;
+ name= "(pfs_user).count";
+ size= global_user_container.get_row_count();
break;
case 70:
name= "(pfs_user).memory";
- size= user_max * sizeof(PFS_user);
+ size= global_user_container.get_memory();
total_memory+= size;
break;
case 71:
- name= "(pfs_host).row_size";
- size= sizeof(PFS_host);
+ name= "(pfs_host).size";
+ size= global_host_container.get_row_size();
break;
case 72:
- name= "(pfs_host).row_count";
- size= host_max;
+ name= "(pfs_host).count";
+ size= global_host_container.get_row_count();
break;
case 73:
name= "(pfs_host).memory";
- size= host_max * sizeof(PFS_host);
+ size= global_host_container.get_memory();
total_memory+= size;
break;
case 74:
- name= "(pfs_stage_class).row_size";
+ name= "(pfs_stage_class).size";
size= sizeof(PFS_stage_class);
break;
case 75:
- name= "(pfs_stage_class).row_count";
+ name= "(pfs_stage_class).count";
size= stage_class_max;
break;
case 76:
@@ -960,25 +1235,25 @@ bool pfs_show_status(handlerton *hton, THD *thd,
total_memory+= size;
break;
case 77:
- name= "events_stages_history.row_size";
+ name= "events_stages_history.size";
size= sizeof(PFS_events_stages);
break;
case 78:
- name= "events_stages_history.row_count";
- size= events_stages_history_per_thread * thread_max;
+ name= "events_stages_history.count";
+ size= events_stages_history_per_thread * global_thread_container.get_row_count();
break;
case 79:
name= "events_stages_history.memory";
- size= events_stages_history_per_thread * thread_max
+ size= events_stages_history_per_thread * global_thread_container.get_row_count()
* sizeof(PFS_events_stages);
total_memory+= size;
break;
case 80:
- name= "events_stages_history_long.row_size";
+ name= "events_stages_history_long.size";
size= sizeof(PFS_events_stages);
break;
case 81:
- name= "events_stages_history_long.row_count";
+ name= "events_stages_history_long.count";
size= events_stages_history_long_size;
break;
case 82:
@@ -987,24 +1262,24 @@ bool pfs_show_status(handlerton *hton, THD *thd,
total_memory+= size;
break;
case 83:
- name= "events_stages_summary_by_thread_by_event_name.row_size";
+ name= "events_stages_summary_by_thread_by_event_name.size";
size= sizeof(PFS_stage_stat);
break;
case 84:
- name= "events_stages_summary_by_thread_by_event_name.row_count";
- size= thread_max * stage_class_max;
+ name= "events_stages_summary_by_thread_by_event_name.count";
+ size= global_thread_container.get_row_count() * stage_class_max;
break;
case 85:
name= "events_stages_summary_by_thread_by_event_name.memory";
- size= thread_max * stage_class_max * sizeof(PFS_stage_stat);
+ size= global_thread_container.get_row_count() * stage_class_max * sizeof(PFS_stage_stat);
total_memory+= size;
break;
case 86:
- name= "events_stages_summary_global_by_event_name.row_size";
+ name= "events_stages_summary_global_by_event_name.size";
size= sizeof(PFS_stage_stat);
break;
case 87:
- name= "events_stages_summary_global_by_event_name.row_count";
+ name= "events_stages_summary_global_by_event_name.count";
size= stage_class_max;
break;
case 88:
@@ -1013,50 +1288,50 @@ bool pfs_show_status(handlerton *hton, THD *thd,
total_memory+= size;
break;
case 89:
- name= "events_stages_summary_by_account_by_event_name.row_size";
+ name= "events_stages_summary_by_account_by_event_name.size";
size= sizeof(PFS_stage_stat);
break;
case 90:
- name= "events_stages_summary_by_account_by_event_name.row_count";
- size= account_max * stage_class_max;
+ name= "events_stages_summary_by_account_by_event_name.count";
+ size= global_account_container.get_row_count() * stage_class_max;
break;
case 91:
name= "events_stages_summary_by_account_by_event_name.memory";
- size= account_max * stage_class_max * sizeof(PFS_stage_stat);
+ size= global_account_container.get_row_count() * stage_class_max * sizeof(PFS_stage_stat);
total_memory+= size;
break;
case 92:
- name= "events_stages_summary_by_user_by_event_name.row_size";
+ name= "events_stages_summary_by_user_by_event_name.size";
size= sizeof(PFS_stage_stat);
break;
case 93:
- name= "events_stages_summary_by_user_by_event_name.row_count";
- size= user_max * stage_class_max;
+ name= "events_stages_summary_by_user_by_event_name.count";
+ size= global_user_container.get_row_count() * stage_class_max;
break;
case 94:
name= "events_stages_summary_by_user_by_event_name.memory";
- size= user_max * stage_class_max * sizeof(PFS_stage_stat);
+ size= global_user_container.get_row_count() * stage_class_max * sizeof(PFS_stage_stat);
total_memory+= size;
break;
case 95:
- name= "events_stages_summary_by_host_by_event_name.row_size";
+ name= "events_stages_summary_by_host_by_event_name.size";
size= sizeof(PFS_stage_stat);
break;
case 96:
- name= "events_stages_summary_by_host_by_event_name.row_count";
- size= host_max * stage_class_max;
+ name= "events_stages_summary_by_host_by_event_name.count";
+ size= global_host_container.get_row_count() * stage_class_max;
break;
case 97:
name= "events_stages_summary_by_host_by_event_name.memory";
- size= host_max * stage_class_max * sizeof(PFS_stage_stat);
+ size= global_host_container.get_row_count() * stage_class_max * sizeof(PFS_stage_stat);
total_memory+= size;
break;
case 98:
- name= "(pfs_statement_class).row_size";
+ name= "(pfs_statement_class).size";
size= sizeof(PFS_statement_class);
break;
case 99:
- name= "(pfs_statement_class).row_count";
+ name= "(pfs_statement_class).count";
size= statement_class_max;
break;
case 100:
@@ -1065,51 +1340,51 @@ bool pfs_show_status(handlerton *hton, THD *thd,
total_memory+= size;
break;
case 101:
- name= "events_statements_history.row_size";
+ name= "events_statements_history.size";
size= sizeof(PFS_events_statements);
break;
case 102:
- name= "events_statements_history.row_count";
- size= events_statements_history_per_thread * thread_max;
+ name= "events_statements_history.count";
+ size= events_statements_history_per_thread * global_thread_container.get_row_count();
break;
case 103:
name= "events_statements_history.memory";
- size= events_statements_history_per_thread * thread_max
+ size= events_statements_history_per_thread * global_thread_container.get_row_count()
* sizeof(PFS_events_statements);
total_memory+= size;
break;
case 104:
- name= "events_statements_history_long.row_size";
+ name= "events_statements_history_long.size";
size= sizeof(PFS_events_statements);
break;
case 105:
- name= "events_statements_history_long.row_count";
+ name= "events_statements_history_long.count";
size= events_statements_history_long_size;
break;
case 106:
name= "events_statements_history_long.memory";
- size= events_statements_history_long_size * sizeof(PFS_events_statements);
+ size= events_statements_history_long_size * (sizeof(PFS_events_statements));
total_memory+= size;
break;
case 107:
- name= "events_statements_summary_by_thread_by_event_name.row_size";
+ name= "events_statements_summary_by_thread_by_event_name.size";
size= sizeof(PFS_statement_stat);
break;
case 108:
- name= "events_statements_summary_by_thread_by_event_name.row_count";
- size= thread_max * statement_class_max;
+ name= "events_statements_summary_by_thread_by_event_name.count";
+ size= global_thread_container.get_row_count() * statement_class_max;
break;
case 109:
name= "events_statements_summary_by_thread_by_event_name.memory";
- size= thread_max * statement_class_max * sizeof(PFS_statement_stat);
+ size= global_thread_container.get_row_count() * statement_class_max * sizeof(PFS_statement_stat);
total_memory+= size;
break;
case 110:
- name= "events_statements_summary_global_by_event_name.row_size";
+ name= "events_statements_summary_global_by_event_name.size";
size= sizeof(PFS_statement_stat);
break;
case 111:
- name= "events_statements_summary_global_by_event_name.row_count";
+ name= "events_statements_summary_global_by_event_name.count";
size= statement_class_max;
break;
case 112:
@@ -1118,63 +1393,63 @@ bool pfs_show_status(handlerton *hton, THD *thd,
total_memory+= size;
break;
case 113:
- name= "events_statements_summary_by_account_by_event_name.row_size";
+ name= "events_statements_summary_by_account_by_event_name.size";
size= sizeof(PFS_statement_stat);
break;
case 114:
- name= "events_statements_summary_by_account_by_event_name.row_count";
- size= account_max * statement_class_max;
+ name= "events_statements_summary_by_account_by_event_name.count";
+ size= global_account_container.get_row_count() * statement_class_max;
break;
case 115:
name= "events_statements_summary_by_account_by_event_name.memory";
- size= account_max * statement_class_max * sizeof(PFS_statement_stat);
+ size= global_account_container.get_row_count() * statement_class_max * sizeof(PFS_statement_stat);
total_memory+= size;
break;
case 116:
- name= "events_statements_summary_by_user_by_event_name.row_size";
+ name= "events_statements_summary_by_user_by_event_name.size";
size= sizeof(PFS_statement_stat);
break;
case 117:
- name= "events_statements_summary_by_user_by_event_name.row_count";
- size= user_max * statement_class_max;
+ name= "events_statements_summary_by_user_by_event_name.count";
+ size= global_user_container.get_row_count() * statement_class_max;
break;
case 118:
name= "events_statements_summary_by_user_by_event_name.memory";
- size= user_max * statement_class_max * sizeof(PFS_statement_stat);
+ size= global_user_container.get_row_count() * statement_class_max * sizeof(PFS_statement_stat);
total_memory+= size;
break;
case 119:
- name= "events_statements_summary_by_host_by_event_name.row_size";
+ name= "events_statements_summary_by_host_by_event_name.size";
size= sizeof(PFS_statement_stat);
break;
case 120:
- name= "events_statements_summary_by_host_by_event_name.row_count";
- size= host_max * statement_class_max;
+ name= "events_statements_summary_by_host_by_event_name.count";
+ size= global_host_container.get_row_count() * statement_class_max;
break;
case 121:
name= "events_statements_summary_by_host_by_event_name.memory";
- size= host_max * statement_class_max * sizeof(PFS_statement_stat);
+ size= global_host_container.get_row_count() * statement_class_max * sizeof(PFS_statement_stat);
total_memory+= size;
break;
case 122:
- name= "events_statements_current.row_size";
+ name= "events_statements_current.size";
size= sizeof(PFS_events_statements);
break;
case 123:
- name= "events_statements_current.row_count";
- size= thread_max * statement_stack_max;
+ name= "events_statements_current.count";
+ size= global_thread_container.get_row_count() * statement_stack_max;
break;
case 124:
name= "events_statements_current.memory";
- size= thread_max * statement_stack_max * sizeof(PFS_events_statements);
+ size= global_thread_container.get_row_count() * statement_stack_max * sizeof(PFS_events_statements);
total_memory+= size;
break;
case 125:
- name= "(pfs_socket_class).row_size";
+ name= "(pfs_socket_class).size";
size= sizeof(PFS_socket_class);
break;
case 126:
- name= "(pfs_socket_class).row_count";
+ name= "(pfs_socket_class).count";
size= socket_class_max;
break;
case 127:
@@ -1183,110 +1458,144 @@ bool pfs_show_status(handlerton *hton, THD *thd,
total_memory+= size;
break;
case 128:
- name= "socket_instances.row_size";
- size= sizeof(PFS_socket);
+ name= "socket_instances.size";
+ size= global_socket_container.get_row_size();
break;
case 129:
- name= "socket_instances.row_count";
- size= socket_max;
+ name= "socket_instances.count";
+ size= global_socket_container.get_row_count();
break;
case 130:
name= "socket_instances.memory";
- size= socket_max * sizeof(PFS_socket);
+ size= global_socket_container.get_memory();
total_memory+= size;
break;
case 131:
- name= "events_statements_summary_by_digest.row_size";
+ name= "events_statements_summary_by_digest.size";
size= sizeof(PFS_statements_digest_stat);
break;
case 132:
- name= "events_statements_summary_by_digest.row_count";
+ name= "events_statements_summary_by_digest.count";
size= digest_max;
break;
case 133:
name= "events_statements_summary_by_digest.memory";
- size= digest_max * sizeof(PFS_statements_digest_stat);
+ size= digest_max * (sizeof(PFS_statements_digest_stat));
total_memory+= size;
break;
case 134:
- name= "session_connect_attrs.row_size";
- size= thread_max;
+ name= "events_statements_summary_by_program.size";
+ size= global_program_container.get_row_size();
break;
case 135:
- name= "session_connect_attrs.row_count";
- size= session_connect_attrs_size_per_thread;
+ name= "events_statements_summary_by_program.count";
+ size= global_program_container.get_row_count();
break;
case 136:
+ name= "events_statements_summary_by_program.memory";
+ size= global_program_container.get_memory();
+ total_memory+= size;
+ break;
+ case 137:
+ name= "session_connect_attrs.size";
+ size= global_thread_container.get_row_count();
+ break;
+ case 138:
+ name= "session_connect_attrs.count";
+ size= session_connect_attrs_size_per_thread;
+ break;
+ case 139:
name= "session_connect_attrs.memory";
- size= thread_max * session_connect_attrs_size_per_thread;
+ size= global_thread_container.get_row_count() * session_connect_attrs_size_per_thread;
+ total_memory+= size;
+ break;
+ case 140:
+ name= "prepared_statements_instances.size";
+ size= global_prepared_stmt_container.get_row_size();
+ break;
+ case 141:
+ name= "prepared_statements_instances.count";
+ size= global_prepared_stmt_container.get_row_count();
+ break;
+ case 142:
+ name= "prepared_statements_instances.memory";
+ size= global_prepared_stmt_container.get_memory();
total_memory+= size;
break;
- case 137:
+ case 143:
name= "(account_hash).count";
size= account_hash.count;
break;
- case 138:
+ case 144:
name= "(account_hash).size";
size= account_hash.size;
break;
- case 139:
+ case 145:
name= "(digest_hash).count";
size= digest_hash.count;
break;
- case 140:
+ case 146:
name= "(digest_hash).size";
size= digest_hash.size;
break;
- case 141:
+ case 147:
name= "(filename_hash).count";
size= filename_hash.count;
break;
- case 142:
+ case 148:
name= "(filename_hash).size";
size= filename_hash.size;
break;
- case 143:
+ case 149:
name= "(host_hash).count";
size= host_hash.count;
break;
- case 144:
+ case 150:
name= "(host_hash).size";
size= host_hash.size;
break;
- case 145:
+ case 151:
name= "(setup_actor_hash).count";
size= setup_actor_hash.count;
break;
- case 146:
+ case 152:
name= "(setup_actor_hash).size";
size= setup_actor_hash.size;
break;
- case 147:
+ case 153:
name= "(setup_object_hash).count";
size= setup_object_hash.count;
break;
- case 148:
+ case 154:
name= "(setup_object_hash).size";
size= setup_object_hash.size;
break;
- case 149:
+ case 155:
name= "(table_share_hash).count";
size= table_share_hash.count;
break;
- case 150:
+ case 156:
name= "(table_share_hash).size";
size= table_share_hash.size;
break;
- case 151:
+ case 157:
name= "(user_hash).count";
size= user_hash.count;
break;
- case 152:
+ case 158:
name= "(user_hash).size";
size= user_hash.size;
break;
- case 153:
+ case 159:
+ name= "(program_hash).count";
+ size= program_hash.count;
+ break;
+ case 160:
+ name= "(program_hash).size";
+ size= program_hash.size;
+ break;
+ case 161:
/*
This is not a performance_schema buffer,
the data is maintained in the server,
@@ -1298,68 +1607,302 @@ bool pfs_show_status(handlerton *hton, THD *thd,
name= "host_cache.size";
size= sizeof(Host_entry);
break;
- case 154:
- name= "(history_long_statements_digest_token_array).row_count";
+
+ case 162:
+ name= "(pfs_memory_class).row_size";
+ size= sizeof(PFS_memory_class);
+ break;
+ case 163:
+ name= "(pfs_memory_class).row_count";
+ size= memory_class_max;
+ break;
+ case 164:
+ name= "(pfs_memory_class).memory";
+ size= memory_class_max * sizeof(PFS_memory_class);
+ total_memory+= size;
+ break;
+
+ case 165:
+ name= "memory_summary_by_thread_by_event_name.row_size";
+ size= sizeof(PFS_memory_stat);
+ break;
+ case 166:
+ name= "memory_summary_by_thread_by_event_name.row_count";
+ size= global_thread_container.get_row_count() * memory_class_max;
+ break;
+ case 167:
+ name= "memory_summary_by_thread_by_event_name.memory";
+ size= global_thread_container.get_row_count() * memory_class_max * sizeof(PFS_memory_stat);
+ total_memory+= size;
+ break;
+ case 168:
+ name= "memory_summary_global_by_event_name.row_size";
+ size= sizeof(PFS_memory_stat);
+ break;
+ case 169:
+ name= "memory_summary_global_by_event_name.row_count";
+ size= memory_class_max;
+ break;
+ case 170:
+ name= "memory_summary_global_by_event_name.memory";
+ size= memory_class_max * sizeof(PFS_memory_stat);
+ total_memory+= size;
+ break;
+ case 171:
+ name= "memory_summary_by_account_by_event_name.row_size";
+ size= sizeof(PFS_memory_stat);
+ break;
+ case 172:
+ name= "memory_summary_by_account_by_event_name.row_count";
+ size= global_account_container.get_row_count() * memory_class_max;
+ break;
+ case 173:
+ name= "memory_summary_by_account_by_event_name.memory";
+ size= global_account_container.get_row_count() * memory_class_max * sizeof(PFS_memory_stat);
+ total_memory+= size;
+ break;
+ case 174:
+ name= "memory_summary_by_user_by_event_name.row_size";
+ size= sizeof(PFS_memory_stat);
+ break;
+ case 175:
+ name= "memory_summary_by_user_by_event_name.row_count";
+ size= global_user_container.get_row_count() * memory_class_max;
+ break;
+ case 176:
+ name= "memory_summary_by_user_by_event_name.memory";
+ size= global_user_container.get_row_count() * memory_class_max * sizeof(PFS_memory_stat);
+ total_memory+= size;
+ break;
+ case 177:
+ name= "memory_summary_by_host_by_event_name.row_size";
+ size= sizeof(PFS_memory_stat);
+ break;
+ case 178:
+ name= "memory_summary_by_host_by_event_name.row_count";
+ size= global_host_container.get_row_count() * memory_class_max;
+ break;
+ case 179:
+ name= "memory_summary_by_host_by_event_name.memory";
+ size= global_host_container.get_row_count() * memory_class_max * sizeof(PFS_memory_stat);
+ total_memory+= size;
+ break;
+ case 180:
+ name= "metadata_locks.row_size";
+ size= global_mdl_container.get_row_size();
+ break;
+ case 181:
+ name= "metadata_locks.row_count";
+ size= global_mdl_container.get_row_count();
+ break;
+ case 182:
+ name= "metadata_locks.memory";
+ size= global_mdl_container.get_memory();
+ total_memory+= size;
+ break;
+ case 183:
+ name= "events_transactions_history.size";
+ size= sizeof(PFS_events_transactions);
+ break;
+ case 184:
+ name= "events_transactions_history.count";
+ size= events_transactions_history_per_thread * global_thread_container.get_row_count();
+ break;
+ case 185:
+ name= "events_transactions_history.memory";
+ size= events_transactions_history_per_thread * global_thread_container.get_row_count()
+ * sizeof(PFS_events_transactions);
+ total_memory+= size;
+ break;
+ case 186:
+ name= "events_transactions_history_long.size";
+ size= sizeof(PFS_events_transactions);
+ break;
+ case 187:
+ name= "events_transactions_history_long.count";
+ size= events_transactions_history_long_size;
+ break;
+ case 188:
+ name= "events_transactions_history_long.memory";
+ size= events_transactions_history_long_size * sizeof(PFS_events_transactions);
+ total_memory+= size;
+ break;
+ case 189:
+ name= "events_transactions_summary_by_thread_by_event_name.size";
+ size= sizeof(PFS_transaction_stat);
+ break;
+ case 190:
+ name= "events_transactions_summary_by_thread_by_event_name.count";
+ size= global_thread_container.get_row_count() * transaction_class_max;
+ break;
+ case 191:
+ name= "events_transactions_summary_by_thread_by_event_name.memory";
+ size= global_thread_container.get_row_count() * transaction_class_max * sizeof(PFS_transaction_stat);
+ total_memory+= size;
+ break;
+ case 192:
+ name= "events_transactions_summary_by_account_by_event_name.size";
+ size= sizeof(PFS_transaction_stat);
+ break;
+ case 193:
+ name= "events_transactions_summary_by_account_by_event_name.count";
+ size= global_account_container.get_row_count() * transaction_class_max;
+ break;
+ case 194:
+ name= "events_transactions_summary_by_account_by_event_name.memory";
+ size= global_account_container.get_row_count() * transaction_class_max * sizeof(PFS_transaction_stat);
+ total_memory+= size;
+ break;
+ case 195:
+ name= "events_transactions_summary_by_user_by_event_name.size";
+ size= sizeof(PFS_transaction_stat);
+ break;
+ case 196:
+ name= "events_transactions_summary_by_user_by_event_name.count";
+ size= global_user_container.get_row_count() * transaction_class_max;
+ break;
+ case 197:
+ name= "events_transactions_summary_by_user_by_event_name.memory";
+ size= global_user_container.get_row_count() * transaction_class_max * sizeof(PFS_transaction_stat);
+ total_memory+= size;
+ break;
+ case 198:
+ name= "events_transactions_summary_by_host_by_event_name.size";
+ size= sizeof(PFS_transaction_stat);
+ break;
+ case 199:
+ name= "events_transactions_summary_by_host_by_event_name.count";
+ size= global_host_container.get_row_count() * transaction_class_max;
+ break;
+ case 200:
+ name= "events_transactions_summary_by_host_by_event_name.memory";
+ size= global_host_container.get_row_count() * transaction_class_max * sizeof(PFS_transaction_stat);
+ total_memory+= size;
+ break;
+ case 201:
+ name= "table_lock_waits_summary_by_table.size";
+ size= global_table_share_lock_container.get_row_size();
+ break;
+ case 202:
+ name= "table_lock_waits_summary_by_table.count";
+ size= global_table_share_lock_container.get_row_count();
+ break;
+ case 203:
+ name= "table_lock_waits_summary_by_table.memory";
+ size= global_table_share_lock_container.get_memory();
+ total_memory+= size;
+ break;
+ case 204:
+ name= "table_io_waits_summary_by_index_usage.size";
+ size= global_table_share_index_container.get_row_size();
+ break;
+ case 205:
+ name= "table_io_waits_summary_by_index_usage.count";
+ size= global_table_share_index_container.get_row_count();
+ break;
+ case 206:
+ name= "table_io_waits_summary_by_index_usage.memory";
+ size= global_table_share_index_container.get_memory();
+ total_memory+= size;
+ break;
+ case 207:
+ name= "(history_long_statements_digest_token_array).count";
size= events_statements_history_long_size;
break;
- case 155:
- name= "(history_long_statements_digest_token_array).row_size";
+ case 208:
+ name= "(history_long_statements_digest_token_array).size";
size= pfs_max_digest_length;
break;
- case 156:
+ case 209:
name= "(history_long_statements_digest_token_array).memory";
size= events_statements_history_long_size * pfs_max_digest_length;
total_memory+= size;
break;
- case 157:
- name= "(history_statements_digest_token_array).row_count";
- size= thread_max * events_statements_history_per_thread;
+ case 210:
+ name= "(history_statements_digest_token_array).count";
+ size= global_thread_container.get_row_count() * events_statements_history_per_thread;
break;
- case 158:
- name= "(history_statements_digest_token_array).row_size";
+ case 211:
+ name= "(history_statements_digest_token_array).size";
size= pfs_max_digest_length;
break;
- case 159:
+ case 212:
name= "(history_statements_digest_token_array).memory";
- size= thread_max * events_statements_history_per_thread * pfs_max_digest_length;
+ size= global_thread_container.get_row_count() * events_statements_history_per_thread * pfs_max_digest_length;
total_memory+= size;
break;
- case 160:
- name= "(current_statements_digest_token_array).row_count";
- size= thread_max * statement_stack_max;
+ case 213:
+ name= "(current_statements_digest_token_array).count";
+ size= global_thread_container.get_row_count() * statement_stack_max;
break;
- case 161:
- name= "(current_statements_digest_token_array).row_size";
+ case 214:
+ name= "(current_statements_digest_token_array).size";
size= pfs_max_digest_length;
break;
- case 162:
+ case 215:
name= "(current_statements_digest_token_array).memory";
- size= thread_max * statement_stack_max * pfs_max_digest_length;
+ size= global_thread_container.get_row_count() * statement_stack_max * pfs_max_digest_length;
total_memory+= size;
break;
- case 163:
- name= "(statements_digest_token_array).row_count";
+ case 216:
+ name= "(history_long_statements_text_array).count";
+ size= events_statements_history_long_size;
+ break;
+ case 217:
+ name= "(history_long_statements_text_array).size";
+ size= pfs_max_sqltext;
+ break;
+ case 218:
+ name= "(history_long_statements_text_array).memory";
+ size= events_statements_history_long_size * pfs_max_sqltext;
+ total_memory+= size;
+ break;
+ case 219:
+ name= "(history_statements_text_array).count";
+ size= global_thread_container.get_row_count() * events_statements_history_per_thread;
+ break;
+ case 220:
+ name= "(history_statements_text_array).size";
+ size= pfs_max_sqltext;
+ break;
+ case 221:
+ name= "(history_statements_text_array).memory";
+ size= global_thread_container.get_row_count() * events_statements_history_per_thread * pfs_max_sqltext;
+ total_memory+= size;
+ break;
+ case 222:
+ name= "(current_statements_text_array).count";
+ size= global_thread_container.get_row_count() * statement_stack_max;
+ break;
+ case 223:
+ name= "(current_statements_text_array).size";
+ size= pfs_max_sqltext;
+ break;
+ case 224:
+ name= "(current_statements_text_array).memory";
+ size= global_thread_container.get_row_count() * statement_stack_max * pfs_max_sqltext;
+ total_memory+= size;
+ break;
+ case 225:
+ name= "(statements_digest_token_array).count";
size= digest_max;
break;
- case 164:
- name= "(statements_digest_token_array).row_size";
+ case 226:
+ name= "(statements_digest_token_array).size";
size= pfs_max_digest_length;
break;
- case 165:
+ case 227:
name= "(statements_digest_token_array).memory";
size= digest_max * pfs_max_digest_length;
total_memory+= size;
break;
-
/*
This case must be last,
for aggregation in total_memory.
*/
- case 166:
+ case 228:
name= "performance_schema.memory";
size= total_memory;
- /* This will fail if something is not advertised here */
- DBUG_ASSERT(size == pfs_allocated_memory);
break;
default:
goto end;
diff --git a/storage/perfschema/pfs_engine_table.h b/storage/perfschema/pfs_engine_table.h
index a1a01df6e15..b751d48a38f 100644
--- a/storage/perfschema/pfs_engine_table.h
+++ b/storage/perfschema/pfs_engine_table.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2016, 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, version 2.0,
@@ -23,13 +23,24 @@
#ifndef PFS_ENGINE_TABLE_H
#define PFS_ENGINE_TABLE_H
-#include "sql_acl.h" /* struct ACL_* */
+#include "table.h"
+#include "sql_acl.h"
/**
@file storage/perfschema/pfs_engine_table.h
Performance schema tables (declarations).
*/
#include "pfs_instr_class.h"
+extern pthread_key_t THR_PFS_VG; // global_variables
+extern pthread_key_t THR_PFS_SV; // session_variables
+extern pthread_key_t THR_PFS_VBT; // variables_by_thread
+extern pthread_key_t THR_PFS_SG; // global_status
+extern pthread_key_t THR_PFS_SS; // session_status
+extern pthread_key_t THR_PFS_SBT; // status_by_thread
+extern pthread_key_t THR_PFS_SBU; // status_by_user
+extern pthread_key_t THR_PFS_SBH; // status_by_host
+extern pthread_key_t THR_PFS_SBA; // status_by_account
+
class Field;
struct PFS_engine_table_share;
struct time_normalizer;
@@ -40,6 +51,36 @@ struct time_normalizer;
*/
/**
+ Store and retrieve table state information during a query.
+*/
+class PFS_table_context
+{
+public:
+ PFS_table_context(ulonglong current_version, bool restore, pthread_key_t key);
+ PFS_table_context(ulonglong current_version, ulong map_size, bool restore, pthread_key_t key);
+~PFS_table_context(void);
+
+ bool initialize(void);
+ bool is_initialized(void) { return m_initialized; }
+ ulonglong current_version(void) { return m_current_version; }
+ ulonglong last_version(void) { return m_last_version; }
+ bool versions_match(void) { return m_last_version == m_current_version; }
+ void set_item(ulong n);
+ bool is_item_set(ulong n);
+ pthread_key_t m_thr_key;
+
+private:
+ ulonglong m_current_version;
+ ulonglong m_last_version;
+ ulong *m_map;
+ ulong m_map_size;
+ ulong m_word_size;
+ bool m_restore;
+ bool m_initialized;
+ ulong m_last_item;
+};
+
+/**
An abstract PERFORMANCE_SCHEMA table.
Every table implemented in the performance schema schema and storage engine
derives from this class.
@@ -88,12 +129,24 @@ public:
{}
/**
+ Helper, assign a value to a long field.
+ @param f the field to set
+ @param value the value to assign
+ */
+ static void set_field_long(Field *f, long value);
+ /**
Helper, assign a value to a ulong field.
@param f the field to set
@param value the value to assign
*/
static void set_field_ulong(Field *f, ulong value);
/**
+ Helper, assign a value to a longlong field.
+ @param f the field to set
+ @param value the value to assign
+ */
+ static void set_field_longlong(Field *f, longlong value);
+ /**
Helper, assign a value to a ulonglong field.
@param f the field to set
@param value the value to assign
@@ -109,6 +162,14 @@ public:
/**
Helper, assign a value to a varchar utf8 field.
@param f the field to set
+ @param cs the string character set
+ @param str the string to assign
+ @param len the length of the string to assign
+ */
+ static void set_field_varchar(Field *f, const CHARSET_INFO *cs, const char *str, uint len);
+ /**
+ Helper, assign a value to a varchar utf8 field.
+ @param f the field to set
@param str the string to assign
@param len the length of the string to assign
*/
@@ -121,6 +182,13 @@ public:
*/
static void set_field_longtext_utf8(Field *f, const char *str, uint len);
/**
+ Helper, assign a value to a blob field.
+ @param f the field to set
+ @param val the value to assign
+ @param len the length of the string to assign
+ */
+ static void set_field_blob(Field *f, const char *val, uint len);
+ /**
Helper, assign a value to an enum field.
@param f the field to set
@param value the value to assign
@@ -133,6 +201,12 @@ public:
*/
static void set_field_timestamp(Field *f, ulonglong value);
/**
+ Helper, assign a value to a double field.
+ @param f the field to set
+ @param value the value to assign
+ */
+ static void set_field_double(Field *f, double value);
+ /**
Helper, read a value from an enum field.
@param f the field to read
@return the field value
@@ -182,7 +256,6 @@ protected:
*/
virtual int delete_row_values(TABLE *table, const unsigned char *buf,
Field **fields);
-
/**
Constructor.
@param share table share
@@ -238,19 +311,14 @@ struct PFS_engine_table_share
pfs_delete_all_rows_t m_delete_all_rows;
/** Get rows count function. */
pfs_get_row_count_t m_get_row_count;
- /**
- Number or records.
- This number does not need to be precise,
- it is used by the optimizer to decide if the table
- has 0, 1, or many records.
- */
- ha_rows m_records;
/** Length of the m_pos position structure. */
uint m_ref_length;
/** The lock, stored on behalf of the SQL layer. */
THR_LOCK *m_thr_lock_ptr;
/** Table definition. */
LEX_STRING sql;
+ /** Table is available even if the Performance Schema is disabled. */
+ bool m_perpetual;
};
/**
@@ -352,6 +420,45 @@ public:
/** Singleton instance of PFS_unknown_acl. */
extern PFS_unknown_acl pfs_unknown_acl;
+
+/**
+ Privileges for world readable tables.
+*/
+class PFS_readonly_world_acl : public PFS_readonly_acl
+{
+public:
+ PFS_readonly_world_acl()
+ {}
+
+ ~PFS_readonly_world_acl()
+ {}
+ virtual ACL_internal_access_result check(ulong want_access, ulong *save_priv) const;
+};
+
+
+/** Singleton instance of PFS_readonly_world_acl */
+extern PFS_readonly_world_acl pfs_readonly_world_acl;
+
+
+/**
+Privileges for world readable truncatable tables.
+*/
+class PFS_truncatable_world_acl : public PFS_truncatable_acl
+{
+public:
+ PFS_truncatable_world_acl()
+ {}
+
+ ~PFS_truncatable_world_acl()
+ {}
+ virtual ACL_internal_access_result check(ulong want_access, ulong *save_priv) const;
+};
+
+
+/** Singleton instance of PFS_readonly_world_acl */
+extern PFS_truncatable_world_acl pfs_truncatable_world_acl;
+
+
/** Position of a cursor, for simple iterations. */
struct PFS_simple_index
{
@@ -368,6 +475,13 @@ struct PFS_simple_index
/**
Set this index at a given position.
+ @param index an index
+ */
+ void set_at(uint index)
+ { m_index= index; }
+
+ /**
+ Set this index at a given position.
@param other a position
*/
void set_at(const struct PFS_simple_index *other)
@@ -404,6 +518,15 @@ struct PFS_double_index
/**
Set this index at a given position.
+ */
+ void set_at(uint index_1, uint index_2)
+ {
+ m_index_1= index_1;
+ m_index_2= index_2;
+ }
+
+ /**
+ Set this index at a given position.
@param other a position
*/
void set_at(const struct PFS_double_index *other)
@@ -445,6 +568,16 @@ struct PFS_triple_index
/**
Set this index at a given position.
+ */
+ void set_at(uint index_1, uint index_2, uint index_3)
+ {
+ m_index_1= index_1;
+ m_index_2= index_2;
+ m_index_3= index_3;
+ }
+
+ /**
+ Set this index at a given position.
@param other a position
*/
void set_at(const struct PFS_triple_index *other)
diff --git a/storage/perfschema/pfs_events.h b/storage/perfschema/pfs_events.h
index ca2fd8582ad..47c4c9280e6 100644
--- a/storage/perfschema/pfs_events.h
+++ b/storage/perfschema/pfs_events.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -43,6 +43,12 @@ struct PFS_events
ulonglong m_end_event_id;
/** NESTING_EVENT_ID. */
ulonglong m_nesting_event_id;
+ /** NESTING_EVENT_TYPE */
+ enum_event_type m_nesting_event_type;
+ /** NESTING_EVENT_LEVEL */
+ uint m_nesting_event_level;
+ /** Instrument metadata. */
+ PFS_instr_class *m_class;
/**
Timer start.
This member is populated only if m_class->m_timed is true.
@@ -53,14 +59,8 @@ struct PFS_events
This member is populated only if m_class->m_timed is true.
*/
ulonglong m_timer_end;
- /** Instrument metadata. */
- PFS_instr_class *m_class;
/** Location of the instrumentation in the source code (file name). */
const char *m_source_file;
- /** (EVENT_TYPE) */
- enum_event_type m_event_type;
- /** NESTING_EVENT_TYPE */
- enum_event_type m_nesting_event_type;
/** Location of the instrumentation in the source code (line number). */
uint m_source_line;
};
diff --git a/storage/perfschema/pfs_events_stages.cc b/storage/perfschema/pfs_events_stages.cc
index a68b0729e96..e5a6b9a2007 100644
--- a/storage/perfschema/pfs_events_stages.cc
+++ b/storage/perfschema/pfs_events_stages.cc
@@ -35,22 +35,24 @@
#include "pfs_user.h"
#include "pfs_events_stages.h"
#include "pfs_atomic.h"
+#include "pfs_buffer_container.h"
+#include "pfs_builtin_memory.h"
#include "m_string.h"
-ulong events_stages_history_long_size= 0;
+PFS_ALIGNED ulong events_stages_history_long_size= 0;
/** Consumer flag for table EVENTS_STAGES_CURRENT. */
-bool flag_events_stages_current= false;
+PFS_ALIGNED bool flag_events_stages_current= false;
/** Consumer flag for table EVENTS_STAGES_HISTORY. */
-bool flag_events_stages_history= false;
+PFS_ALIGNED bool flag_events_stages_history= false;
/** Consumer flag for table EVENTS_STAGES_HISTORY_LONG. */
-bool flag_events_stages_history_long= false;
+PFS_ALIGNED bool flag_events_stages_history_long= false;
/** True if EVENTS_STAGES_HISTORY_LONG circular buffer is full. */
-bool events_stages_history_long_full= false;
+PFS_ALIGNED bool events_stages_history_long_full= false;
/** Index in EVENTS_STAGES_HISTORY_LONG circular buffer. */
-volatile uint32 events_stages_history_long_index= 0;
+PFS_ALIGNED PFS_cacheline_uint32 events_stages_history_long_index;
/** EVENTS_STAGES_HISTORY_LONG circular buffer. */
-PFS_events_stages *events_stages_history_long_array= NULL;
+PFS_ALIGNED PFS_events_stages *events_stages_history_long_array= NULL;
/**
Initialize table EVENTS_STAGES_HISTORY_LONG.
@@ -60,14 +62,16 @@ int init_events_stages_history_long(uint events_stages_history_long_sizing)
{
events_stages_history_long_size= events_stages_history_long_sizing;
events_stages_history_long_full= false;
- PFS_atomic::store_u32(&events_stages_history_long_index, 0);
+ PFS_atomic::store_u32(&events_stages_history_long_index.m_u32, 0);
if (events_stages_history_long_size == 0)
return 0;
events_stages_history_long_array=
- PFS_MALLOC_ARRAY(events_stages_history_long_size, sizeof(PFS_events_stages),
- PFS_events_stages, MYF(MY_ZEROFILL));
+ PFS_MALLOC_ARRAY(& builtin_memory_stages_history_long,
+ events_stages_history_long_size,
+ sizeof(PFS_events_stages), PFS_events_stages,
+ MYF(MY_ZEROFILL));
return (events_stages_history_long_array ? 0 : 1);
}
@@ -75,7 +79,9 @@ int init_events_stages_history_long(uint events_stages_history_long_sizing)
/** Cleanup table EVENTS_STAGES_HISTORY_LONG. */
void cleanup_events_stages_history_long(void)
{
- pfs_free(events_stages_history_long_array);
+ PFS_FREE_ARRAY(& builtin_memory_stages_history_long,
+ events_stages_history_long_size, sizeof(PFS_events_stages),
+ events_stages_history_long_array);
events_stages_history_long_array= NULL;
}
@@ -129,7 +135,7 @@ void insert_events_stages_history_long(PFS_events_stages *stage)
DBUG_ASSERT(events_stages_history_long_array != NULL);
- uint index= PFS_atomic::add_u32(&events_stages_history_long_index, 1);
+ uint index= PFS_atomic::add_u32(&events_stages_history_long_index.m_u32, 1);
index= index % events_stages_history_long_size;
if (index == 0)
@@ -139,40 +145,38 @@ void insert_events_stages_history_long(PFS_events_stages *stage)
copy_events_stages(&events_stages_history_long_array[index], stage);
}
+static void fct_reset_events_stages_current(PFS_thread *pfs)
+{
+ pfs->m_stage_current.m_class= NULL;
+}
+
/** Reset table EVENTS_STAGES_CURRENT data. */
void reset_events_stages_current(void)
{
- PFS_thread *pfs_thread= thread_array;
- PFS_thread *pfs_thread_last= thread_array + thread_max;
+ global_thread_container.apply_all(fct_reset_events_stages_current);
+}
- for ( ; pfs_thread < pfs_thread_last; pfs_thread++)
- {
- pfs_thread->m_stage_current.m_class= NULL;
- }
+static void fct_reset_events_stages_history(PFS_thread *pfs_thread)
+{
+ PFS_events_stages *pfs= pfs_thread->m_stages_history;
+ PFS_events_stages *pfs_last= pfs + events_stages_history_per_thread;
+
+ pfs_thread->m_stages_history_index= 0;
+ pfs_thread->m_stages_history_full= false;
+ for ( ; pfs < pfs_last; pfs++)
+ pfs->m_class= NULL;
}
/** Reset table EVENTS_STAGES_HISTORY data. */
void reset_events_stages_history(void)
{
- PFS_thread *pfs_thread= thread_array;
- PFS_thread *pfs_thread_last= thread_array + thread_max;
-
- for ( ; pfs_thread < pfs_thread_last; pfs_thread++)
- {
- PFS_events_stages *pfs= pfs_thread->m_stages_history;
- PFS_events_stages *pfs_last= pfs + events_stages_history_per_thread;
-
- pfs_thread->m_stages_history_index= 0;
- pfs_thread->m_stages_history_full= false;
- for ( ; pfs < pfs_last; pfs++)
- pfs->m_class= NULL;
- }
+ global_thread_container.apply_all(fct_reset_events_stages_history);
}
/** Reset table EVENTS_STAGES_HISTORY_LONG data. */
void reset_events_stages_history_long(void)
{
- PFS_atomic::store_u32(&events_stages_history_long_index, 0);
+ PFS_atomic::store_u32(&events_stages_history_long_index.m_u32, 0);
events_stages_history_long_full= false;
PFS_events_stages *pfs= events_stages_history_long_array;
@@ -181,70 +185,53 @@ void reset_events_stages_history_long(void)
pfs->m_class= NULL;
}
+static void fct_reset_events_stages_by_thread(PFS_thread *thread)
+{
+ PFS_account *account= sanitize_account(thread->m_account);
+ PFS_user *user= sanitize_user(thread->m_user);
+ PFS_host *host= sanitize_host(thread->m_host);
+ aggregate_thread_stages(thread, account, user, host);
+}
+
/** Reset table EVENTS_STAGES_SUMMARY_BY_THREAD_BY_EVENT_NAME data. */
void reset_events_stages_by_thread()
{
- PFS_thread *thread= thread_array;
- PFS_thread *thread_last= thread_array + thread_max;
- PFS_account *account;
- PFS_user *user;
- PFS_host *host;
+ global_thread_container.apply(fct_reset_events_stages_by_thread);
+}
- for ( ; thread < thread_last; thread++)
- {
- if (thread->m_lock.is_populated())
- {
- account= sanitize_account(thread->m_account);
- user= sanitize_user(thread->m_user);
- host= sanitize_host(thread->m_host);
- aggregate_thread_stages(thread, account, user, host);
- }
- }
+static void fct_reset_events_stages_by_account(PFS_account *pfs)
+{
+ PFS_user *user= sanitize_user(pfs->m_user);
+ PFS_host *host= sanitize_host(pfs->m_host);
+ pfs->aggregate_stages(user, host);
}
/** Reset table EVENTS_STAGES_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME data. */
void reset_events_stages_by_account()
{
- PFS_account *pfs= account_array;
- PFS_account *pfs_last= account_array + account_max;
- PFS_user *user;
- PFS_host *host;
+ global_account_container.apply(fct_reset_events_stages_by_account);
+}
- for ( ; pfs < pfs_last; pfs++)
- {
- if (pfs->m_lock.is_populated())
- {
- user= sanitize_user(pfs->m_user);
- host= sanitize_host(pfs->m_host);
- pfs->aggregate_stages(user, host);
- }
- }
+static void fct_reset_events_stages_by_user(PFS_user *pfs)
+{
+ pfs->aggregate_stages();
}
/** Reset table EVENTS_STAGES_SUMMARY_BY_USER_BY_EVENT_NAME data. */
void reset_events_stages_by_user()
{
- PFS_user *pfs= user_array;
- PFS_user *pfs_last= user_array + user_max;
+ global_user_container.apply(fct_reset_events_stages_by_user);
+}
- for ( ; pfs < pfs_last; pfs++)
- {
- if (pfs->m_lock.is_populated())
- pfs->aggregate_stages();
- }
+static void fct_reset_events_stages_by_host(PFS_host *pfs)
+{
+ pfs->aggregate_stages();
}
/** Reset table EVENTS_STAGES_SUMMARY_BY_HOST_BY_EVENT_NAME data. */
void reset_events_stages_by_host()
{
- PFS_host *pfs= host_array;
- PFS_host *pfs_last= host_array + host_max;
-
- for ( ; pfs < pfs_last; pfs++)
- {
- if (pfs->m_lock.is_populated())
- pfs->aggregate_stages();
- }
+ global_host_container.apply(fct_reset_events_stages_by_host);
}
/** Reset table EVENTS_STAGES_GLOBAL_BY_EVENT_NAME data. */
diff --git a/storage/perfschema/pfs_events_stages.h b/storage/perfschema/pfs_events_stages.h
index f61a7c3c077..0b7d27ded82 100644
--- a/storage/perfschema/pfs_events_stages.h
+++ b/storage/perfschema/pfs_events_stages.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -38,7 +38,7 @@ struct PFS_host;
/** A stage record. */
struct PFS_events_stages : public PFS_events
{
- /* No specific attributes */
+ PSI_stage_progress m_progress;
};
void insert_events_stages_history(PFS_thread *thread, PFS_events_stages *stage);
@@ -49,7 +49,7 @@ extern bool flag_events_stages_history;
extern bool flag_events_stages_history_long;
extern bool events_stages_history_long_full;
-extern volatile uint32 events_stages_history_long_index;
+extern PFS_ALIGNED PFS_cacheline_uint32 events_stages_history_long_index;
extern PFS_events_stages *events_stages_history_long_array;
extern ulong events_stages_history_long_size;
diff --git a/storage/perfschema/pfs_events_statements.cc b/storage/perfschema/pfs_events_statements.cc
index 1942787665a..e0f1b2bfb77 100644
--- a/storage/perfschema/pfs_events_statements.cc
+++ b/storage/perfschema/pfs_events_statements.cc
@@ -35,23 +35,26 @@
#include "pfs_user.h"
#include "pfs_events_statements.h"
#include "pfs_atomic.h"
+#include "pfs_buffer_container.h"
+#include "pfs_builtin_memory.h"
#include "m_string.h"
-size_t events_statements_history_long_size= 0;
+PFS_ALIGNED size_t events_statements_history_long_size= 0;
/** Consumer flag for table EVENTS_STATEMENTS_CURRENT. */
-bool flag_events_statements_current= false;
+PFS_ALIGNED bool flag_events_statements_current= false;
/** Consumer flag for table EVENTS_STATEMENTS_HISTORY. */
-bool flag_events_statements_history= false;
+PFS_ALIGNED bool flag_events_statements_history= false;
/** Consumer flag for table EVENTS_STATEMENTS_HISTORY_LONG. */
-bool flag_events_statements_history_long= false;
+PFS_ALIGNED bool flag_events_statements_history_long= false;
/** True if EVENTS_STATEMENTS_HISTORY_LONG circular buffer is full. */
-bool events_statements_history_long_full= false;
+PFS_ALIGNED bool events_statements_history_long_full= false;
/** Index in EVENTS_STATEMENTS_HISTORY_LONG circular buffer. */
-volatile uint32 events_statements_history_long_index= 0;
+PFS_ALIGNED PFS_cacheline_uint32 events_statements_history_long_index;
/** EVENTS_STATEMENTS_HISTORY_LONG circular buffer. */
-PFS_events_statements *events_statements_history_long_array= NULL;
+PFS_ALIGNED PFS_events_statements *events_statements_history_long_array= NULL;
static unsigned char *h_long_stmts_digest_token_array= NULL;
+static char *h_long_stmts_text_array= NULL;
/**
Initialize table EVENTS_STATEMENTS_HISTORY_LONG.
@@ -61,29 +64,32 @@ int init_events_statements_history_long(size_t events_statements_history_long_si
{
events_statements_history_long_size= events_statements_history_long_sizing;
events_statements_history_long_full= false;
- PFS_atomic::store_u32(&events_statements_history_long_index, 0);
+ PFS_atomic::store_u32(&events_statements_history_long_index.m_u32, 0);
if (events_statements_history_long_size == 0)
return 0;
events_statements_history_long_array=
- PFS_MALLOC_ARRAY(events_statements_history_long_size, sizeof(PFS_events_statements),
+ PFS_MALLOC_ARRAY(& builtin_memory_statements_history_long,
+ events_statements_history_long_size, sizeof(PFS_events_statements),
PFS_events_statements, MYF(MY_ZEROFILL));
if (events_statements_history_long_array == NULL)
- {
- cleanup_events_statements_history_long();
- return 1;
- }
+ {
+ cleanup_events_statements_history_long();
+ return 1;
+ }
if (pfs_max_digest_length > 0)
{
- /* Size of each digest token array. */
+ /* Size of each digest text array. */
size_t digest_text_size= pfs_max_digest_length * sizeof(unsigned char);
h_long_stmts_digest_token_array=
- PFS_MALLOC_ARRAY(events_statements_history_long_size, digest_text_size,
+ PFS_MALLOC_ARRAY(& builtin_memory_statements_history_long_tokens,
+ events_statements_history_long_size, digest_text_size,
unsigned char, MYF(MY_ZEROFILL));
+
if (h_long_stmts_digest_token_array == NULL)
{
cleanup_events_statements_history_long();
@@ -91,10 +97,28 @@ int init_events_statements_history_long(size_t events_statements_history_long_si
}
}
+ if (pfs_max_sqltext > 0)
+ {
+ /* Size of each sql text array. */
+ size_t sqltext_size= pfs_max_sqltext * sizeof(char);
+
+ h_long_stmts_text_array=
+ PFS_MALLOC_ARRAY(& builtin_memory_statements_history_long_sqltext,
+ events_statements_history_long_size, sqltext_size,
+ char, MYF(MY_ZEROFILL));
+
+ if (h_long_stmts_text_array == NULL)
+ {
+ cleanup_events_statements_history_long();
+ return 1;
+ }
+ }
+
for (size_t index= 0; index < events_statements_history_long_size; index++)
{
events_statements_history_long_array[index].m_digest_storage.reset(h_long_stmts_digest_token_array
+ index * pfs_max_digest_length, pfs_max_digest_length);
+ events_statements_history_long_array[index].m_sqltext= h_long_stmts_text_array + index * pfs_max_sqltext;
}
return 0;
@@ -103,17 +127,44 @@ int init_events_statements_history_long(size_t events_statements_history_long_si
/** Cleanup table EVENTS_STATEMENTS_HISTORY_LONG. */
void cleanup_events_statements_history_long(void)
{
- pfs_free(events_statements_history_long_array);
- pfs_free(h_long_stmts_digest_token_array);
+ PFS_FREE_ARRAY(& builtin_memory_statements_history_long,
+ events_statements_history_long_size,
+ sizeof(PFS_events_statements),
+ events_statements_history_long_array);
+
+ PFS_FREE_ARRAY(& builtin_memory_statements_history_long_tokens,
+ events_statements_history_long_size,
+ (pfs_max_digest_length * sizeof(unsigned char)),
+ h_long_stmts_digest_token_array);
+
+ PFS_FREE_ARRAY(& builtin_memory_statements_history_long_sqltext,
+ events_statements_history_long_size,
+ (pfs_max_sqltext * sizeof(char)),
+ h_long_stmts_text_array);
+
events_statements_history_long_array= NULL;
h_long_stmts_digest_token_array= NULL;
+ h_long_stmts_text_array= NULL;
}
static inline void copy_events_statements(PFS_events_statements *dest,
- const PFS_events_statements *source)
+ const PFS_events_statements *source)
{
- /* Copy all attributes except DIGEST */
- memcpy(dest, source, my_offsetof(PFS_events_statements, m_digest_storage));
+ /* Copy all attributes except SQL TEXT and DIGEST */
+ memcpy(dest, source, my_offsetof(PFS_events_statements, m_sqltext));
+
+ /* Copy SQL TEXT */
+ int sqltext_length= source->m_sqltext_length;
+
+ if (sqltext_length > 0)
+ {
+ memcpy(dest->m_sqltext, source->m_sqltext, sqltext_length);
+ dest->m_sqltext_length= sqltext_length;
+ }
+ else
+ {
+ dest->m_sqltext_length= 0;
+ }
/* Copy DIGEST */
dest->m_digest_storage.copy(& source->m_digest_storage);
@@ -163,7 +214,7 @@ void insert_events_statements_history_long(PFS_events_statements *statement)
DBUG_ASSERT(events_statements_history_long_array != NULL);
- uint index= PFS_atomic::add_u32(&events_statements_history_long_index, 1);
+ uint index= PFS_atomic::add_u32(&events_statements_history_long_index.m_u32, 1);
index= index % events_statements_history_long_size;
if (index == 0)
@@ -173,44 +224,42 @@ void insert_events_statements_history_long(PFS_events_statements *statement)
copy_events_statements(&events_statements_history_long_array[index], statement);
}
+static void fct_reset_events_statements_current(PFS_thread *pfs_thread)
+{
+ PFS_events_statements *pfs_stmt= & pfs_thread->m_statement_stack[0];
+ PFS_events_statements *pfs_stmt_last= pfs_stmt + statement_stack_max;
+
+ for ( ; pfs_stmt < pfs_stmt_last; pfs_stmt++)
+ pfs_stmt->m_class= NULL;
+}
+
/** Reset table EVENTS_STATEMENTS_CURRENT data. */
void reset_events_statements_current(void)
{
- PFS_thread *pfs_thread= thread_array;
- PFS_thread *pfs_thread_last= thread_array + thread_max;
+ global_thread_container.apply_all(fct_reset_events_statements_current);
+}
- for ( ; pfs_thread < pfs_thread_last; pfs_thread++)
- {
- PFS_events_statements *pfs_stmt= & pfs_thread->m_statement_stack[0];
- PFS_events_statements *pfs_stmt_last= pfs_stmt + statement_stack_max;
+static void fct_reset_events_statements_history(PFS_thread *pfs_thread)
+{
+ PFS_events_statements *pfs= pfs_thread->m_statements_history;
+ PFS_events_statements *pfs_last= pfs + events_statements_history_per_thread;
- for ( ; pfs_stmt < pfs_stmt_last; pfs_stmt++)
- pfs_stmt->m_class= NULL;
- }
+ pfs_thread->m_statements_history_index= 0;
+ pfs_thread->m_statements_history_full= false;
+ for ( ; pfs < pfs_last; pfs++)
+ pfs->m_class= NULL;
}
/** Reset table EVENTS_STATEMENTS_HISTORY data. */
void reset_events_statements_history(void)
{
- PFS_thread *pfs_thread= thread_array;
- PFS_thread *pfs_thread_last= thread_array + thread_max;
-
- for ( ; pfs_thread < pfs_thread_last; pfs_thread++)
- {
- PFS_events_statements *pfs= pfs_thread->m_statements_history;
- PFS_events_statements *pfs_last= pfs + events_statements_history_per_thread;
-
- pfs_thread->m_statements_history_index= 0;
- pfs_thread->m_statements_history_full= false;
- for ( ; pfs < pfs_last; pfs++)
- pfs->m_class= NULL;
- }
+ global_thread_container.apply_all(fct_reset_events_statements_history);
}
/** Reset table EVENTS_STATEMENTS_HISTORY_LONG data. */
void reset_events_statements_history_long(void)
{
- PFS_atomic::store_u32(&events_statements_history_long_index, 0);
+ PFS_atomic::store_u32(&events_statements_history_long_index.m_u32, 0);
events_statements_history_long_full= false;
PFS_events_statements *pfs= events_statements_history_long_array;
@@ -219,70 +268,53 @@ void reset_events_statements_history_long(void)
pfs->m_class= NULL;
}
+static void fct_reset_events_statements_by_thread(PFS_thread *thread)
+{
+ PFS_account *account= sanitize_account(thread->m_account);
+ PFS_user *user= sanitize_user(thread->m_user);
+ PFS_host *host= sanitize_host(thread->m_host);
+ aggregate_thread_statements(thread, account, user, host);
+}
+
/** Reset table EVENTS_STATEMENTS_SUMMARY_BY_THREAD_BY_EVENT_NAME data. */
void reset_events_statements_by_thread()
{
- PFS_thread *thread= thread_array;
- PFS_thread *thread_last= thread_array + thread_max;
- PFS_account *account;
- PFS_user *user;
- PFS_host *host;
+ global_thread_container.apply(fct_reset_events_statements_by_thread);
+}
- for ( ; thread < thread_last; thread++)
- {
- if (thread->m_lock.is_populated())
- {
- account= sanitize_account(thread->m_account);
- user= sanitize_user(thread->m_user);
- host= sanitize_host(thread->m_host);
- aggregate_thread_statements(thread, account, user, host);
- }
- }
+static void fct_reset_events_statements_by_account(PFS_account *pfs)
+{
+ PFS_user *user= sanitize_user(pfs->m_user);
+ PFS_host *host= sanitize_host(pfs->m_host);
+ pfs->aggregate_statements(user, host);
}
/** Reset table EVENTS_STATEMENTS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME data. */
void reset_events_statements_by_account()
{
- PFS_account *pfs= account_array;
- PFS_account *pfs_last= account_array + account_max;
- PFS_user *user;
- PFS_host *host;
+ global_account_container.apply(fct_reset_events_statements_by_account);
+}
- for ( ; pfs < pfs_last; pfs++)
- {
- if (pfs->m_lock.is_populated())
- {
- user= sanitize_user(pfs->m_user);
- host= sanitize_host(pfs->m_host);
- pfs->aggregate_statements(user, host);
- }
- }
+static void fct_reset_events_statements_by_user(PFS_user *pfs)
+{
+ pfs->aggregate_statements();
}
/** Reset table EVENTS_STATEMENTS_SUMMARY_BY_USER_BY_EVENT_NAME data. */
void reset_events_statements_by_user()
{
- PFS_user *pfs= user_array;
- PFS_user *pfs_last= user_array + user_max;
+ global_user_container.apply(fct_reset_events_statements_by_user);
+}
- for ( ; pfs < pfs_last; pfs++)
- {
- if (pfs->m_lock.is_populated())
- pfs->aggregate_statements();
- }
+static void fct_reset_events_statements_by_host(PFS_host *pfs)
+{
+ pfs->aggregate_statements();
}
/** Reset table EVENTS_STATEMENTS_SUMMARY_BY_HOST_BY_EVENT_NAME data. */
void reset_events_statements_by_host()
{
- PFS_host *pfs= host_array;
- PFS_host *pfs_last= host_array + host_max;
-
- for ( ; pfs < pfs_last; pfs++)
- {
- if (pfs->m_lock.is_populated())
- pfs->aggregate_statements();
- }
+ global_host_container.apply(fct_reset_events_statements_by_host);
}
/** Reset table EVENTS_STATEMENTS_GLOBAL_BY_EVENT_NAME data. */
diff --git a/storage/perfschema/pfs_events_statements.h b/storage/perfschema/pfs_events_statements.h
index e47e2e79280..8b24a9e75c8 100644
--- a/storage/perfschema/pfs_events_statements.h
+++ b/storage/perfschema/pfs_events_statements.h
@@ -40,18 +40,20 @@ struct PFS_host;
/** A statement record. */
struct PFS_events_statements : public PFS_events
{
+ enum_object_type m_sp_type;
+ char m_schema_name[NAME_LEN];
+ uint m_schema_name_length;
+ char m_object_name[NAME_LEN];
+ uint m_object_name_length;
+
/** Database name. */
char m_current_schema_name[NAME_LEN];
/** Length of @c m_current_schema_name. */
uint m_current_schema_name_length;
- /** SQL_TEXT */
- char m_sqltext[COL_INFO_SIZE];
- /** Length of @ m_info. */
- uint m_sqltext_length;
/** Locked time. */
ulonglong m_lock_time;
-
+
/** Diagnostics area, message text. */
char m_message_text[MYSQL_ERRMSG_SIZE+1];
/** Diagnostics area, error number. */
@@ -102,6 +104,14 @@ struct PFS_events_statements : public PFS_events
uint m_sqltext_cs_number;
/**
+ SQL_TEXT.
+ This pointer is immutable,
+ and always point to pre allocated memory.
+ */
+ char *m_sqltext;
+ /** Length of @ m_info. */
+ uint m_sqltext_length;
+ /**
Statement digest.
This underlying token array storage pointer is immutable,
and always point to pre allocated memory.
@@ -112,12 +122,14 @@ struct PFS_events_statements : public PFS_events
void insert_events_statements_history(PFS_thread *thread, PFS_events_statements *statement);
void insert_events_statements_history_long(PFS_events_statements *statement);
+extern ulong nested_statement_lost;
+
extern bool flag_events_statements_current;
extern bool flag_events_statements_history;
extern bool flag_events_statements_history_long;
extern bool events_statements_history_long_full;
-extern volatile uint32 events_statements_history_long_index;
+extern PFS_ALIGNED PFS_cacheline_uint32 events_statements_history_long_index;
extern PFS_events_statements *events_statements_history_long_array;
extern size_t events_statements_history_long_size;
diff --git a/storage/perfschema/pfs_events_transactions.cc b/storage/perfschema/pfs_events_transactions.cc
new file mode 100644
index 00000000000..884234913e8
--- /dev/null
+++ b/storage/perfschema/pfs_events_transactions.cc
@@ -0,0 +1,267 @@
+/* Copyright (c) 2013, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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_events_transactions.cc
+ Events transactions data structures (implementation).
+*/
+
+#include "my_global.h"
+#include "my_sys.h"
+#include "pfs_global.h"
+#include "pfs_instr_class.h"
+#include "pfs_instr.h"
+#include "pfs_account.h"
+#include "pfs_host.h"
+#include "pfs_user.h"
+#include "pfs_events_transactions.h"
+#include "pfs_atomic.h"
+#include "pfs_buffer_container.h"
+#include "pfs_builtin_memory.h"
+#include "m_string.h"
+
+PFS_ALIGNED ulong events_transactions_history_long_size= 0;
+/** Consumer flag for table EVENTS_TRANSACTIONS_CURRENT. */
+PFS_ALIGNED bool flag_events_transactions_current= false;
+/** Consumer flag for table EVENTS_TRANSACTIONS_HISTORY. */
+PFS_ALIGNED bool flag_events_transactions_history= false;
+/** Consumer flag for table EVENTS_TRANSACTIONS_HISTORY_LONG. */
+PFS_ALIGNED bool flag_events_transactions_history_long= false;
+
+/** True if EVENTS_TRANSACTIONS_HISTORY_LONG circular buffer is full. */
+PFS_ALIGNED bool events_transactions_history_long_full= false;
+/** Index in EVENTS_TRANSACTIONS_HISTORY_LONG circular buffer. */
+PFS_ALIGNED PFS_cacheline_uint32 events_transactions_history_long_index;
+/** EVENTS_TRANSACTIONS_HISTORY_LONG circular buffer. */
+PFS_ALIGNED PFS_events_transactions *events_transactions_history_long_array= NULL;
+
+/**
+ Initialize table EVENTS_TRANSACTIONS_HISTORY_LONG.
+ @param events_transactions_history_long_sizing table sizing
+*/
+int init_events_transactions_history_long(uint events_transactions_history_long_sizing)
+{
+ events_transactions_history_long_size= events_transactions_history_long_sizing;
+ events_transactions_history_long_full= false;
+ PFS_atomic::store_u32(&events_transactions_history_long_index.m_u32, 0);
+
+ if (events_transactions_history_long_size == 0)
+ return 0;
+
+ events_transactions_history_long_array=
+ PFS_MALLOC_ARRAY(& builtin_memory_transactions_history_long,
+ events_transactions_history_long_size,
+ sizeof(PFS_events_transactions), PFS_events_transactions,
+ MYF(MY_ZEROFILL));
+
+ return (events_transactions_history_long_array ? 0 : 1);
+}
+
+/** Cleanup table EVENTS_TRANSACTIONS_HISTORY_LONG. */
+void cleanup_events_transactions_history_long(void)
+{
+ PFS_FREE_ARRAY(& builtin_memory_transactions_history_long,
+ events_transactions_history_long_size, sizeof(PFS_events_transactions),
+ events_transactions_history_long_array);
+ events_transactions_history_long_array= NULL;
+}
+
+static inline void copy_events_transactions(PFS_events_transactions *dest,
+ const PFS_events_transactions *source)
+{
+ memcpy(dest, source, sizeof(PFS_events_transactions));
+}
+
+/**
+ Insert a transaction record in table EVENTS_TRANSACTIONS_HISTORY.
+ @param thread thread that executed the wait
+ @param transaction record to insert
+*/
+void insert_events_transactions_history(PFS_thread *thread, PFS_events_transactions *transaction)
+{
+ if (unlikely(events_transactions_history_per_thread == 0))
+ return;
+
+ DBUG_ASSERT(thread->m_transactions_history != NULL);
+
+ uint index= thread->m_transactions_history_index;
+
+ /*
+ A concurrent thread executing TRUNCATE TABLE EVENTS_TRANSACTIONS_CURRENT
+ could alter the data that this thread is inserting,
+ causing a potential race condition.
+ We are not testing for this and insert a possibly empty record,
+ to make this thread (the writer) faster.
+ This is ok, the readers of m_transactions_history will filter this out.
+ */
+ copy_events_transactions(&thread->m_transactions_history[index], transaction);
+
+ index++;
+ if (index >= events_transactions_history_per_thread)
+ {
+ index= 0;
+ thread->m_transactions_history_full= true;
+ }
+ thread->m_transactions_history_index= index;
+}
+
+/**
+ Insert a transaction record in table EVENTS_TRANSACTIONS_HISTORY_LONG.
+ @param transaction record to insert
+*/
+void insert_events_transactions_history_long(PFS_events_transactions *transaction)
+{
+ if (unlikely(events_transactions_history_long_size == 0))
+ return ;
+
+ DBUG_ASSERT(events_transactions_history_long_array != NULL);
+
+ uint index= PFS_atomic::add_u32(&events_transactions_history_long_index.m_u32, 1);
+
+ index= index % events_transactions_history_long_size;
+ if (index == 0)
+ events_transactions_history_long_full= true;
+
+ /* See related comment in insert_events_transactions_history. */
+ copy_events_transactions(&events_transactions_history_long_array[index], transaction);
+}
+
+static void fct_reset_events_transactions_current(PFS_thread *pfs)
+{
+ pfs->m_transaction_current.m_class= NULL;
+}
+
+/** Reset table EVENTS_TRANSACTIONS_CURRENT data. */
+void reset_events_transactions_current(void)
+{
+ global_thread_container.apply_all(fct_reset_events_transactions_current);
+}
+
+static void fct_reset_events_transactions_history(PFS_thread *pfs_thread)
+{
+ PFS_events_transactions *pfs= pfs_thread->m_transactions_history;
+ PFS_events_transactions *pfs_last= pfs + events_transactions_history_per_thread;
+
+ pfs_thread->m_transactions_history_index= 0;
+ pfs_thread->m_transactions_history_full= false;
+ for ( ; pfs < pfs_last; pfs++)
+ pfs->m_class= NULL;
+}
+
+/** Reset table EVENTS_TRANSACTIONS_HISTORY data. */
+void reset_events_transactions_history(void)
+{
+ global_thread_container.apply_all(fct_reset_events_transactions_history);
+}
+
+/** Reset table EVENTS_TRANSACTIONS_HISTORY_LONG data. */
+void reset_events_transactions_history_long(void)
+{
+ PFS_atomic::store_u32(&events_transactions_history_long_index.m_u32, 0);
+ events_transactions_history_long_full= false;
+
+ PFS_events_transactions *pfs= events_transactions_history_long_array;
+ PFS_events_transactions *pfs_last= pfs + events_transactions_history_long_size;
+ for ( ; pfs < pfs_last; pfs++)
+ pfs->m_class= NULL;
+}
+
+static void fct_reset_events_transactions_by_thread(PFS_thread *thread)
+{
+ PFS_account *account= sanitize_account(thread->m_account);
+ PFS_user *user= sanitize_user(thread->m_user);
+ PFS_host *host= sanitize_host(thread->m_host);
+ aggregate_thread_transactions(thread, account, user, host);
+}
+
+/** Reset table EVENTS_TRANSACTIONS_SUMMARY_BY_THREAD_BY_EVENT_NAME data. */
+void reset_events_transactions_by_thread()
+{
+ global_thread_container.apply(fct_reset_events_transactions_by_thread);
+}
+
+static void fct_reset_events_transactions_by_account(PFS_account *pfs)
+{
+ PFS_user *user= sanitize_user(pfs->m_user);
+ PFS_host *host= sanitize_host(pfs->m_host);
+ pfs->aggregate_transactions(user, host);
+}
+
+/** Reset table EVENTS_TRANSACTIONS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME data. */
+void reset_events_transactions_by_account()
+{
+ global_account_container.apply(fct_reset_events_transactions_by_account);
+}
+
+static void fct_reset_events_transactions_by_user(PFS_user *pfs)
+{
+ pfs->aggregate_transactions();
+}
+
+/** Reset table EVENTS_TRANSACTIONS_SUMMARY_BY_USER_BY_EVENT_NAME data. */
+void reset_events_transactions_by_user()
+{
+ global_user_container.apply(fct_reset_events_transactions_by_user);
+}
+
+static void fct_reset_events_transactions_by_host(PFS_host *pfs)
+{
+ pfs->aggregate_transactions();
+}
+
+/** Reset table EVENTS_TRANSACTIONS_SUMMARY_BY_HOST_BY_EVENT_NAME data. */
+void reset_events_transactions_by_host()
+{
+ global_host_container.apply(fct_reset_events_transactions_by_host);
+}
+
+/** Reset table EVENTS_TRANSACTIONS_GLOBAL_BY_EVENT_NAME data. */
+void reset_events_transactions_global()
+{
+ global_transaction_stat.reset();
+}
+
+/**
+ Check if the XID consists of printable characters, ASCII 32 - 127.
+ @param xid XID structure
+ @param offset offset into XID.data[]
+ @param length number of bytes to process
+ @return true if all bytes are in printable range
+*/
+bool xid_printable(PSI_xid *xid, size_t offset, size_t length)
+{
+ if (xid->is_null())
+ return false;
+
+ DBUG_ASSERT(offset + length <= MYSQL_XIDDATASIZE);
+
+ unsigned char *c= (unsigned char*)&xid->data + offset;
+
+ for (size_t i= 0; i < length; i++, c++)
+ {
+ if(*c < 32 || *c > 127)
+ return false;
+ }
+
+ return true;
+}
+
diff --git a/storage/perfschema/pfs_events_transactions.h b/storage/perfschema/pfs_events_transactions.h
new file mode 100644
index 00000000000..dc4fd8b0b60
--- /dev/null
+++ b/storage/perfschema/pfs_events_transactions.h
@@ -0,0 +1,132 @@
+/* Copyright (c) 2013, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#ifndef PFS_EVENTS_TRANSACTIONS_H
+#define PFS_EVENTS_TRANSACTIONS_H
+
+/**
+ @file storage/perfschema/pfs_events_transactions.h
+ Events transactions data structures (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_events.h"
+#include "rpl_gtid.h"
+#include "mysql/plugin.h" /* MYSQL_XIDDATASIZE */
+#include "my_thread.h"
+
+struct PFS_thread;
+struct PFS_account;
+struct PFS_user;
+struct PFS_host;
+
+/**
+ struct PSI_xid is binary compatible with the XID structure as
+ in the X/Open CAE Specification, Distributed Transaction Processing:
+ The XA Specification, X/Open Company Ltd., 1991.
+ http://www.opengroup.org/bookstore/catalog/c193.htm
+
+ A value of -1 in formatID means that the XID is null.
+ Max length for bqual and gtrid is 64 bytes each.
+
+ @see XID in sql/handler.h
+ @see MYSQL_XID in mysql/plugin.h
+*/
+struct PSI_xid
+{
+ /** Format identifier. */
+ long formatID;
+ /** GTRID length, value 1-64. */
+ long gtrid_length;
+ /** BQUAL length, value 1-64. */
+ long bqual_length;
+ /** XID raw data, not \0-terminated */
+ char data[MYSQL_XIDDATASIZE];
+
+ PSI_xid() {null();}
+ bool is_null() { return formatID == -1; }
+ void null() { formatID= -1; gtrid_length= 0; bqual_length= 0;}
+};
+typedef struct PSI_xid PSI_xid;
+
+/** A transaction record. */
+struct PFS_events_transactions : public PFS_events
+{
+ /** Source identifier, mapped from internal format. */
+ //rpl_sid m_sid;
+ /** InnoDB transaction ID. */
+ ulonglong m_trxid;
+ /** Status */
+ enum_transaction_state m_state;
+ /** Global Transaction ID specifier. */
+ Gtid_specification m_gtid_spec;
+ /** True if XA transaction. */
+ my_bool m_xa;
+ /** XA transaction ID. */
+ PSI_xid m_xid;
+ /** XA status */
+ enum_xa_transaction_state m_xa_state;
+ /** Transaction isolation level. */
+ enum_isolation_level m_isolation_level;
+ /** True if read-only transaction, otherwise read-write. */
+ my_bool m_read_only;
+ /** True if autocommit transaction. */
+ my_bool m_autocommit;
+ /** Total number of savepoints. */
+ ulonglong m_savepoint_count;
+ /** Number of rollback_to_savepoint. */
+ ulonglong m_rollback_to_savepoint_count;
+ /** Number of release_savepoint. */
+ ulonglong m_release_savepoint_count;
+};
+
+bool xid_printable(PSI_xid *xid, size_t offset, size_t length);
+
+void insert_events_transactions_history(PFS_thread *thread, PFS_events_transactions *transaction);
+void insert_events_transactions_history_long(PFS_events_transactions *transaction);
+
+extern bool flag_events_transactions_current;
+extern bool flag_events_transactions_history;
+extern bool flag_events_transactions_history_long;
+
+extern bool events_transactions_history_long_full;
+extern PFS_cacheline_uint32 events_transactions_history_long_index;
+extern PFS_events_transactions *events_transactions_history_long_array;
+extern ulong events_transactions_history_long_size;
+
+int init_events_transactions_history_long(uint events_transactions_history_long_sizing);
+void cleanup_events_transactions_history_long();
+
+void reset_events_transactions_current();
+void reset_events_transactions_history();
+void reset_events_transactions_history_long();
+void reset_events_transactions_by_thread();
+void reset_events_transactions_by_account();
+void reset_events_transactions_by_user();
+void reset_events_transactions_by_host();
+void reset_events_transactions_global();
+void aggregate_account_transactions(PFS_account *account);
+void aggregate_user_transactions(PFS_user *user);
+void aggregate_host_transactions(PFS_host *host);
+
+#endif
+
diff --git a/storage/perfschema/pfs_events_waits.cc b/storage/perfschema/pfs_events_waits.cc
index c3961461f34..b51ee5fd2c8 100644
--- a/storage/perfschema/pfs_events_waits.cc
+++ b/storage/perfschema/pfs_events_waits.cc
@@ -35,26 +35,28 @@
#include "pfs_account.h"
#include "pfs_events_waits.h"
#include "pfs_atomic.h"
+#include "pfs_buffer_container.h"
+#include "pfs_builtin_memory.h"
#include "m_string.h"
-ulong events_waits_history_long_size= 0;
+PFS_ALIGNED ulong events_waits_history_long_size= 0;
/** Consumer flag for table EVENTS_WAITS_CURRENT. */
-bool flag_events_waits_current= false;
+PFS_ALIGNED bool flag_events_waits_current= false;
/** Consumer flag for table EVENTS_WAITS_HISTORY. */
-bool flag_events_waits_history= false;
+PFS_ALIGNED bool flag_events_waits_history= false;
/** Consumer flag for table EVENTS_WAITS_HISTORY_LONG. */
-bool flag_events_waits_history_long= false;
+PFS_ALIGNED bool flag_events_waits_history_long= false;
/** Consumer flag for the global instrumentation. */
-bool flag_global_instrumentation= false;
+PFS_ALIGNED bool flag_global_instrumentation= false;
/** Consumer flag for the per thread instrumentation. */
-bool flag_thread_instrumentation= false;
+PFS_ALIGNED bool flag_thread_instrumentation= false;
/** True if EVENTS_WAITS_HISTORY_LONG circular buffer is full. */
-bool events_waits_history_long_full= false;
+PFS_ALIGNED bool events_waits_history_long_full= false;
/** Index in EVENTS_WAITS_HISTORY_LONG circular buffer. */
-volatile uint32 events_waits_history_long_index= 0;
+PFS_ALIGNED PFS_cacheline_uint32 events_waits_history_long_index;
/** EVENTS_WAITS_HISTORY_LONG circular buffer. */
-PFS_events_waits *events_waits_history_long_array= NULL;
+PFS_ALIGNED PFS_events_waits *events_waits_history_long_array= NULL;
/**
Initialize table EVENTS_WAITS_HISTORY_LONG.
@@ -64,14 +66,16 @@ int init_events_waits_history_long(uint events_waits_history_long_sizing)
{
events_waits_history_long_size= events_waits_history_long_sizing;
events_waits_history_long_full= false;
- PFS_atomic::store_u32(&events_waits_history_long_index, 0);
+ PFS_atomic::store_u32(&events_waits_history_long_index.m_u32, 0);
if (events_waits_history_long_size == 0)
return 0;
events_waits_history_long_array=
- PFS_MALLOC_ARRAY(events_waits_history_long_size, sizeof(PFS_events_waits),
- PFS_events_waits, MYF(MY_ZEROFILL));
+ PFS_MALLOC_ARRAY(& builtin_memory_waits_history_long,
+ events_waits_history_long_size,
+ sizeof(PFS_events_waits), PFS_events_waits,
+ MYF(MY_ZEROFILL));
return (events_waits_history_long_array ? 0 : 1);
}
@@ -79,7 +83,9 @@ int init_events_waits_history_long(uint events_waits_history_long_sizing)
/** Cleanup table EVENTS_WAITS_HISTORY_LONG. */
void cleanup_events_waits_history_long(void)
{
- pfs_free(events_waits_history_long_array);
+ PFS_FREE_ARRAY(& builtin_memory_waits_history_long,
+ events_waits_history_long_size, sizeof(PFS_events_waits),
+ events_waits_history_long_array);
events_waits_history_long_array= NULL;
}
@@ -129,7 +135,7 @@ void insert_events_waits_history_long(PFS_events_waits *wait)
if (unlikely(events_waits_history_long_size == 0))
return;
- uint index= PFS_atomic::add_u32(&events_waits_history_long_index, 1);
+ uint index= PFS_atomic::add_u32(&events_waits_history_long_index.m_u32, 1);
index= index % events_waits_history_long_size;
if (index == 0)
@@ -139,44 +145,43 @@ void insert_events_waits_history_long(PFS_events_waits *wait)
copy_events_waits(&events_waits_history_long_array[index], wait);
}
+static void fct_reset_events_waits_current(PFS_thread *pfs_thread)
+{
+ PFS_events_waits *pfs_wait= pfs_thread->m_events_waits_stack;
+ PFS_events_waits *pfs_wait_last= pfs_wait + WAIT_STACK_SIZE;
+
+ for ( ; pfs_wait < pfs_wait_last; pfs_wait++)
+ pfs_wait->m_wait_class= NO_WAIT_CLASS;
+}
+
+
/** Reset table EVENTS_WAITS_CURRENT data. */
void reset_events_waits_current(void)
{
- PFS_thread *pfs_thread= thread_array;
- PFS_thread *pfs_thread_last= thread_array + thread_max;
+ global_thread_container.apply_all(fct_reset_events_waits_current);
+}
- for ( ; pfs_thread < pfs_thread_last; pfs_thread++)
- {
- PFS_events_waits *pfs_wait= pfs_thread->m_events_waits_stack;
- PFS_events_waits *pfs_wait_last= pfs_wait + WAIT_STACK_SIZE;
+static void fct_reset_events_waits_history(PFS_thread *pfs_thread)
+{
+ PFS_events_waits *wait= pfs_thread->m_waits_history;
+ PFS_events_waits *wait_last= wait + events_waits_history_per_thread;
- for ( ; pfs_wait < pfs_wait_last; pfs_wait++)
- pfs_wait->m_wait_class= NO_WAIT_CLASS;
- }
+ pfs_thread->m_waits_history_index= 0;
+ pfs_thread->m_waits_history_full= false;
+ for ( ; wait < wait_last; wait++)
+ wait->m_wait_class= NO_WAIT_CLASS;
}
/** Reset table EVENTS_WAITS_HISTORY data. */
void reset_events_waits_history(void)
{
- PFS_thread *pfs_thread= thread_array;
- PFS_thread *pfs_thread_last= thread_array + thread_max;
-
- for ( ; pfs_thread < pfs_thread_last; pfs_thread++)
- {
- PFS_events_waits *wait= pfs_thread->m_waits_history;
- PFS_events_waits *wait_last= wait + events_waits_history_per_thread;
-
- pfs_thread->m_waits_history_index= 0;
- pfs_thread->m_waits_history_full= false;
- for ( ; wait < wait_last; wait++)
- wait->m_wait_class= NO_WAIT_CLASS;
- }
+ global_thread_container.apply_all(fct_reset_events_waits_history);
}
/** Reset table EVENTS_WAITS_HISTORY_LONG data. */
void reset_events_waits_history_long(void)
{
- PFS_atomic::store_u32(&events_waits_history_long_index, 0);
+ PFS_atomic::store_u32(&events_waits_history_long_index.m_u32, 0);
events_waits_history_long_full= false;
PFS_events_waits *wait= events_waits_history_long_array;
@@ -185,141 +190,112 @@ void reset_events_waits_history_long(void)
wait->m_wait_class= NO_WAIT_CLASS;
}
+static void fct_reset_events_waits_by_thread(PFS_thread *thread)
+{
+ PFS_account *account= sanitize_account(thread->m_account);
+ PFS_user *user= sanitize_user(thread->m_user);
+ PFS_host *host= sanitize_host(thread->m_host);
+ aggregate_thread_waits(thread, account, user, host);
+}
+
/** Reset table EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME data. */
void reset_events_waits_by_thread()
{
- PFS_thread *thread= thread_array;
- PFS_thread *thread_last= thread_array + thread_max;
- PFS_account *account;
- PFS_user *user;
- PFS_host *host;
+ global_thread_container.apply(fct_reset_events_waits_by_thread);
+}
- for ( ; thread < thread_last; thread++)
- {
- if (thread->m_lock.is_populated())
- {
- account= sanitize_account(thread->m_account);
- user= sanitize_user(thread->m_user);
- host= sanitize_host(thread->m_host);
- aggregate_thread_waits(thread, account, user, host);
- }
- }
+static void fct_reset_events_waits_by_account(PFS_account *pfs)
+{
+ PFS_user *user= sanitize_user(pfs->m_user);
+ PFS_host *host= sanitize_host(pfs->m_host);
+ pfs->aggregate_waits(user, host);
}
/** Reset table EVENTS_WAITS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME data. */
void reset_events_waits_by_account()
{
- PFS_account *pfs= account_array;
- PFS_account *pfs_last= account_array + account_max;
- PFS_user *user;
- PFS_host *host;
+ global_account_container.apply(fct_reset_events_waits_by_account);
+}
- for ( ; pfs < pfs_last; pfs++)
- {
- if (pfs->m_lock.is_populated())
- {
- user= sanitize_user(pfs->m_user);
- host= sanitize_host(pfs->m_host);
- pfs->aggregate_waits(user, host);
- }
- }
+static void fct_reset_events_waits_by_user(PFS_user *pfs)
+{
+ pfs->aggregate_waits();
}
/** Reset table EVENTS_WAITS_SUMMARY_BY_USER_BY_EVENT_NAME data. */
void reset_events_waits_by_user()
{
- PFS_user *pfs= user_array;
- PFS_user *pfs_last= user_array + user_max;
+ global_user_container.apply(fct_reset_events_waits_by_user);
+}
- for ( ; pfs < pfs_last; pfs++)
- {
- if (pfs->m_lock.is_populated())
- pfs->aggregate_waits();
- }
+static void fct_reset_events_waits_by_host(PFS_host *pfs)
+{
+ pfs->aggregate_waits();
}
/** Reset table EVENTS_WAITS_SUMMARY_BY_HOST_BY_EVENT_NAME data. */
void reset_events_waits_by_host()
{
- PFS_host *pfs= host_array;
- PFS_host *pfs_last= host_array + host_max;
+ global_host_container.apply(fct_reset_events_waits_by_host);
+}
- for ( ; pfs < pfs_last; pfs++)
- {
- if (pfs->m_lock.is_populated())
- pfs->aggregate_waits();
- }
+static void fct_reset_table_waits_by_table(PFS_table_share *pfs)
+{
+ pfs->aggregate();
}
void reset_table_waits_by_table()
{
- PFS_table_share *pfs= table_share_array;
- PFS_table_share *pfs_last= pfs + table_share_max;
+ global_table_share_container.apply(fct_reset_table_waits_by_table);
+}
- for ( ; pfs < pfs_last; pfs++)
- {
- if (pfs->m_lock.is_populated())
- pfs->aggregate();
- }
+static void fct_reset_table_io_waits_by_table(PFS_table_share *pfs)
+{
+ pfs->aggregate_io();
}
void reset_table_io_waits_by_table()
{
- PFS_table_share *pfs= table_share_array;
- PFS_table_share *pfs_last= pfs + table_share_max;
+ global_table_share_container.apply(fct_reset_table_io_waits_by_table);
+}
- for ( ; pfs < pfs_last; pfs++)
- {
- if (pfs->m_lock.is_populated())
- pfs->aggregate_io();
- }
+static void fct_reset_table_lock_waits_by_table(PFS_table_share *pfs)
+{
+ pfs->aggregate_lock();
}
void reset_table_lock_waits_by_table()
{
- PFS_table_share *pfs= table_share_array;
- PFS_table_share *pfs_last= pfs + table_share_max;
+ global_table_share_container.apply(fct_reset_table_lock_waits_by_table);
+}
- for ( ; pfs < pfs_last; pfs++)
- {
- if (pfs->m_lock.is_populated())
- pfs->aggregate_lock();
- }
+void fct_reset_table_waits_by_table_handle(PFS_table *pfs)
+{
+ pfs->sanitized_aggregate();
}
void reset_table_waits_by_table_handle()
{
- PFS_table *pfs= table_array;
- PFS_table *pfs_last= pfs + table_max;
+ global_table_container.apply(fct_reset_table_waits_by_table_handle);
+}
- for ( ; pfs < pfs_last; pfs++)
- {
- if (pfs->m_lock.is_populated())
- pfs->sanitized_aggregate();
- }
+void fct_reset_table_io_waits_by_table_handle(PFS_table *pfs)
+{
+ pfs->sanitized_aggregate_io();
}
void reset_table_io_waits_by_table_handle()
{
- PFS_table *pfs= table_array;
- PFS_table *pfs_last= pfs + table_max;
+ global_table_container.apply(fct_reset_table_io_waits_by_table_handle);
+}
- for ( ; pfs < pfs_last; pfs++)
- {
- if (pfs->m_lock.is_populated())
- pfs->sanitized_aggregate_io();
- }
+void fct_reset_table_lock_waits_by_table_handle(PFS_table *pfs)
+{
+ pfs->sanitized_aggregate_lock();
}
void reset_table_lock_waits_by_table_handle()
{
- PFS_table *pfs= table_array;
- PFS_table *pfs_last= pfs + table_max;
-
- for ( ; pfs < pfs_last; pfs++)
- {
- if (pfs->m_lock.is_populated())
- pfs->sanitized_aggregate_lock();
- }
+ global_table_container.apply(fct_reset_table_lock_waits_by_table_handle);
}
diff --git a/storage/perfschema/pfs_events_waits.h b/storage/perfschema/pfs_events_waits.h
index 702f7e3ce07..570e1c9b71e 100644
--- a/storage/perfschema/pfs_events_waits.h
+++ b/storage/perfschema/pfs_events_waits.h
@@ -1,5 +1,5 @@
-/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- Copyright (c) 2017, MariaDB Corporation.
+/* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2017, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License, version 2.0,
@@ -45,6 +45,7 @@ struct PFS_table_share;
struct PFS_account;
struct PFS_user;
struct PFS_host;
+struct PFS_metadata_lock;
/** Class of a wait event. */
enum events_waits_class
@@ -56,29 +57,13 @@ enum events_waits_class
WAIT_CLASS_TABLE,
WAIT_CLASS_FILE,
WAIT_CLASS_SOCKET,
- WAIT_CLASS_IDLE
+ WAIT_CLASS_IDLE,
+ WAIT_CLASS_METADATA
};
/** A wait event record. */
struct PFS_events_waits : public PFS_events
{
- /** Executing thread. */
- PFS_thread *m_thread;
- /** Table share, for table operations only. */
- PFS_table_share *m_weak_table_share;
- /** File, for file operations only. */
- PFS_file *m_weak_file;
- /** Address in memory of the object instance waited on. */
- const void *m_object_instance_addr;
- /** Socket, for socket operations only. */
- PFS_socket *m_weak_socket;
- /**
- Number of bytes read/written.
- This member is populated for file READ/WRITE operations only.
- */
- size_t m_number_of_bytes;
- /** Flags */
- ulong m_flags;
/**
The type of wait.
Readers:
@@ -93,11 +78,25 @@ struct PFS_events_waits : public PFS_events
events_waits_class m_wait_class;
/** Object type */
enum_object_type m_object_type;
+ /** Table share, for table operations only. */
+ PFS_table_share *m_weak_table_share;
+ /** File, for file operations only. */
+ PFS_file *m_weak_file;
+ /** Socket, for socket operations only. */
+ PFS_socket *m_weak_socket;
+ /** Metadata lock, for mdl operations only. */
+ PFS_metadata_lock *m_weak_metadata_lock;
/** For weak pointers, target object version. */
uint32 m_weak_version;
/** Operation performed. */
enum_operation_type m_operation;
/**
+ Number of bytes/rows read/written.
+ This member is populated for FILE READ/WRITE operations, with a number of bytes.
+ This member is populated for TABLE IO operations, with a number of rows.
+ */
+ size_t m_number_of_bytes;
+ /**
Index used.
This member is populated for TABLE IO operations only.
*/
@@ -124,7 +123,7 @@ extern bool flag_global_instrumentation;
extern bool flag_thread_instrumentation;
extern bool events_waits_history_long_full;
-extern volatile uint32 events_waits_history_long_index;
+extern PFS_ALIGNED PFS_cacheline_uint32 events_waits_history_long_index;
extern PFS_events_waits *events_waits_history_long_array;
extern ulong events_waits_history_long_size;
diff --git a/storage/perfschema/pfs_global.cc b/storage/perfschema/pfs_global.cc
index e1b5e3400ca..26cb693d441 100644
--- a/storage/perfschema/pfs_global.cc
+++ b/storage/perfschema/pfs_global.cc
@@ -1,4 +1,5 @@
-/* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2017, 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, version 2.0,
@@ -27,37 +28,38 @@
#include <my_global.h>
#include "pfs_global.h"
-#include <my_sys.h>
-#include <my_net.h>
-#ifdef HAVE_MALLOC_H
-#include <malloc.h> /* memalign() may be here */
-#endif
+#include "pfs_builtin_memory.h"
+#include "log.h"
+
+#include <stdlib.h>
+#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
-
-#ifdef HAVE_STRING_H
-#include <string.h>
+#ifdef _WIN32
+#include <winsock2.h>
#endif
-
-#ifdef __WIN__
- #include <winsock2.h>
-#else
- #include <arpa/inet.h>
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
#endif
bool pfs_initialized= false;
-size_t pfs_allocated_memory= 0;
/**
Memory allocation for the performance schema.
- The memory used internally in the performance schema implementation
- is allocated once during startup, and considered static thereafter.
+ The memory used internally in the performance schema implementation.
+ It is allocated at startup, or during runtime with scalable buffers.
*/
-void *pfs_malloc(size_t size, myf flags)
+void *pfs_malloc(PFS_builtin_memory_class *klass, size_t size, myf flags)
{
- DBUG_ASSERT(! pfs_initialized);
+ DBUG_ASSERT(klass != NULL);
DBUG_ASSERT(size > 0);
void *ptr= NULL;
@@ -91,13 +93,14 @@ void *pfs_malloc(size_t size, myf flags)
return NULL;
#endif
- pfs_allocated_memory+= size;
+ klass->count_alloc(size);
+
if (flags & MY_ZEROFILL)
memset(ptr, 0, size);
return ptr;
}
-void pfs_free(void *ptr)
+void pfs_free(PFS_builtin_memory_class *klass, size_t size, void *ptr)
{
if (ptr == NULL)
return;
@@ -119,40 +122,58 @@ void pfs_free(void *ptr)
#endif /* HAVE_ALIGNED_MALLOC */
#endif /* HAVE_MEMALIGN */
#endif /* HAVE_POSIX_MEMALIGN */
-}
-void pfs_print_error(const char *format, ...)
-{
- va_list args;
- va_start(args, format);
- /*
- Printing to anything else, like the error log, would generate even more
- recursive calls to the performance schema implementation
- (file io is instrumented), so that could lead to catastrophic results.
- Printing to something safe, and low level: stderr only.
- */
- vfprintf(stderr, format, args);
- va_end(args);
- fflush(stderr);
+ klass->count_free(size);
}
/**
Array allocation for the performance schema.
Checks for overflow of n * size before allocating.
- @param n number of array elements
+ @param klass performance schema memory class
+ @param n number of array elements
@param size element size
@param flags malloc flags
@return pointer to memory on success, else NULL
*/
-void *pfs_malloc_array(size_t n, size_t size, myf flags)
+void *pfs_malloc_array(PFS_builtin_memory_class *klass, size_t n, size_t size, myf flags)
{
+ DBUG_ASSERT(klass != NULL);
DBUG_ASSERT(n > 0);
DBUG_ASSERT(size > 0);
+ void *ptr= NULL;
size_t array_size= n * size;
/* Check for overflow before allocating. */
if (is_overflow(array_size, n, size))
+ {
+ sql_print_warning("Failed to allocate memory for %zu chunks each of size "
+ "%zu for buffer '%s' due to overflow", n, size,
+ klass->m_class.m_name);
return NULL;
- return pfs_malloc(array_size, flags);
+ }
+
+ if(NULL == (ptr= pfs_malloc(klass, array_size, flags)))
+ {
+ sql_print_warning("Failed to allocate %zu bytes for buffer '%s' due to "
+ "out-of-memory", array_size, klass->m_class.m_name);
+ }
+ return ptr;
+}
+
+/**
+ Free array allocated by @sa pfs_malloc_array.
+ @param klass performance schema memory class
+ @param n number of array elements
+ @param size element size
+ @param ptr pointer to memory
+*/
+void pfs_free_array(PFS_builtin_memory_class *klass, size_t n, size_t size, void *ptr)
+{
+ if (ptr == NULL)
+ return;
+ size_t array_size= n * size;
+ /* Overflow should have been detected by pfs_malloc_array. */
+ DBUG_ASSERT(!is_overflow(array_size, n, size));
+ return pfs_free(klass, array_size, ptr);
}
/**
@@ -170,6 +191,22 @@ bool is_overflow(size_t product, size_t n1, size_t n2)
return false;
}
+void pfs_print_error(const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ /*
+ Printing to anything else, like the error log, would generate even more
+ recursive calls to the performance schema implementation
+ (file io is instrumented), so that could lead to catastrophic results.
+ Printing to something safe, and low level: stderr only.
+ */
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fflush(stderr);
+}
+
+
/** Convert raw ip address into readable format. Do not do a reverse DNS lookup. */
uint pfs_get_socket_address(char *host,
@@ -192,7 +229,7 @@ uint pfs_get_socket_address(char *host,
if (host_len < INET_ADDRSTRLEN+1)
return 0;
struct sockaddr_in *sa4= (struct sockaddr_in *)(src_addr);
- #ifdef __WIN__
+ #ifdef _WIN32
/* Older versions of Windows do not support inet_ntop() */
getnameinfo((struct sockaddr *)sa4, sizeof(struct sockaddr_in),
host, host_len, NULL, 0, NI_NUMERICHOST);
@@ -209,7 +246,7 @@ uint pfs_get_socket_address(char *host,
if (host_len < INET6_ADDRSTRLEN+1)
return 0;
struct sockaddr_in6 *sa6= (struct sockaddr_in6 *)(src_addr);
- #ifdef __WIN__
+ #ifdef _WIN32
/* Older versions of Windows do not support inet_ntop() */
getnameinfo((struct sockaddr *)sa6, sizeof(struct sockaddr_in6),
host, host_len, NULL, 0, NI_NUMERICHOST);
@@ -228,4 +265,3 @@ uint pfs_get_socket_address(char *host,
/* Return actual IP address string length */
return ((uint)strlen((const char*)host));
}
-
diff --git a/storage/perfschema/pfs_global.h b/storage/perfschema/pfs_global.h
index 58db39e607d..d26e81adae7 100644
--- a/storage/perfschema/pfs_global.h
+++ b/storage/perfschema/pfs_global.h
@@ -32,7 +32,6 @@
/** True when the performance schema is initialized. */
extern bool pfs_initialized;
-
/** Total memory allocated by the performance schema, in bytes. */
extern size_t pfs_allocated_memory;
@@ -48,23 +47,74 @@ extern size_t pfs_allocated_memory;
#define PFS_ALIGNED
#endif /* HAVE_POSIX_MEMALIGN || HAVE_MEMALIGN || HAVE_ALIGNED_MALLOC */
-void *pfs_malloc(size_t size, myf flags);
+#ifdef CPU_LEVEL1_DCACHE_LINESIZE
+#define PFS_CACHE_LINE_SIZE CPU_LEVEL1_DCACHE_LINESIZE
+#else
+#define PFS_CACHE_LINE_SIZE 128
+#endif
+
+/**
+ A uint32 variable, guaranteed to be alone in a CPU cache line.
+ This is for performance, for variables accessed very frequently.
+*/
+struct PFS_cacheline_uint32
+{
+ uint32 m_u32;
+ char m_full_cache_line[PFS_CACHE_LINE_SIZE - sizeof(uint32)];
+
+ PFS_cacheline_uint32()
+ : m_u32(0)
+ {}
+};
+
+/**
+ A uint64 variable, guaranteed to be alone in a CPU cache line.
+ This is for performance, for variables accessed very frequently.
+*/
+struct PFS_cacheline_uint64
+{
+ uint64 m_u64;
+ char m_full_cache_line[PFS_CACHE_LINE_SIZE - sizeof(uint64)];
+
+ PFS_cacheline_uint64()
+ : m_u64(0)
+ {}
+};
+
+struct PFS_builtin_memory_class;
+
+/** Memory allocation for the performance schema. */
+void *pfs_malloc(PFS_builtin_memory_class *klass, size_t size, myf flags);
/** Allocate an array of structures with overflow check. */
-void *pfs_malloc_array(size_t n, size_t size, myf flags);
+void *pfs_malloc_array(PFS_builtin_memory_class *klass, size_t n, size_t size, myf flags);
/**
Helper, to allocate an array of structures.
+ @param k memory class
@param n number of elements in the array
@param s size of array element
@param T type of an element
@param f flags to use when allocating memory
*/
-#define PFS_MALLOC_ARRAY(n, s, T, f) \
- reinterpret_cast<T*>(pfs_malloc_array((n), (s), (f)))
+#define PFS_MALLOC_ARRAY(k, n, s, T, f) \
+ reinterpret_cast<T*>(pfs_malloc_array((k), (n), (s), (f)))
/** Free memory allocated with @sa pfs_malloc. */
-void pfs_free(void *ptr);
+void pfs_free(PFS_builtin_memory_class *klass, size_t size, void *ptr);
+
+/** Free memory allocated with @sa pfs_malloc_array. */
+void pfs_free_array(PFS_builtin_memory_class *klass, size_t n, size_t size, void *ptr);
+
+/**
+ Helper, to free an array of structures.
+ @param k memory class
+ @param n number of elements in the array
+ @param s size of array element
+ @param p the array to free
+*/
+#define PFS_FREE_ARRAY(k, n, s, p) \
+ pfs_free_array((k), (n), (s), (p))
/** Detect multiplication overflow. */
bool is_overflow(size_t product, size_t n1, size_t n2);
diff --git a/storage/perfschema/pfs_host.cc b/storage/perfschema/pfs_host.cc
index d6461ef3851..b896215efda 100644
--- a/storage/perfschema/pfs_host.cc
+++ b/storage/perfschema/pfs_host.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2018, 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, version 2.0,
@@ -34,21 +34,13 @@
#include "pfs_host.h"
#include "pfs_global.h"
#include "pfs_instr_class.h"
+#include "pfs_buffer_container.h"
/**
@addtogroup Performance_schema_buffers
@{
*/
-ulong host_max;
-ulong host_lost;
-
-PFS_host *host_array= NULL;
-
-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;
-
LF_HASH host_hash;
static bool host_hash_inited= false;
@@ -59,59 +51,8 @@ static bool host_hash_inited= false;
*/
int init_host(const PFS_global_param *param)
{
- uint index;
-
- host_max= param->m_host_sizing;
-
- host_array= NULL;
- host_instr_class_waits_array= NULL;
- host_instr_class_stages_array= NULL;
- host_instr_class_statements_array= NULL;
- uint waits_sizing= host_max * wait_class_max;
- uint stages_sizing= host_max * stage_class_max;
- uint statements_sizing= host_max * statement_class_max;
-
- if (host_max > 0)
- {
- host_array= PFS_MALLOC_ARRAY(host_max, sizeof(PFS_host), PFS_host,
- MYF(MY_ZEROFILL));
- if (unlikely(host_array == NULL))
- return 1;
- }
-
- if (waits_sizing > 0)
- {
- host_instr_class_waits_array=
- PFS_connection_slice::alloc_waits_slice(waits_sizing);
- if (unlikely(host_instr_class_waits_array == NULL))
- return 1;
- }
-
- if (stages_sizing > 0)
- {
- host_instr_class_stages_array=
- PFS_connection_slice::alloc_stages_slice(stages_sizing);
- if (unlikely(host_instr_class_stages_array == NULL))
- return 1;
- }
-
- if (statements_sizing > 0)
- {
- host_instr_class_statements_array=
- PFS_connection_slice::alloc_statements_slice(statements_sizing);
- if (unlikely(host_instr_class_statements_array == NULL))
- return 1;
- }
-
- for (index= 0; index < host_max; index++)
- {
- host_array[index].m_instr_class_waits_stats=
- &host_instr_class_waits_array[index * wait_class_max];
- host_array[index].m_instr_class_stages_stats=
- &host_instr_class_stages_array[index * stage_class_max];
- host_array[index].m_instr_class_statements_stats=
- &host_instr_class_statements_array[index * statement_class_max];
- }
+ if (global_host_container.init(param->m_host_sizing))
+ return 1;
return 0;
}
@@ -119,15 +60,7 @@ int init_host(const PFS_global_param *param)
/** Cleanup all the host buffers. */
void cleanup_host(void)
{
- pfs_free(host_array);
- host_array= NULL;
- pfs_free(host_instr_class_waits_array);
- host_instr_class_waits_array= NULL;
- pfs_free(host_instr_class_stages_array);
- host_instr_class_stages_array= NULL;
- pfs_free(host_instr_class_statements_array);
- host_instr_class_statements_array= NULL;
- host_max= 0;
+ global_host_container.cleanup();
}
C_MODE_START
@@ -151,13 +84,12 @@ C_MODE_END
Initialize the host hash.
@return 0 on success
*/
-int init_host_hash(void)
+int init_host_hash(const PFS_global_param *param)
{
- if ((! host_hash_inited) && (host_max > 0))
+ if ((! host_hash_inited) && (param->m_host_sizing != 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;
@@ -203,16 +135,12 @@ static void set_host_key(PFS_host_key *key,
PFS_host *find_or_create_host(PFS_thread *thread,
const char *hostname, uint hostname_length)
{
- if (host_max == 0)
- {
- host_lost++;
- return NULL;
- }
+ static PFS_ALIGNED PFS_cacheline_uint32 monotonic;
LF_PINS *pins= get_host_hash_pins(thread);
if (unlikely(pins == NULL))
{
- host_lost++;
+ global_host_container.m_lost++;
return NULL;
}
@@ -220,8 +148,10 @@ PFS_host *find_or_create_host(PFS_thread *thread,
set_host_key(&key, hostname, hostname_length);
PFS_host **entry;
+ PFS_host *pfs;
uint retry_count= 0;
const uint retry_max= 3;
+ pfs_dirty_state dirty_state;
search:
entry= reinterpret_cast<PFS_host**>
@@ -238,68 +168,55 @@ search:
lf_hash_search_unpin(pins);
- PFS_scan scan;
- uint random= randomized_index(hostname, host_max);
-
- for (scan.init(random, host_max);
- scan.has_pass();
- scan.next_pass())
+ pfs= global_host_container.allocate(& dirty_state);
+ if (pfs != NULL)
{
- PFS_host *pfs= host_array + scan.first();
- PFS_host *pfs_last= host_array + scan.last();
- for ( ; pfs < pfs_last; pfs++)
+ pfs->m_key= key;
+ if (hostname_length > 0)
+ pfs->m_hostname= &pfs->m_key.m_hash_key[0];
+ else
+ pfs->m_hostname= NULL;
+ pfs->m_hostname_length= hostname_length;
+
+ pfs->init_refcount();
+ pfs->reset_stats();
+ pfs->m_disconnected_count= 0;
+
+ int res;
+ pfs->m_lock.dirty_to_allocated(& dirty_state);
+ res= lf_hash_insert(&host_hash, pins, &pfs);
+ if (likely(res == 0))
{
- if (pfs->m_lock.is_free())
+ return pfs;
+ }
+
+ global_host_container.deallocate(pfs);
+
+ if (res > 0)
+ {
+ if (++retry_count > retry_max)
{
- if (pfs->m_lock.free_to_dirty())
- {
- pfs->m_key= key;
- if (hostname_length > 0)
- pfs->m_hostname= &pfs->m_key.m_hash_key[0];
- else
- pfs->m_hostname= NULL;
- pfs->m_hostname_length= hostname_length;
-
- pfs->init_refcount();
- pfs->reset_stats();
- pfs->m_disconnected_count= 0;
-
- int res;
- res= lf_hash_insert(&host_hash, pins, &pfs);
- if (likely(res == 0))
- {
- pfs->m_lock.dirty_to_allocated();
- return pfs;
- }
-
- pfs->m_lock.dirty_to_free();
-
- if (res > 0)
- {
- if (++retry_count > retry_max)
- {
- host_lost++;
- return NULL;
- }
- goto search;
- }
-
- host_lost++;
- return NULL;
- }
+ global_host_container.m_lost++;
+ return NULL;
}
+ goto search;
}
+
+ global_host_container.m_lost++;
+ return NULL;
}
- host_lost++;
return NULL;
}
-void PFS_host::aggregate()
+void PFS_host::aggregate(bool alive)
{
aggregate_waits();
aggregate_stages();
aggregate_statements();
+ aggregate_transactions();
+ aggregate_memory(alive);
+ aggregate_status();
aggregate_stats();
}
@@ -311,24 +228,63 @@ void PFS_host::aggregate_waits()
void PFS_host::aggregate_stages()
{
+ if (read_instr_class_stages_stats() == NULL)
+ return;
+
/*
Aggregate EVENTS_STAGES_SUMMARY_BY_HOST_BY_EVENT_NAME to:
- EVENTS_STAGES_SUMMARY_GLOBAL_BY_EVENT_NAME
*/
- aggregate_all_stages(m_instr_class_stages_stats,
+ aggregate_all_stages(write_instr_class_stages_stats(),
global_instr_class_stages_array);
}
void PFS_host::aggregate_statements()
{
+ if (read_instr_class_statements_stats() == NULL)
+ return;
+
/*
Aggregate EVENTS_STATEMENTS_SUMMARY_BY_HOST_BY_EVENT_NAME to:
- EVENTS_STATEMENTS_SUMMARY_GLOBAL_BY_EVENT_NAME
*/
- aggregate_all_statements(m_instr_class_statements_stats,
+ aggregate_all_statements(write_instr_class_statements_stats(),
global_instr_class_statements_array);
}
+void PFS_host::aggregate_transactions()
+{
+ if (read_instr_class_transactions_stats() == NULL)
+ return;
+
+ /*
+ Aggregate EVENTS_TRANSACTIONS_SUMMARY_BY_HOST_BY_EVENT_NAME to:
+ - EVENTS_TRANSACTIONS_SUMMARY_GLOBAL_BY_EVENT_NAME
+ */
+ aggregate_all_transactions(write_instr_class_transactions_stats(),
+ &global_transaction_stat);
+}
+
+void PFS_host::aggregate_memory(bool alive)
+{
+ if (read_instr_class_memory_stats() == NULL)
+ return;
+
+ /*
+ Aggregate MEMORY_SUMMARY_BY_HOST_BY_EVENT_NAME to:
+ - MEMORY_SUMMARY_GLOBAL_BY_EVENT_NAME
+ */
+ aggregate_all_memory(alive,
+ write_instr_class_memory_stats(),
+ global_instr_class_memory_array);
+}
+
+void PFS_host::aggregate_status()
+{
+ /* No parent to aggregate to, clean the stats */
+ m_status_stats.reset();
+}
+
void PFS_host::aggregate_stats()
{
/* No parent to aggregate to, clean the stats */
@@ -340,12 +296,24 @@ void PFS_host::release()
dec_refcount();
}
+void PFS_host::carry_memory_stat_delta(PFS_memory_stat_delta *delta, uint index)
+{
+ PFS_memory_stat *event_name_array;
+ PFS_memory_stat *stat;
+ PFS_memory_stat_delta delta_buffer;
+ PFS_memory_stat_delta *remaining_delta;
+
+ event_name_array= write_instr_class_memory_stats();
+ stat= & event_name_array[index];
+ remaining_delta= stat->apply_delta(delta, &delta_buffer);
+
+ if (remaining_delta != NULL)
+ carry_global_memory_stat_delta(remaining_delta, index);
+}
+
PFS_host *sanitize_host(PFS_host *unsafe)
{
- if ((&host_array[0] <= unsafe) &&
- (unsafe < &host_array[host_max]))
- return unsafe;
- return NULL;
+ return global_host_container.sanitize(unsafe);
}
void purge_host(PFS_thread *thread, PFS_host *host)
@@ -365,13 +333,33 @@ void purge_host(PFS_thread *thread, PFS_host *host)
{
lf_hash_delete(&host_hash, pins,
host->m_key.m_hash_key, host->m_key.m_key_length);
- host->m_lock.allocated_to_free();
+ host->aggregate(false);
+ global_host_container.deallocate(host);
}
}
lf_hash_search_unpin(pins);
}
+class Proc_purge_host
+ : public PFS_buffer_processor<PFS_host>
+{
+public:
+ Proc_purge_host(PFS_thread *thread)
+ : m_thread(thread)
+ {}
+
+ virtual void operator()(PFS_host *pfs)
+ {
+ pfs->aggregate(true);
+ if (pfs->get_refcount() == 0)
+ purge_host(m_thread, pfs);
+ }
+
+private:
+ PFS_thread *m_thread;
+};
+
/** Purge non connected hosts, reset stats of connected hosts. */
void purge_all_host(void)
{
@@ -379,18 +367,8 @@ void purge_all_host(void)
if (unlikely(thread == NULL))
return;
- PFS_host *pfs= host_array;
- PFS_host *pfs_last= host_array + host_max;
-
- for ( ; pfs < pfs_last; pfs++)
- {
- if (pfs->m_lock.is_populated())
- {
- pfs->aggregate();
- if (pfs->get_refcount() == 0)
- purge_host(thread, pfs);
- }
- }
+ Proc_purge_host proc(thread);
+ global_host_container.apply(proc);
}
/** @} */
diff --git a/storage/perfschema/pfs_host.h b/storage/perfschema/pfs_host.h
index d52207d3571..3781988237b 100644
--- a/storage/perfschema/pfs_host.h
+++ b/storage/perfschema/pfs_host.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -40,6 +40,7 @@ struct PFS_thread;
@{
*/
+/** Hash key for a host. */
struct PFS_host_key
{
/**
@@ -51,6 +52,7 @@ struct PFS_host_key
uint m_key_length;
};
+/** Per host statistics. */
struct PFS_ALIGNED PFS_host : PFS_connection_slice
{
public:
@@ -74,13 +76,18 @@ public:
PFS_atomic::add_32(& m_refcount, -1);
}
- void aggregate(void);
+ void aggregate(bool alive);
void aggregate_waits(void);
void aggregate_stages(void);
void aggregate_statements(void);
+ void aggregate_transactions(void);
+ void aggregate_memory(bool alive);
+ void aggregate_status(void);
void aggregate_stats(void);
void release(void);
+ void carry_memory_stat_delta(PFS_memory_stat_delta *delta, uint index);
+
/* Internal lock. */
pfs_lock m_lock;
PFS_host_key m_key;
@@ -95,7 +102,7 @@ private:
int init_host(const PFS_global_param *param);
void cleanup_host(void);
-int init_host_hash(void);
+int init_host_hash(const PFS_global_param *param);
void cleanup_host_hash(void);
PFS_host *find_or_create_host(PFS_thread *thread,
@@ -104,14 +111,7 @@ PFS_host *find_or_create_host(PFS_thread *thread,
PFS_host *sanitize_host(PFS_host *unsafe);
void purge_all_host(void);
-/* For iterators and show status. */
-
-extern ulong host_max;
-extern ulong host_lost;
-
-/* Exposing the data directly, for iterators. */
-
-extern PFS_host *host_array;
+/* For show status. */
extern LF_HASH host_hash;
diff --git a/storage/perfschema/pfs_instr.cc b/storage/perfschema/pfs_instr.cc
index ca9e0385021..728c503ec4e 100644
--- a/storage/perfschema/pfs_instr.cc
+++ b/storage/perfschema/pfs_instr.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2018, 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, version 2.0,
@@ -37,115 +37,45 @@
#include "pfs_account.h"
#include "pfs_global.h"
#include "pfs_instr_class.h"
+#include "pfs_buffer_container.h"
+#include "pfs_builtin_memory.h"
+
+ulong nested_statement_lost= 0;
/**
@addtogroup Performance_schema_buffers
@{
*/
-/** Size of the mutex instances array. @sa mutex_array */
-ulong mutex_max;
-/** True when @c mutex_array is full. */
-bool mutex_full;
-/** Number of mutexes instance lost. @sa mutex_array */
-ulong mutex_lost;
-/** Size of the rwlock instances array. @sa rwlock_array */
-ulong rwlock_max;
-/** True when @c rwlock_array is full. */
-bool rwlock_full;
-/** Number or rwlock instances lost. @sa rwlock_array */
-ulong rwlock_lost;
-/** Size of the conditions instances array. @sa cond_array */
-ulong cond_max;
-/** True when @c cond_array is full. */
-bool cond_full;
-/** Number of conditions instances lost. @sa cond_array */
-ulong cond_lost;
-/** Size of the thread instances array. @sa thread_array */
-ulong thread_max;
-/** True when @c thread_array is full. */
-bool thread_full;
-/** Number or thread instances lost. @sa thread_array */
-ulong thread_lost;
-/** Size of the file instances array. @sa file_array */
-ulong file_max;
-/** True when @c file_array is full. */
-bool file_full;
-/** Number of file instances lost. @sa file_array */
-ulong file_lost;
/**
Size of the file handle array. @sa file_handle_array.
Signed value, for easier comparisons with a file descriptor number.
*/
-long file_handle_max;
+long file_handle_max= 0;
/** True when @c file_handle_array is full. */
bool file_handle_full;
/** Number of file handle lost. @sa file_handle_array */
-ulong file_handle_lost;
-/** Size of the table instances array. @sa table_array */
-ulong table_max;
-/** True when @c table_array is full. */
-bool table_full;
-/** Number of table instances lost. @sa table_array */
-ulong table_lost;
-/** Size of the socket instances array. @sa socket_array */
-ulong socket_max;
-/** True when @c socket_array is full. */
-bool socket_full;
-/** Number of socket instances lost. @sa socket_array */
-ulong socket_lost;
+ulong file_handle_lost= 0;
/** Number of EVENTS_WAITS_HISTORY records per thread. */
-ulong events_waits_history_per_thread;
+ulong events_waits_history_per_thread= 0;
/** Number of EVENTS_STAGES_HISTORY records per thread. */
-ulong events_stages_history_per_thread;
+ulong events_stages_history_per_thread= 0;
/** Number of EVENTS_STATEMENTS_HISTORY records per thread. */
-ulong events_statements_history_per_thread;
-uint statement_stack_max;
+ulong events_statements_history_per_thread= 0;
+uint statement_stack_max= 0;
size_t pfs_max_digest_length= 0;
+size_t pfs_max_sqltext= 0;
/** Number of locker lost. @sa LOCKER_STACK_SIZE. */
ulong locker_lost= 0;
-/** Number of statement lost. @sa STATEMENT_STACK_SIZE. */
+/** Number of statements 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.
- @sa mutex_max
- @sa mutex_lost
-*/
-PFS_mutex *mutex_array= NULL;
-
-/**
- RWLock instrumentation instances array.
- @sa rwlock_max
- @sa rwlock_lost
-*/
-PFS_rwlock *rwlock_array= NULL;
-
-/**
- Condition instrumentation instances array.
- @sa cond_max
- @sa cond_lost
-*/
-PFS_cond *cond_array= NULL;
-
-/**
- Thread instrumentation instances array.
- @sa thread_max
- @sa thread_lost
-*/
-PFS_thread *thread_array= NULL;
-
-/**
- File instrumentation instances array.
- @sa file_max
- @sa file_lost
- @sa filename_hash
-*/
-PFS_file *file_array= NULL;
+/** Number of EVENTS_TRANSACTIONS_HISTORY records per thread. */
+ulong events_transactions_history_per_thread= 0;
/**
File instrumentation handle array.
@@ -154,39 +84,11 @@ PFS_file *file_array= NULL;
*/
PFS_file **file_handle_array= NULL;
-/**
- Table instrumentation instances array.
- @sa table_max
- @sa table_lost
-*/
-PFS_table *table_array= NULL;
-
-/**
- Socket instrumentation instances array.
- @sa socket_max
- @sa socket_lost
-*/
-PFS_socket *socket_array= NULL;
-
PFS_stage_stat *global_instr_class_stages_array= NULL;
PFS_statement_stat *global_instr_class_statements_array= NULL;
+PFS_memory_stat *global_instr_class_memory_array= NULL;
-static volatile uint64 thread_internal_id_counter= 0;
-
-static uint thread_instr_class_waits_sizing;
-static uint thread_instr_class_stages_sizing;
-static uint thread_instr_class_statements_sizing;
-static PFS_single_stat *thread_instr_class_waits_array= NULL;
-static PFS_stage_stat *thread_instr_class_stages_array= NULL;
-static PFS_statement_stat *thread_instr_class_statements_array= NULL;
-
-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 unsigned char *current_stmts_digest_token_array= NULL;
-static unsigned char *history_stmts_digest_token_array= NULL;
-static char *thread_session_connect_attrs_array= NULL;
+static PFS_ALIGNED PFS_cacheline_uint64 thread_internal_id_counter;
/** Hash table for instrumented files. */
LF_HASH filename_hash;
@@ -200,291 +102,76 @@ static bool filename_hash_inited= false;
*/
int init_instruments(const PFS_global_param *param)
{
- PFS_events_statements *pfs_stmt;
- unsigned char *pfs_tokens;
-
- uint thread_waits_history_sizing;
- uint thread_stages_history_sizing;
- uint thread_statements_history_sizing;
- uint thread_statements_stack_sizing;
- uint thread_session_connect_attrs_sizing;
uint index;
/* Make sure init_event_name_sizing is called */
DBUG_ASSERT(wait_class_max != 0);
- mutex_max= param->m_mutex_sizing;
- mutex_full= false;
- mutex_lost= 0;
- rwlock_max= param->m_rwlock_sizing;
- rwlock_full= false;
- rwlock_lost= 0;
- cond_max= param->m_cond_sizing;
- cond_full= false;
- cond_lost= 0;
- file_max= param->m_file_sizing;
- file_full= false;
- file_lost= 0;
file_handle_max= param->m_file_handle_sizing;
file_handle_full= false;
file_handle_lost= 0;
pfs_max_digest_length= param->m_max_digest_length;
-
- table_max= param->m_table_sizing;
- table_full= false;
- table_lost= 0;
- thread_max= param->m_thread_sizing;
- thread_full= false;
- thread_lost= 0;
- socket_max= param->m_socket_sizing;
- socket_full= false;
- socket_lost= 0;
+ pfs_max_sqltext= param->m_max_sql_text_length;
events_waits_history_per_thread= param->m_events_waits_history_sizing;
- thread_waits_history_sizing= param->m_thread_sizing
- * events_waits_history_per_thread;
-
- thread_instr_class_waits_sizing= param->m_thread_sizing
- * wait_class_max;
events_stages_history_per_thread= param->m_events_stages_history_sizing;
- thread_stages_history_sizing= param->m_thread_sizing
- * events_stages_history_per_thread;
events_statements_history_per_thread= param->m_events_statements_history_sizing;
- thread_statements_history_sizing= param->m_thread_sizing
- * events_statements_history_per_thread;
- statement_stack_max= 1;
- thread_statements_stack_sizing= param->m_thread_sizing * statement_stack_max;
+ statement_stack_max= param->m_statement_stack_sizing;
- thread_instr_class_stages_sizing= param->m_thread_sizing
- * param->m_stage_class_sizing;
-
- thread_instr_class_statements_sizing= param->m_thread_sizing
- * param->m_statement_class_sizing;
+ events_transactions_history_per_thread= param->m_events_transactions_history_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;
- size_t current_digest_tokens_sizing= param->m_thread_sizing * pfs_max_digest_length * statement_stack_max;
- size_t history_digest_tokens_sizing= param->m_thread_sizing * pfs_max_digest_length * events_statements_history_per_thread;
-
- mutex_array= NULL;
- rwlock_array= NULL;
- cond_array= NULL;
- file_array= NULL;
file_handle_array= NULL;
- table_array= NULL;
- socket_array= NULL;
- thread_array= NULL;
- thread_waits_history_array= NULL;
- thread_stages_history_array= NULL;
- thread_statements_history_array= NULL;
- thread_statements_stack_array= NULL;
- current_stmts_digest_token_array= NULL;
- history_stmts_digest_token_array= NULL;
- thread_instr_class_waits_array= NULL;
- thread_instr_class_stages_array= NULL;
- thread_instr_class_statements_array= NULL;
- thread_internal_id_counter= 0;
-
- if (mutex_max > 0)
- {
- mutex_array= PFS_MALLOC_ARRAY(mutex_max, sizeof(PFS_mutex), PFS_mutex, MYF(MY_ZEROFILL));
- if (unlikely(mutex_array == NULL))
- return 1;
- }
- if (rwlock_max > 0)
- {
- rwlock_array= PFS_MALLOC_ARRAY(rwlock_max, sizeof(PFS_rwlock), PFS_rwlock, MYF(MY_ZEROFILL));
- if (unlikely(rwlock_array == NULL))
- return 1;
- }
+ thread_internal_id_counter.m_u64= 0;
- if (cond_max > 0)
- {
- cond_array= PFS_MALLOC_ARRAY(cond_max, sizeof(PFS_cond), PFS_cond, MYF(MY_ZEROFILL));
- if (unlikely(cond_array == NULL))
- return 1;
- }
+ if (global_mutex_container.init(param->m_mutex_sizing))
+ return 1;
- if (file_max > 0)
- {
- file_array= PFS_MALLOC_ARRAY(file_max, sizeof(PFS_file), PFS_file, MYF(MY_ZEROFILL));
- if (unlikely(file_array == NULL))
- return 1;
- }
+ if (global_rwlock_container.init(param->m_rwlock_sizing))
+ return 1;
- if (file_handle_max > 0)
- {
- file_handle_array= PFS_MALLOC_ARRAY(file_handle_max, sizeof(PFS_file*), PFS_file*, MYF(MY_ZEROFILL));
- if (unlikely(file_handle_array == NULL))
- return 1;
- }
+ if (global_cond_container.init(param->m_cond_sizing))
+ return 1;
- if (table_max > 0)
- {
- table_array= PFS_MALLOC_ARRAY(table_max, sizeof(PFS_table), PFS_table, MYF(MY_ZEROFILL));
- if (unlikely(table_array == NULL))
- return 1;
- }
-
- if (socket_max > 0)
- {
- socket_array= PFS_MALLOC_ARRAY(socket_max, sizeof(PFS_socket), PFS_socket, MYF(MY_ZEROFILL));
- if (unlikely(socket_array == NULL))
- return 1;
- }
-
- if (thread_max > 0)
- {
- thread_array= PFS_MALLOC_ARRAY(thread_max, sizeof(PFS_thread), PFS_thread, MYF(MY_ZEROFILL));
- if (unlikely(thread_array == NULL))
- return 1;
- }
+ if (global_file_container.init(param->m_file_sizing))
+ return 1;
- if (thread_waits_history_sizing > 0)
- {
- thread_waits_history_array=
- PFS_MALLOC_ARRAY(thread_waits_history_sizing, sizeof(PFS_events_waits), PFS_events_waits,
- MYF(MY_ZEROFILL));
- if (unlikely(thread_waits_history_array == NULL))
- return 1;
- }
-
- if (thread_instr_class_waits_sizing > 0)
- {
- thread_instr_class_waits_array=
- PFS_MALLOC_ARRAY(thread_instr_class_waits_sizing,
- sizeof(PFS_single_stat), PFS_single_stat, MYF(MY_ZEROFILL));
- if (unlikely(thread_instr_class_waits_array == NULL))
- return 1;
-
- for (index= 0; index < thread_instr_class_waits_sizing; index++)
- thread_instr_class_waits_array[index].reset();
- }
-
- if (thread_stages_history_sizing > 0)
- {
- thread_stages_history_array=
- PFS_MALLOC_ARRAY(thread_stages_history_sizing, sizeof(PFS_events_stages), PFS_events_stages,
- MYF(MY_ZEROFILL));
- if (unlikely(thread_stages_history_array == NULL))
- return 1;
- }
-
- if (thread_instr_class_stages_sizing > 0)
- {
- thread_instr_class_stages_array=
- PFS_MALLOC_ARRAY(thread_instr_class_stages_sizing,
- sizeof(PFS_stage_stat), PFS_stage_stat, MYF(MY_ZEROFILL));
- if (unlikely(thread_instr_class_stages_array == NULL))
- return 1;
-
- for (index= 0; index < thread_instr_class_stages_sizing; index++)
- thread_instr_class_stages_array[index].reset();
- }
-
- if (thread_statements_history_sizing > 0)
- {
- thread_statements_history_array=
- PFS_MALLOC_ARRAY(thread_statements_history_sizing, sizeof(PFS_events_statements),
- PFS_events_statements, MYF(MY_ZEROFILL));
- if (unlikely(thread_statements_history_array == NULL))
- return 1;
- }
-
- if (thread_statements_stack_sizing > 0)
- {
- thread_statements_stack_array=
- PFS_MALLOC_ARRAY(thread_statements_stack_sizing, sizeof(PFS_events_statements),
- PFS_events_statements, MYF(MY_ZEROFILL));
- if (unlikely(thread_statements_stack_array == NULL))
- return 1;
- }
-
- if (thread_instr_class_statements_sizing > 0)
- {
- thread_instr_class_statements_array=
- PFS_MALLOC_ARRAY(thread_instr_class_statements_sizing,
- sizeof(PFS_statement_stat), PFS_statement_stat, MYF(MY_ZEROFILL));
- if (unlikely(thread_instr_class_statements_array == NULL))
- return 1;
-
- for (index= 0; index < thread_instr_class_statements_sizing; index++)
- 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;
- }
-
- if (current_digest_tokens_sizing > 0)
- {
- current_stmts_digest_token_array=
- (unsigned char *)pfs_malloc(current_digest_tokens_sizing, MYF(MY_ZEROFILL));
- if (unlikely(current_stmts_digest_token_array == NULL))
- return 1;
- }
-
- if (history_digest_tokens_sizing > 0)
+ if (file_handle_max > 0)
{
- history_stmts_digest_token_array=
- (unsigned char *)pfs_malloc(history_digest_tokens_sizing, MYF(MY_ZEROFILL));
- if (unlikely(history_stmts_digest_token_array == NULL))
+ file_handle_array= PFS_MALLOC_ARRAY(& builtin_memory_file_handle,
+ file_handle_max,
+ sizeof(PFS_file*), PFS_file*,
+ MYF(MY_ZEROFILL));
+ if (unlikely(file_handle_array == NULL))
return 1;
}
- for (index= 0; index < thread_max; index++)
- {
- thread_array[index].m_waits_history=
- &thread_waits_history_array[index * events_waits_history_per_thread];
- thread_array[index].m_instr_class_waits_stats=
- &thread_instr_class_waits_array[index * wait_class_max];
- thread_array[index].m_stages_history=
- &thread_stages_history_array[index * events_stages_history_per_thread];
- thread_array[index].m_instr_class_stages_stats=
- &thread_instr_class_stages_array[index * stage_class_max];
- thread_array[index].m_statements_history=
- &thread_statements_history_array[index * events_statements_history_per_thread];
- thread_array[index].m_statement_stack=
- &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];
- thread_array[index].m_session_connect_attrs=
- &thread_session_connect_attrs_array[index * session_connect_attrs_size_per_thread];
- }
+ if (global_table_container.init(param->m_table_sizing))
+ return 1;
- for (index= 0; index < thread_statements_stack_sizing; index++)
- {
- pfs_stmt= & thread_statements_stack_array[index];
+ if (global_socket_container.init(param->m_socket_sizing))
+ return 1;
- pfs_tokens= & current_stmts_digest_token_array[index * pfs_max_digest_length];
- pfs_stmt->m_digest_storage.reset(pfs_tokens, pfs_max_digest_length);
- }
+ if (global_mdl_container.init(param->m_metadata_lock_sizing))
+ return 1;
- for (index= 0; index < thread_statements_history_sizing; index++)
- {
- pfs_stmt= & thread_statements_history_array[index];
-
- pfs_tokens= & history_stmts_digest_token_array[index * pfs_max_digest_length];
- pfs_stmt->m_digest_storage.reset(pfs_tokens, pfs_max_digest_length);
- }
+ if (global_thread_container.init(param->m_thread_sizing))
+ return 1;
if (stage_class_max > 0)
{
global_instr_class_stages_array=
- PFS_MALLOC_ARRAY(stage_class_max,
- sizeof(PFS_stage_stat), PFS_stage_stat, MYF(MY_ZEROFILL));
+ PFS_MALLOC_ARRAY(& builtin_memory_global_stages,
+ stage_class_max,
+ sizeof(PFS_stage_stat), PFS_stage_stat,
+ MYF(MY_ZEROFILL));
if (unlikely(global_instr_class_stages_array == NULL))
return 1;
@@ -495,8 +182,10 @@ int init_instruments(const PFS_global_param *param)
if (statement_class_max > 0)
{
global_instr_class_statements_array=
- PFS_MALLOC_ARRAY(statement_class_max,
- sizeof(PFS_statement_stat), PFS_statement_stat, MYF(MY_ZEROFILL));
+ PFS_MALLOC_ARRAY(& builtin_memory_global_statements,
+ statement_class_max,
+ sizeof(PFS_statement_stat), PFS_statement_stat,
+ MYF(MY_ZEROFILL));
if (unlikely(global_instr_class_statements_array == NULL))
return 1;
@@ -504,60 +193,59 @@ int init_instruments(const PFS_global_param *param)
global_instr_class_statements_array[index].reset();
}
+ if (memory_class_max > 0)
+ {
+ global_instr_class_memory_array=
+ PFS_MALLOC_ARRAY(& builtin_memory_global_memory,
+ memory_class_max,
+ sizeof(PFS_memory_stat), PFS_memory_stat,
+ MYF(MY_ZEROFILL));
+ if (unlikely(global_instr_class_memory_array == NULL))
+ return 1;
+
+ for (index= 0; index < memory_class_max; index++)
+ global_instr_class_memory_array[index].reset();
+ }
+
return 0;
}
/** Cleanup all the instruments buffers. */
void cleanup_instruments(void)
{
- pfs_free(mutex_array);
- mutex_array= NULL;
- mutex_max= 0;
- pfs_free(rwlock_array);
- rwlock_array= NULL;
- rwlock_max= 0;
- pfs_free(cond_array);
- cond_array= NULL;
- cond_max= 0;
- pfs_free(file_array);
- file_array= NULL;
- file_max= 0;
- pfs_free(file_handle_array);
+ global_mutex_container.cleanup();
+ global_rwlock_container.cleanup();
+ global_cond_container.cleanup();
+ global_file_container.cleanup();
+
+ PFS_FREE_ARRAY(& builtin_memory_file_handle,
+ file_handle_max, sizeof(PFS_file*),
+ file_handle_array);
file_handle_array= NULL;
file_handle_max= 0;
- pfs_free(table_array);
- table_array= NULL;
- table_max= 0;
- pfs_free(socket_array);
- socket_array= NULL;
- socket_max= 0;
- pfs_free(thread_array);
- thread_array= NULL;
- thread_max= 0;
- pfs_free(thread_waits_history_array);
- thread_waits_history_array= NULL;
- pfs_free(thread_stages_history_array);
- thread_stages_history_array= NULL;
- pfs_free(thread_statements_history_array);
- thread_statements_history_array= NULL;
- pfs_free(thread_statements_stack_array);
- thread_statements_stack_array= NULL;
- pfs_free(thread_instr_class_waits_array);
- thread_instr_class_waits_array= NULL;
- pfs_free(global_instr_class_stages_array);
+
+ global_table_container.cleanup();
+ global_socket_container.cleanup();
+ global_mdl_container.cleanup();
+ global_thread_container.cleanup();
+
+ PFS_FREE_ARRAY(& builtin_memory_global_stages,
+ stage_class_max,
+ sizeof(PFS_stage_stat),
+ global_instr_class_stages_array);
global_instr_class_stages_array= NULL;
- pfs_free(global_instr_class_statements_array);
+
+ PFS_FREE_ARRAY(& builtin_memory_global_statements,
+ statement_class_max,
+ sizeof(PFS_statement_stat),
+ global_instr_class_statements_array);
global_instr_class_statements_array= NULL;
- pfs_free(thread_instr_class_statements_array);
- 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;
- pfs_free(current_stmts_digest_token_array);
- current_stmts_digest_token_array= NULL;
- pfs_free(history_stmts_digest_token_array);
- history_stmts_digest_token_array= NULL;
+
+ PFS_FREE_ARRAY(& builtin_memory_global_memory,
+ memory_class_max,
+ sizeof(PFS_memory_stat),
+ global_instr_class_memory_array);
+ global_instr_class_memory_array= NULL;
}
C_MODE_START
@@ -582,13 +270,12 @@ C_MODE_END
Initialize the file name hash.
@return 0 on success
*/
-int init_file_hash(void)
+int init_file_hash(const PFS_global_param *param)
{
- if ((! filename_hash_inited) && (file_max > 0))
+ if ((! filename_hash_inited) && (param->m_file_sizing != 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;
}
return 0;
@@ -604,75 +291,6 @@ void cleanup_file_hash(void)
}
}
-void PFS_scan::init(uint random, uint max_size)
-{
- m_pass= 0;
-
- if (max_size == 0)
- {
- /* Degenerated case, no buffer */
- m_pass_max= 0;
- return;
- }
-
- DBUG_ASSERT(random < max_size);
-
- if (PFS_MAX_ALLOC_RETRY < max_size)
- {
- /*
- The buffer is big compared to PFS_MAX_ALLOC_RETRY,
- scan it only partially.
- */
- if (random + PFS_MAX_ALLOC_RETRY < max_size)
- {
- /*
- Pass 1: [random, random + PFS_MAX_ALLOC_RETRY - 1]
- Pass 2: not used.
- */
- m_pass_max= 1;
- m_first[0]= random;
- m_last[0]= random + PFS_MAX_ALLOC_RETRY;
- m_first[1]= 0;
- m_last[1]= 0;
- }
- else
- {
- /*
- Pass 1: [random, max_size - 1]
- Pass 2: [0, ...]
- The combined length of pass 1 and 2 is PFS_MAX_ALLOC_RETRY.
- */
- m_pass_max= 2;
- m_first[0]= random;
- m_last[0]= max_size;
- m_first[1]= 0;
- m_last[1]= PFS_MAX_ALLOC_RETRY - (max_size - random);
- }
- }
- else
- {
- /*
- The buffer is small compared to PFS_MAX_ALLOC_RETRY,
- scan it in full in two passes.
- Pass 1: [random, max_size - 1]
- Pass 2: [0, random - 1]
- */
- m_pass_max= 2;
- m_first[0]= random;
- m_last[0]= max_size;
- m_first[1]= 0;
- m_last[1]= random;
- }
-
- DBUG_ASSERT(m_first[0] < max_size);
- DBUG_ASSERT(m_first[1] < max_size);
- DBUG_ASSERT(m_last[1] <= max_size);
- DBUG_ASSERT(m_last[1] <= max_size);
- /* The combined length of all passes should not exceed PFS_MAX_ALLOC_RETRY. */
- DBUG_ASSERT((m_last[0] - m_first[0]) +
- (m_last[1] - m_first[1]) <= PFS_MAX_ALLOC_RETRY);
-}
-
/**
Create instrumentation for a mutex instance.
@param klass the mutex class
@@ -681,76 +299,25 @@ void PFS_scan::init(uint random, uint max_size)
*/
PFS_mutex* create_mutex(PFS_mutex_class *klass, const void *identity)
{
- static uint PFS_ALIGNED mutex_monotonic_index= 0;
- uint index;
- uint attempts= 0;
PFS_mutex *pfs;
+ pfs_dirty_state dirty_state;
- if (mutex_full)
+ pfs= global_mutex_container.allocate(& dirty_state, klass->m_volatility);
+ if (pfs != NULL)
{
- /*
- This is a safety plug.
- When mutex_array is severely undersized,
- do not spin to death for each call.
- */
- mutex_lost++;
- return NULL;
- }
-
- while (++attempts <= mutex_max)
- {
- /*
- Problem:
- Multiple threads running concurrently may need to create a new
- instrumented mutex, and find an empty slot in mutex_array[].
- With N1 threads running on a N2 core hardware:
- - up to N2 hardware threads can run concurrently,
- causing contention if looking at the same array[i] slot.
- - up to N1 threads can run almost concurrently (with thread scheduling),
- scanning maybe overlapping regions in the [0-mutex_max] array.
-
- Solution:
- Instead of letting different threads compete on the same array[i] entry,
- this code forces all threads to cooperate with the monotonic_index.
- Only one thread will be allowed to test a given array[i] slot.
- All threads do scan from the same region, starting at monotonic_index.
- Serializing on monotonic_index ensures that when a slot is found occupied
- in a given loop by a given thread, other threads will not attempt this
- slot.
- */
- index= PFS_atomic::add_u32(& mutex_monotonic_index, 1) % mutex_max;
- pfs= mutex_array + index;
-
- if (pfs->m_lock.is_free())
- {
- if (pfs->m_lock.free_to_dirty())
- {
- pfs->m_identity= identity;
- pfs->m_class= klass;
- pfs->m_enabled= klass->m_enabled && flag_global_instrumentation;
- pfs->m_timed= klass->m_timed;
- pfs->m_mutex_stat.reset();
- pfs->m_owner= NULL;
- pfs->m_last_locked= 0;
- pfs->m_lock.dirty_to_allocated();
- if (klass->is_singleton())
- klass->m_singleton= pfs;
- return pfs;
- }
- }
+ pfs->m_identity= identity;
+ pfs->m_class= klass;
+ pfs->m_enabled= klass->m_enabled && flag_global_instrumentation;
+ pfs->m_timed= klass->m_timed;
+ pfs->m_mutex_stat.reset();
+ pfs->m_owner= NULL;
+ pfs->m_last_locked= 0;
+ pfs->m_lock.dirty_to_allocated(& dirty_state);
+ if (klass->is_singleton())
+ klass->m_singleton= pfs;
}
- mutex_lost++;
- /*
- Race condition.
- The mutex_array might not be full if a concurrent thread
- called destroy_mutex() during the scan, leaving one
- empty slot we did not find.
- However, 99.999 percent full tables or 100 percent full tables
- are treated the same here, we declare the array overloaded.
- */
- mutex_full= true;
- return NULL;
+ return pfs;
}
/**
@@ -766,8 +333,8 @@ void destroy_mutex(PFS_mutex *pfs)
pfs->m_mutex_stat.reset();
if (klass->is_singleton())
klass->m_singleton= NULL;
- pfs->m_lock.allocated_to_free();
- mutex_full= false;
+
+ global_mutex_container.deallocate(pfs);
}
/**
@@ -778,47 +345,27 @@ void destroy_mutex(PFS_mutex *pfs)
*/
PFS_rwlock* create_rwlock(PFS_rwlock_class *klass, const void *identity)
{
- static uint PFS_ALIGNED rwlock_monotonic_index= 0;
- uint index;
- uint attempts= 0;
PFS_rwlock *pfs;
+ pfs_dirty_state dirty_state;
- if (rwlock_full)
+ pfs= global_rwlock_container.allocate(& dirty_state);
+ if (pfs != NULL)
{
- rwlock_lost++;
- return NULL;
- }
-
- while (++attempts <= rwlock_max)
- {
- /* See create_mutex() */
- index= PFS_atomic::add_u32(& rwlock_monotonic_index, 1) % rwlock_max;
- pfs= rwlock_array + index;
-
- if (pfs->m_lock.is_free())
- {
- if (pfs->m_lock.free_to_dirty())
- {
- pfs->m_identity= identity;
- pfs->m_class= klass;
- pfs->m_enabled= klass->m_enabled && flag_global_instrumentation;
- pfs->m_timed= klass->m_timed;
- pfs->m_rwlock_stat.reset();
- pfs->m_lock.dirty_to_allocated();
- pfs->m_writer= NULL;
- pfs->m_readers= 0;
- pfs->m_last_written= 0;
- pfs->m_last_read= 0;
- if (klass->is_singleton())
- klass->m_singleton= pfs;
- return pfs;
- }
- }
+ pfs->m_identity= identity;
+ pfs->m_class= klass;
+ pfs->m_enabled= klass->m_enabled && flag_global_instrumentation;
+ pfs->m_timed= klass->m_timed;
+ pfs->m_rwlock_stat.reset();
+ pfs->m_writer= NULL;
+ pfs->m_readers= 0;
+ pfs->m_last_written= 0;
+ pfs->m_last_read= 0;
+ pfs->m_lock.dirty_to_allocated(& dirty_state);
+ if (klass->is_singleton())
+ klass->m_singleton= pfs;
}
- rwlock_lost++;
- rwlock_full= true;
- return NULL;
+ return pfs;
}
/**
@@ -834,8 +381,8 @@ void destroy_rwlock(PFS_rwlock *pfs)
pfs->m_rwlock_stat.reset();
if (klass->is_singleton())
klass->m_singleton= NULL;
- pfs->m_lock.allocated_to_free();
- rwlock_full= false;
+
+ global_rwlock_container.deallocate(pfs);
}
/**
@@ -846,45 +393,23 @@ void destroy_rwlock(PFS_rwlock *pfs)
*/
PFS_cond* create_cond(PFS_cond_class *klass, const void *identity)
{
- static uint PFS_ALIGNED cond_monotonic_index= 0;
- uint index;
- uint attempts= 0;
PFS_cond *pfs;
+ pfs_dirty_state dirty_state;
- if (cond_full)
- {
- cond_lost++;
- return NULL;
- }
-
- while (++attempts <= cond_max)
+ pfs= global_cond_container.allocate(& dirty_state);
+ if (pfs != NULL)
{
- /* See create_mutex() */
- index= PFS_atomic::add_u32(& cond_monotonic_index, 1) % cond_max;
- pfs= cond_array + index;
-
- if (pfs->m_lock.is_free())
- {
- if (pfs->m_lock.free_to_dirty())
- {
- pfs->m_identity= identity;
- pfs->m_class= klass;
- pfs->m_enabled= klass->m_enabled && flag_global_instrumentation;
- pfs->m_timed= klass->m_timed;
- pfs->m_cond_stat.m_signal_count= 0;
- pfs->m_cond_stat.m_broadcast_count= 0;
- pfs->m_wait_stat.reset();
- pfs->m_lock.dirty_to_allocated();
- if (klass->is_singleton())
- klass->m_singleton= pfs;
- return pfs;
- }
- }
+ pfs->m_identity= identity;
+ pfs->m_class= klass;
+ pfs->m_enabled= klass->m_enabled && flag_global_instrumentation;
+ pfs->m_timed= klass->m_timed;
+ pfs->m_cond_stat.reset();
+ pfs->m_lock.dirty_to_allocated(& dirty_state);
+ if (klass->is_singleton())
+ klass->m_singleton= pfs;
}
- cond_lost++;
- cond_full= true;
- return NULL;
+ return pfs;
}
/**
@@ -897,17 +422,16 @@ void destroy_cond(PFS_cond *pfs)
PFS_cond_class *klass= pfs->m_class;
/* Aggregate to EVENTS_WAITS_SUMMARY_GLOBAL_BY_EVENT_NAME */
klass->m_cond_stat.aggregate(& pfs->m_cond_stat);
- pfs->m_wait_stat.reset();
+ pfs->m_cond_stat.reset();
if (klass->is_singleton())
klass->m_singleton= NULL;
- pfs->m_lock.allocated_to_free();
- cond_full= false;
+
+ global_cond_container.deallocate(pfs);
}
PFS_thread* PFS_thread::get_current_thread()
{
- PFS_thread *pfs= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
- return pfs;
+ return static_cast<PFS_thread*>(my_get_thread_local(THR_PFS));
}
void PFS_thread::reset_session_connect_attrs()
@@ -923,6 +447,64 @@ void PFS_thread::reset_session_connect_attrs()
}
}
+void PFS_thread::set_history_derived_flags()
+{
+ if (m_history)
+ {
+ m_flag_events_waits_history= flag_events_waits_history;
+ m_flag_events_waits_history_long= flag_events_waits_history_long;
+ m_flag_events_stages_history= flag_events_stages_history;
+ m_flag_events_stages_history_long= flag_events_stages_history_long;
+ m_flag_events_statements_history= flag_events_statements_history;
+ m_flag_events_statements_history_long= flag_events_statements_history_long;
+ m_flag_events_transactions_history= flag_events_transactions_history;
+ m_flag_events_transactions_history_long= flag_events_transactions_history_long;
+ }
+ else
+ {
+ m_flag_events_waits_history= false;
+ m_flag_events_waits_history_long= false;
+ m_flag_events_stages_history= false;
+ m_flag_events_stages_history_long= false;
+ m_flag_events_statements_history= false;
+ m_flag_events_statements_history_long= false;
+ m_flag_events_transactions_history= false;
+ m_flag_events_transactions_history_long= false;
+ }
+}
+
+void PFS_thread::carry_memory_stat_delta(PFS_memory_stat_delta *delta, uint index)
+{
+ if (m_account != NULL)
+ {
+ m_account->carry_memory_stat_delta(delta, index);
+ return;
+ }
+
+ if (m_user != NULL)
+ {
+ m_user->carry_memory_stat_delta(delta, index);
+ /* do not return, need to process m_host below */
+ }
+
+ if (m_host != NULL)
+ {
+ m_host->carry_memory_stat_delta(delta, index);
+ return;
+ }
+
+ carry_global_memory_stat_delta(delta, index);
+}
+
+void carry_global_memory_stat_delta(PFS_memory_stat_delta *delta, uint index)
+{
+ PFS_memory_stat *stat;
+ PFS_memory_stat_delta delta_buffer;
+
+ stat= & global_instr_class_memory_array[index];
+ (void) stat->apply_delta(delta, &delta_buffer);
+}
+
/**
Create instrumentation for a thread instance.
@param klass the thread class
@@ -935,158 +517,101 @@ void PFS_thread::reset_session_connect_attrs()
PFS_thread* create_thread(PFS_thread_class *klass, const void *identity,
ulonglong processlist_id)
{
- static uint PFS_ALIGNED thread_monotonic_index= 0;
- uint index;
- uint attempts= 0;
PFS_thread *pfs;
+ pfs_dirty_state dirty_state;
+
+ pfs= global_thread_container.allocate(& dirty_state);
+ if (pfs != NULL)
+ {
+ pfs->m_thread_internal_id=
+ PFS_atomic::add_u64(&thread_internal_id_counter.m_u64, 1);
+ pfs->m_parent_thread_internal_id= 0;
+ pfs->m_processlist_id= static_cast<ulong>(processlist_id);
+ pfs->m_thread_os_id= 0;
+ pfs->m_event_id= 1;
+ pfs->m_stmt_lock.set_allocated();
+ pfs->m_session_lock.set_allocated();
+ pfs->set_enabled(true);
+ pfs->set_history(true);
+ pfs->m_class= klass;
+ pfs->m_events_waits_current= & pfs->m_events_waits_stack[WAIT_STACK_BOTTOM];
+ pfs->m_waits_history_full= false;
+ pfs->m_waits_history_index= 0;
+ pfs->m_stages_history_full= false;
+ pfs->m_stages_history_index= 0;
+ pfs->m_statements_history_full= false;
+ pfs->m_statements_history_index= 0;
+ pfs->m_transactions_history_full= false;
+ pfs->m_transactions_history_index= 0;
+
+ pfs->reset_stats();
+ pfs->reset_session_connect_attrs();
- if (thread_full)
- {
- thread_lost++;
- return NULL;
- }
+ pfs->m_filename_hash_pins= NULL;
+ pfs->m_table_share_hash_pins= NULL;
+ pfs->m_setup_actor_hash_pins= NULL;
+ pfs->m_setup_object_hash_pins= NULL;
+ pfs->m_user_hash_pins= NULL;
+ pfs->m_account_hash_pins= NULL;
+ pfs->m_host_hash_pins= NULL;
+ pfs->m_digest_hash_pins= NULL;
+ pfs->m_program_hash_pins= NULL;
+
+ pfs->m_username_length= 0;
+ pfs->m_hostname_length= 0;
+ pfs->m_dbname_length= 0;
+ pfs->m_command= 0;
+ pfs->m_start_time= 0;
+ pfs->m_stage= 0;
+ pfs->m_stage_progress= NULL;
+ pfs->m_processlist_info[0]= '\0';
+ pfs->m_processlist_info_length= 0;
+ pfs->m_connection_type= VIO_CLOSED;
+
+ pfs->m_thd= NULL;
+ pfs->m_host= NULL;
+ pfs->m_user= NULL;
+ pfs->m_account= NULL;
+ set_thread_account(pfs);
- while (++attempts <= thread_max)
- {
- /* See create_mutex() */
- index= PFS_atomic::add_u32(& thread_monotonic_index, 1) % thread_max;
- pfs= thread_array + index;
+ /*
+ For child waits, by default,
+ - NESTING_EVENT_ID is NULL
+ - NESTING_EVENT_TYPE is NULL
+ */
+ PFS_events_waits *child_wait= & pfs->m_events_waits_stack[0];
+ child_wait->m_event_id= 0;
- if (pfs->m_lock.is_free())
- {
- if (pfs->m_lock.free_to_dirty())
- {
- pfs->m_thread_internal_id=
- PFS_atomic::add_u64(&thread_internal_id_counter, 1);
- pfs->m_parent_thread_internal_id= 0;
- pfs->m_processlist_id= (ulong)processlist_id;
- pfs->m_event_id= 1;
- pfs->m_stmt_lock.set_allocated();
- pfs->m_session_lock.set_allocated();
- pfs->m_enabled= true;
- pfs->m_class= klass;
- pfs->m_events_waits_current= & pfs->m_events_waits_stack[WAIT_STACK_BOTTOM];
- pfs->m_waits_history_full= false;
- pfs->m_waits_history_index= 0;
- pfs->m_stages_history_full= false;
- pfs->m_stages_history_index= 0;
- pfs->m_statements_history_full= false;
- 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;
- pfs->m_setup_actor_hash_pins= NULL;
- pfs->m_setup_object_hash_pins= NULL;
- pfs->m_user_hash_pins= NULL;
- pfs->m_account_hash_pins= NULL;
- pfs->m_host_hash_pins= NULL;
- pfs->m_digest_hash_pins= NULL;
-
- pfs->m_username_length= 0;
- pfs->m_hostname_length= 0;
- pfs->m_dbname_length= 0;
- pfs->m_command= 0;
- pfs->m_start_time= 0;
- pfs->m_stage= 0;
- pfs->m_processlist_info[0]= '\0';
- pfs->m_processlist_info_length= 0;
-
- pfs->m_host= NULL;
- pfs->m_user= NULL;
- pfs->m_account= NULL;
- set_thread_account(pfs);
-
- PFS_events_waits *child_wait;
- for (index= 0; index < WAIT_STACK_SIZE; index++)
- {
- child_wait= & pfs->m_events_waits_stack[index];
- child_wait->m_thread_internal_id= pfs->m_thread_internal_id;
- child_wait->m_event_id= 0;
- child_wait->m_end_event_id= 0;
- child_wait->m_event_type= EVENT_TYPE_STATEMENT;
- child_wait->m_wait_class= NO_WAIT_CLASS;
- }
-
- PFS_events_stages *child_stage= & pfs->m_stage_current;
- child_stage->m_thread_internal_id= pfs->m_thread_internal_id;
- child_stage->m_event_id= 0;
- child_stage->m_end_event_id= 0;
- child_stage->m_event_type= EVENT_TYPE_STATEMENT;
- child_stage->m_class= NULL;
- child_stage->m_timer_start= 0;
- child_stage->m_timer_end= 0;
- child_stage->m_source_file= NULL;
- child_stage->m_source_line= 0;
-
- PFS_events_statements *child_statement;
- for (index= 0; index < statement_stack_max; index++)
- {
- child_statement= & pfs->m_statement_stack[index];
- child_statement->m_thread_internal_id= pfs->m_thread_internal_id;
- child_statement->m_event_id= 0;
- child_statement->m_end_event_id= 0;
- child_statement->m_event_type= EVENT_TYPE_STATEMENT;
- child_statement->m_class= NULL;
- child_statement->m_timer_start= 0;
- child_statement->m_timer_end= 0;
- child_statement->m_lock_time= 0;
- child_statement->m_source_file= NULL;
- child_statement->m_source_line= 0;
- child_statement->m_current_schema_name_length= 0;
- child_statement->m_sqltext_length= 0;
-
- child_statement->m_message_text[0]= '\0';
- child_statement->m_sql_errno= 0;
- child_statement->m_sqlstate[0]= '\0';
- child_statement->m_error_count= 0;
- child_statement->m_warning_count= 0;
- child_statement->m_rows_affected= 0;
-
- child_statement->m_rows_sent= 0;
- child_statement->m_rows_examined= 0;
- child_statement->m_created_tmp_disk_tables= 0;
- child_statement->m_created_tmp_tables= 0;
- child_statement->m_select_full_join= 0;
- child_statement->m_select_full_range_join= 0;
- child_statement->m_select_range= 0;
- child_statement->m_select_range_check= 0;
- child_statement->m_select_scan= 0;
- child_statement->m_sort_merge_passes= 0;
- child_statement->m_sort_range= 0;
- child_statement->m_sort_rows= 0;
- child_statement->m_sort_scan= 0;
- child_statement->m_no_index_used= 0;
- child_statement->m_no_good_index_used= 0;
- }
- pfs->m_events_statements_count= 0;
-
- pfs->m_lock.dirty_to_allocated();
- return pfs;
- }
- }
+ /*
+ For child stages, by default,
+ - NESTING_EVENT_ID is NULL
+ - NESTING_EVENT_TYPE is NULL
+ */
+ PFS_events_stages *child_stage= & pfs->m_stage_current;
+ child_stage->m_nesting_event_id= 0;
+
+ pfs->m_events_statements_count= 0;
+ pfs->m_transaction_current.m_event_id= 0;
+
+ pfs->m_lock.dirty_to_allocated(& dirty_state);
}
- thread_lost++;
- thread_full= true;
- return NULL;
+ return pfs;
}
PFS_mutex *sanitize_mutex(PFS_mutex *unsafe)
{
- SANITIZE_ARRAY_BODY(PFS_mutex, mutex_array, mutex_max, unsafe);
+ return global_mutex_container.sanitize(unsafe);
}
PFS_rwlock *sanitize_rwlock(PFS_rwlock *unsafe)
{
- SANITIZE_ARRAY_BODY(PFS_rwlock, rwlock_array, rwlock_max, unsafe);
+ return global_rwlock_container.sanitize(unsafe);
}
PFS_cond *sanitize_cond(PFS_cond *unsafe)
{
- SANITIZE_ARRAY_BODY(PFS_cond, cond_array, cond_max, unsafe);
+ return global_cond_container.sanitize(unsafe);
}
/**
@@ -1100,17 +625,22 @@ PFS_cond *sanitize_cond(PFS_cond *unsafe)
*/
PFS_thread *sanitize_thread(PFS_thread *unsafe)
{
- SANITIZE_ARRAY_BODY(PFS_thread, thread_array, thread_max, unsafe);
+ return global_thread_container.sanitize(unsafe);
}
PFS_file *sanitize_file(PFS_file *unsafe)
{
- SANITIZE_ARRAY_BODY(PFS_file, file_array, file_max, unsafe);
+ return global_file_container.sanitize(unsafe);
}
PFS_socket *sanitize_socket(PFS_socket *unsafe)
{
- SANITIZE_ARRAY_BODY(PFS_socket, socket_array, socket_max, unsafe);
+ return global_socket_container.sanitize(unsafe);
+}
+
+PFS_metadata_lock *sanitize_metadata_lock(PFS_metadata_lock *unsafe)
+{
+ return global_mdl_container.sanitize(unsafe);
}
/**
@@ -1181,12 +711,16 @@ void destroy_thread(PFS_thread *pfs)
lf_hash_put_pins(pfs->m_digest_hash_pins);
pfs->m_digest_hash_pins= NULL;
}
- pfs->m_lock.allocated_to_free();
- thread_full= false;
+ if (pfs->m_program_hash_pins)
+ {
+ lf_hash_put_pins(pfs->m_program_hash_pins);
+ pfs->m_program_hash_pins= NULL;
+ }
+ global_thread_container.deallocate(pfs);
}
/**
- Get the hash pins for @filename_hash.
+ Get the hash pins for @c filename_hash.
@param thread The running thread.
@returns The LF_HASH pins for the thread.
*/
@@ -1221,7 +755,7 @@ find_or_create_file(PFS_thread *thread, PFS_file_class *klass,
LF_PINS *pins= get_filename_hash_pins(thread);
if (unlikely(pins == NULL))
{
- file_lost++;
+ global_file_container.m_lost++;
return NULL;
}
@@ -1272,6 +806,7 @@ find_or_create_file(PFS_thread *thread, PFS_file_class *klass,
char dirbuffer[FN_REFLEN];
size_t dirlen;
const char *normalized_filename;
+ uint normalized_length;
dirlen= dirname_length(safe_filename);
if (dirlen == 0)
@@ -1288,7 +823,7 @@ find_or_create_file(PFS_thread *thread, PFS_file_class *klass,
if (my_realpath(buffer, dirbuffer, MYF(0)) != 0)
{
- file_lost++;
+ global_file_container.m_lost++;
return NULL;
}
@@ -1302,14 +837,12 @@ find_or_create_file(PFS_thread *thread, PFS_file_class *klass,
*buf_end= '\0';
normalized_filename= buffer;
- uint normalized_length= static_cast<uint>(strlen(normalized_filename));
+ normalized_length= (uint)strlen(normalized_filename);
PFS_file **entry;
uint retry_count= 0;
const uint retry_max= 3;
- static uint PFS_ALIGNED file_monotonic_index= 0;
- uint index;
- uint attempts= 0;
+ pfs_dirty_state dirty_state;
search:
@@ -1332,70 +865,204 @@ search:
return NULL;
}
- if (file_full)
+ pfs= global_file_container.allocate(& dirty_state);
+ if (pfs != NULL)
{
- file_lost++;
- return NULL;
- }
+ pfs->m_class= klass;
+ pfs->m_enabled= klass->m_enabled && flag_global_instrumentation;
+ pfs->m_timed= klass->m_timed;
+ memcpy(pfs->m_filename, normalized_filename, normalized_length);
+ pfs->m_filename[normalized_length]= '\0';
+ pfs->m_filename_length= normalized_length;
+ pfs->m_file_stat.m_open_count= 1;
+ pfs->m_file_stat.m_io_stat.reset();
+ pfs->m_identity= (const void *)pfs;
+ pfs->m_temporary= false;
+
+ int res;
+ pfs->m_lock.dirty_to_allocated(& dirty_state);
+ res= lf_hash_insert(&filename_hash, pins,
+ &pfs);
+ if (likely(res == 0))
+ {
+ if (klass->is_singleton())
+ klass->m_singleton= pfs;
+ return pfs;
+ }
- while (++attempts <= file_max)
- {
- /* See create_mutex() */
- index= PFS_atomic::add_u32(& file_monotonic_index, 1) % file_max;
- pfs= file_array + index;
+ global_file_container.deallocate(pfs);
- if (pfs->m_lock.is_free())
+ if (res > 0)
{
- if (pfs->m_lock.free_to_dirty())
+ /* Duplicate insert by another thread */
+ if (++retry_count > retry_max)
{
- pfs->m_class= klass;
- pfs->m_enabled= klass->m_enabled && flag_global_instrumentation;
- pfs->m_timed= klass->m_timed;
- strncpy(pfs->m_filename, normalized_filename, normalized_length + 1);
- pfs->m_filename[normalized_length]= '\0';
- pfs->m_filename_length= normalized_length;
- pfs->m_file_stat.m_open_count= 1;
- pfs->m_file_stat.m_io_stat.reset();
- pfs->m_identity= (const void *)pfs;
-
- int res;
- res= lf_hash_insert(&filename_hash, thread->m_filename_hash_pins,
- &pfs);
- if (likely(res == 0))
- {
- pfs->m_lock.dirty_to_allocated();
- if (klass->is_singleton())
- klass->m_singleton= pfs;
- return pfs;
- }
-
- pfs->m_lock.dirty_to_free();
-
- if (res > 0)
- {
- /* Duplicate insert by another thread */
- if (++retry_count > retry_max)
- {
- /* Avoid infinite loops */
- file_lost++;
- return NULL;
- }
- goto search;
- }
-
- /* OOM in lf_hash_insert */
- file_lost++;
+ /* Avoid infinite loops */
+ global_file_container.m_lost++;
return NULL;
}
+ goto search;
}
+
+ /* OOM in lf_hash_insert */
+ global_file_container.m_lost++;
+ return NULL;
}
- file_lost++;
- file_full= true;
return NULL;
}
/**
+ Find a file instrumentation instance by name, and rename it
+ @param thread the executing instrumented thread
+ @param old_filename the file to be renamed
+ @param old_len the length in bytes of the old filename
+ @param new_filename the new file name
+ @param new_len the length in bytes of the new filename
+*/
+void find_and_rename_file(PFS_thread *thread, const char *old_filename,
+ uint old_len, const char *new_filename, uint new_len)
+{
+ PFS_file *pfs;
+
+ DBUG_ASSERT(thread != NULL);
+
+ LF_PINS *pins= get_filename_hash_pins(thread);
+ if (unlikely(pins == NULL))
+ {
+ global_file_container.m_lost++;
+ return;
+ }
+
+ /*
+ Normalize the old file name.
+ */
+ char safe_buffer[FN_REFLEN];
+ const char *safe_filename;
+
+ if (old_len >= FN_REFLEN)
+ {
+ memcpy(safe_buffer, old_filename, FN_REFLEN - 1);
+ safe_buffer[FN_REFLEN - 1]= 0;
+ safe_filename= safe_buffer;
+ }
+ else
+ safe_filename= old_filename;
+
+ char buffer[FN_REFLEN];
+ char dirbuffer[FN_REFLEN];
+ size_t dirlen;
+ const char *normalized_filename;
+ uint normalized_length;
+
+ dirlen= dirname_length(safe_filename);
+ if (dirlen == 0)
+ {
+ dirbuffer[0]= FN_CURLIB;
+ dirbuffer[1]= FN_LIBCHAR;
+ dirbuffer[2]= '\0';
+ }
+ else
+ {
+ memcpy(dirbuffer, safe_filename, dirlen);
+ dirbuffer[dirlen]= '\0';
+ }
+
+ if (my_realpath(buffer, dirbuffer, MYF(0)) != 0)
+ {
+ global_file_container.m_lost++;
+ return;
+ }
+
+ /* 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) && (*(ptr-1) != FN_LIBCHAR))
+ *ptr++= FN_LIBCHAR;
+ if (buf_end > ptr)
+ strncpy(ptr, safe_filename + dirlen, buf_end - ptr);
+ *buf_end= '\0';
+
+ normalized_filename= buffer;
+ normalized_length= (uint)strlen(normalized_filename);
+
+ PFS_file **entry;
+ entry= reinterpret_cast<PFS_file**>
+ (lf_hash_search(&filename_hash, pins,
+ normalized_filename, normalized_length));
+
+ if (entry && (entry != MY_ERRPTR))
+ pfs= *entry;
+ else
+ {
+ lf_hash_search_unpin(pins);
+ return;
+ }
+
+ lf_hash_delete(&filename_hash, pins,
+ pfs->m_filename, pfs->m_filename_length);
+
+ /*
+ Normalize the new file name.
+ */
+ if (new_len >= FN_REFLEN)
+ {
+ memcpy(safe_buffer, new_filename, FN_REFLEN - 1);
+ safe_buffer[FN_REFLEN - 1]= 0;
+ safe_filename= safe_buffer;
+ }
+ else
+ safe_filename= new_filename;
+
+ dirlen= dirname_length(safe_filename);
+ if (dirlen == 0)
+ {
+ dirbuffer[0]= FN_CURLIB;
+ dirbuffer[1]= FN_LIBCHAR;
+ dirbuffer[2]= '\0';
+ }
+ else
+ {
+ memcpy(dirbuffer, safe_filename, dirlen);
+ dirbuffer[dirlen]= '\0';
+ }
+
+ if (my_realpath(buffer, dirbuffer, MYF(0)) != 0)
+ {
+ global_file_container.m_lost++;
+ return;
+ }
+
+ /* Append the unresolved file name to the resolved path */
+ ptr= buffer + strlen(buffer);
+ buf_end= &buffer[sizeof(buffer)-1];
+ if ((buf_end > ptr) && (*(ptr-1) != FN_LIBCHAR))
+ *ptr++= FN_LIBCHAR;
+ if (buf_end > ptr)
+ strncpy(ptr, safe_filename + dirlen, buf_end - ptr);
+ *buf_end= '\0';
+
+ normalized_filename= buffer;
+ normalized_length= (uint)strlen(normalized_filename);
+
+ memcpy(pfs->m_filename, normalized_filename, normalized_length);
+ pfs->m_filename[normalized_length]= '\0';
+ pfs->m_filename_length= normalized_length;
+
+ int res;
+ res= lf_hash_insert(&filename_hash, pins, &pfs);
+
+ if (likely(res == 0))
+ return;
+ else
+ {
+ global_file_container.deallocate(pfs);
+ global_file_container.m_lost++;
+ return;
+ }
+}
+
+/**
Release instrumentation for a file instance.
@param pfs the file to release
*/
@@ -1430,8 +1097,8 @@ void destroy_file(PFS_thread *thread, PFS_file *pfs)
pfs->m_filename, pfs->m_filename_length);
if (klass->is_singleton())
klass->m_singleton= NULL;
- pfs->m_lock.allocated_to_free();
- file_full= false;
+
+ global_file_container.deallocate(pfs);
}
/**
@@ -1444,49 +1111,32 @@ 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 PFS_ALIGNED table_monotonic_index= 0;
- uint index;
- uint attempts= 0;
PFS_table *pfs;
-
- if (table_full)
- {
- table_lost++;
- return NULL;
- }
-
- while (++attempts <= table_max)
- {
- /* See create_mutex() */
- index= PFS_atomic::add_u32(& table_monotonic_index, 1) % table_max;
- pfs= table_array + index;
-
- if (pfs->m_lock.is_free())
- {
- if (pfs->m_lock.free_to_dirty())
- {
- pfs->m_identity= identity;
- pfs->m_share= share;
- pfs->m_io_enabled= share->m_enabled &&
- flag_global_instrumentation && global_table_io_class.m_enabled;
- pfs->m_io_timed= share->m_timed && global_table_io_class.m_timed;
- pfs->m_lock_enabled= share->m_enabled &&
- flag_global_instrumentation && global_table_lock_class.m_enabled;
- pfs->m_lock_timed= share->m_timed && global_table_lock_class.m_timed;
- pfs->m_has_io_stats= false;
- pfs->m_has_lock_stats= false;
- share->inc_refcount();
- pfs->m_table_stat.fast_reset();
- pfs->m_thread_owner= opening_thread;
- pfs->m_lock.dirty_to_allocated();
- return pfs;
- }
- }
+ pfs_dirty_state dirty_state;
+
+ pfs= global_table_container.allocate(& dirty_state);
+ if (pfs != NULL)
+ {
+ pfs->m_identity= identity;
+ pfs->m_share= share;
+ pfs->m_io_enabled= share->m_enabled &&
+ flag_global_instrumentation && global_table_io_class.m_enabled;
+ pfs->m_io_timed= share->m_timed && global_table_io_class.m_timed;
+ pfs->m_lock_enabled= share->m_enabled &&
+ flag_global_instrumentation && global_table_lock_class.m_enabled;
+ pfs->m_lock_timed= share->m_timed && global_table_lock_class.m_timed;
+ pfs->m_has_io_stats= false;
+ pfs->m_has_lock_stats= false;
+ pfs->m_internal_lock= PFS_TL_NONE;
+ pfs->m_external_lock= PFS_TL_NONE;
+ share->inc_refcount();
+ pfs->m_table_stat.fast_reset();
+ pfs->m_thread_owner= opening_thread;
+ pfs->m_owner_event_id= opening_thread->m_event_id;
+ pfs->m_lock.dirty_to_allocated(& dirty_state);
}
- table_lost++;
- table_full= true;
- return NULL;
+ return pfs;
}
void PFS_table::sanitized_aggregate(void)
@@ -1498,18 +1148,12 @@ void PFS_table::sanitized_aggregate(void)
PFS_table_share *safe_share= sanitize_table_share(m_share);
if (safe_share != NULL)
{
- if (m_has_io_stats && m_has_lock_stats)
+ if (m_has_io_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);
+ safe_aggregate_io(NULL, & m_table_stat, safe_share);
m_has_io_stats= false;
}
- else if (m_has_lock_stats)
+ if (m_has_lock_stats)
{
safe_aggregate_lock(& m_table_stat, safe_share);
m_has_lock_stats= false;
@@ -1522,7 +1166,7 @@ void PFS_table::sanitized_aggregate_io(void)
PFS_table_share *safe_share= sanitize_table_share(m_share);
if (safe_share != NULL && m_has_io_stats)
{
- safe_aggregate_io(& m_table_stat, safe_share);
+ safe_aggregate_io(NULL, & m_table_stat, safe_share);
m_has_io_stats= false;
}
}
@@ -1537,29 +1181,67 @@ void PFS_table::sanitized_aggregate_lock(void)
}
}
-void PFS_table::safe_aggregate(PFS_table_stat *table_stat,
- PFS_table_share *table_share)
+void PFS_table::safe_aggregate_io(const TABLE_SHARE *optional_server_share,
+ PFS_table_stat *table_stat,
+ PFS_table_share *table_share)
{
DBUG_ASSERT(table_stat != NULL);
DBUG_ASSERT(table_share != NULL);
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, key_count);
- table_stat->fast_reset();
-}
+ PFS_table_share_index *to_stat;
+ PFS_table_io_stat *from_stat;
+ uint index;
-void PFS_table::safe_aggregate_io(PFS_table_stat *table_stat,
- PFS_table_share *table_share)
-{
- DBUG_ASSERT(table_stat != NULL);
- DBUG_ASSERT(table_share != NULL);
+ DBUG_ASSERT(key_count <= MAX_INDEXES);
- uint key_count= sanitize_index_count(table_share->m_key_count);
+ /* Aggregate stats for each index, if any */
+ for (index= 0; index < key_count; index++)
+ {
+ from_stat= & table_stat->m_index_stat[index];
+ if (from_stat->m_has_data)
+ {
+ if (optional_server_share != NULL)
+ {
+ /*
+ An instrumented thread is closing a table,
+ and capable of providing index names when
+ creating index statistics on the fly.
+ */
+ to_stat= table_share->find_or_create_index_stat(optional_server_share, index);
+ }
+ else
+ {
+ /*
+ A monitoring thread, performing TRUNCATE TABLE,
+ is asking to flush existing stats from table handles,
+ but it does not know about index names used in handles.
+ If the index stat already exists, find it and aggregate to it.
+ It the index stat does not exist yet, drop the stat and do nothing.
+ */
+ to_stat= table_share->find_index_stat(index);
+ }
+ if (to_stat != NULL)
+ {
+ /* Aggregate to TABLE_IO_SUMMARY */
+ to_stat->m_stat.aggregate(from_stat);
+ }
+ }
+ }
+
+ /* Aggregate stats for the table */
+ from_stat= & table_stat->m_index_stat[MAX_INDEXES];
+ if (from_stat->m_has_data)
+ {
+ to_stat= table_share->find_or_create_index_stat(NULL, MAX_INDEXES);
+ if (to_stat != NULL)
+ {
+ /* Aggregate to TABLE_IO_SUMMARY */
+ to_stat->m_stat.aggregate(from_stat);
+ }
+ }
- /* Aggregate to TABLE_IO_SUMMARY */
- table_share->m_table_stat.aggregate_io(table_stat, key_count);
table_stat->fast_reset_io();
}
@@ -1569,8 +1251,17 @@ void PFS_table::safe_aggregate_lock(PFS_table_stat *table_stat,
DBUG_ASSERT(table_stat != NULL);
DBUG_ASSERT(table_share != NULL);
- /* Aggregate to TABLE_LOCK_SUMMARY */
- table_share->m_table_stat.aggregate_lock(table_stat);
+ PFS_table_lock_stat *from_stat= & table_stat->m_lock_stat;
+
+ PFS_table_share_lock *to_stat;
+
+ to_stat= table_share->find_or_create_lock_stat();
+ if (to_stat != NULL)
+ {
+ /* Aggregate to TABLE_LOCK_SUMMARY */
+ to_stat->m_stat.aggregate(from_stat);
+ }
+
table_stat->fast_reset_lock();
}
@@ -1582,29 +1273,22 @@ void destroy_table(PFS_table *pfs)
{
DBUG_ASSERT(pfs != NULL);
pfs->m_share->dec_refcount();
- pfs->m_lock.allocated_to_free();
- table_full= false;
+ global_table_container.deallocate(pfs);
}
/**
Create instrumentation for a socket instance.
@param klass the socket class
- @param identity the socket descriptor
+ @param fd the socket file descriptor
+ @param addr the socket address
+ @param addr_len the socket address length
@return a socket instance, or NULL
*/
PFS_socket* create_socket(PFS_socket_class *klass, const my_socket *fd,
const struct sockaddr *addr, socklen_t addr_len)
{
- static uint PFS_ALIGNED socket_monotonic_index= 0;
- uint index;
- uint attempts= 0;
PFS_socket *pfs;
-
- if (socket_full)
- {
- socket_lost++;
- return NULL;
- }
+ pfs_dirty_state dirty_state;
uint fd_used= 0;
uint addr_len_used= addr_len;
@@ -1615,48 +1299,38 @@ PFS_socket* create_socket(PFS_socket_class *klass, const my_socket *fd,
if (addr_len_used > sizeof(sockaddr_storage))
addr_len_used= sizeof(sockaddr_storage);
- while (++attempts <= socket_max)
+ pfs= global_socket_container.allocate(& dirty_state);
+
+ if (pfs != NULL)
{
- index= PFS_atomic::add_u32(& socket_monotonic_index, 1) % socket_max;
- pfs= socket_array + index;
+ 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;
- if (pfs->m_lock.is_free())
+ pfs->m_addr_len= addr_len_used;
+ if ((addr != NULL) && (addr_len_used > 0))
{
- 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_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;
- 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(& dirty_state);
+
+ if (klass->is_singleton())
+ klass->m_singleton= pfs;
}
- socket_lost++;
- socket_full= true;
- return NULL;
+ return pfs;
}
/**
@@ -1678,67 +1352,112 @@ void destroy_socket(PFS_socket *pfs)
PFS_thread *thread= pfs->m_thread_owner;
if (thread != NULL)
{
- PFS_single_stat *event_name_array;
- event_name_array= thread->m_instr_class_waits_stats;
- uint index= pfs->m_class->m_event_name_index;
-
/* Combine stats for all operations */
PFS_single_stat stat;
pfs->m_socket_stat.m_io_stat.sum_waits(&stat);
- event_name_array[index].aggregate(&stat);
+ if (stat.m_count != 0)
+ {
+ PFS_single_stat *event_name_array;
+ event_name_array= thread->write_instr_class_waits_stats();
+ uint index= pfs->m_class->m_event_name_index;
+
+ event_name_array[index].aggregate(&stat);
+ }
}
pfs->m_socket_stat.reset();
pfs->m_thread_owner= NULL;
pfs->m_fd= 0;
pfs->m_addr_len= 0;
- pfs->m_lock.allocated_to_free();
- socket_full= false;
+
+ global_socket_container.deallocate(pfs);
+}
+
+PFS_metadata_lock* create_metadata_lock(void *identity,
+ const MDL_key *mdl_key,
+ opaque_mdl_type mdl_type,
+ opaque_mdl_duration mdl_duration,
+ opaque_mdl_status mdl_status,
+ const char *src_file,
+ uint src_line)
+{
+ PFS_metadata_lock *pfs;
+ pfs_dirty_state dirty_state;
+
+ pfs= global_mdl_container.allocate(& dirty_state);
+ if (pfs != NULL)
+ {
+ pfs->m_identity= identity;
+ pfs->m_enabled= global_metadata_class.m_enabled && flag_global_instrumentation;
+ pfs->m_timed= global_metadata_class.m_timed;
+ pfs->m_mdl_key.mdl_key_init(mdl_key);
+ pfs->m_mdl_type= mdl_type;
+ pfs->m_mdl_duration= mdl_duration;
+ pfs->m_mdl_status= mdl_status;
+ pfs->m_src_file= src_file;
+ pfs->m_src_line= src_line;
+ pfs->m_owner_thread_id= 0;
+ pfs->m_owner_event_id= 0;
+ pfs->m_lock.dirty_to_allocated(& dirty_state);
+ }
+
+ return pfs;
+}
+
+void destroy_metadata_lock(PFS_metadata_lock *pfs)
+{
+ DBUG_ASSERT(pfs != NULL);
+ global_mdl_container.deallocate(pfs);
+}
+
+static void fct_reset_mutex_waits(PFS_mutex *pfs)
+{
+ pfs->m_mutex_stat.reset();
}
static void reset_mutex_waits_by_instance(void)
{
- PFS_mutex *pfs= mutex_array;
- PFS_mutex *pfs_last= mutex_array + mutex_max;
+ global_mutex_container.apply_all(fct_reset_mutex_waits);
+}
- for ( ; pfs < pfs_last; pfs++)
- pfs->m_mutex_stat.reset();
+static void fct_reset_rwlock_waits(PFS_rwlock *pfs)
+{
+ pfs->m_rwlock_stat.reset();
}
static void reset_rwlock_waits_by_instance(void)
{
- PFS_rwlock *pfs= rwlock_array;
- PFS_rwlock *pfs_last= rwlock_array + rwlock_max;
+ global_rwlock_container.apply_all(fct_reset_rwlock_waits);
+}
- for ( ; pfs < pfs_last; pfs++)
- pfs->m_rwlock_stat.reset();
+static void fct_reset_cond_waits(PFS_cond *pfs)
+{
+ pfs->m_cond_stat.reset();
}
static void reset_cond_waits_by_instance(void)
{
- PFS_cond *pfs= cond_array;
- PFS_cond *pfs_last= cond_array + cond_max;
+ global_cond_container.apply_all(fct_reset_cond_waits);
+}
- for ( ; pfs < pfs_last; pfs++)
- pfs->m_cond_stat.reset();
+static void fct_reset_file_waits(PFS_file *pfs)
+{
+ pfs->m_file_stat.reset();
}
static void reset_file_waits_by_instance(void)
{
- PFS_file *pfs= file_array;
- PFS_file *pfs_last= file_array + file_max;
+ global_file_container.apply_all(fct_reset_file_waits);
+}
- for ( ; pfs < pfs_last; pfs++)
- pfs->m_file_stat.reset();
+static void fct_reset_socket_waits(PFS_socket *pfs)
+{
+ pfs->m_socket_stat.reset();
}
static void reset_socket_waits_by_instance(void)
{
- PFS_socket *pfs= socket_array;
- PFS_socket *pfs_last= socket_array + socket_max;
-
- for ( ; pfs < pfs_last; pfs++)
- pfs->m_socket_stat.reset();
+ global_socket_container.apply_all(fct_reset_socket_waits);
}
/** Reset the wait statistics per object instance. */
@@ -1751,24 +1470,26 @@ void reset_events_waits_by_instance(void)
reset_socket_waits_by_instance();
}
+static void fct_reset_file_io(PFS_file *pfs)
+{
+ pfs->m_file_stat.m_io_stat.reset();
+}
+
/** Reset the io statistics per file instance. */
void reset_file_instance_io(void)
{
- PFS_file *pfs= file_array;
- PFS_file *pfs_last= file_array + file_max;
+ global_file_container.apply_all(fct_reset_file_io);
+}
- for ( ; pfs < pfs_last; pfs++)
- pfs->m_file_stat.m_io_stat.reset();
+static void fct_reset_socket_io(PFS_socket *pfs)
+{
+ pfs->m_socket_stat.m_io_stat.reset();
}
/** Reset the io statistics per socket instance. */
void reset_socket_instance_io(void)
{
- PFS_socket *pfs= socket_array;
- PFS_socket *pfs_last= socket_array + socket_max;
-
- for ( ; pfs < pfs_last; pfs++)
- pfs->m_socket_stat.m_io_stat.reset();
+ global_socket_container.apply_all(fct_reset_socket_io);
}
void aggregate_all_event_names(PFS_single_stat *from_array,
@@ -1909,6 +1630,124 @@ void aggregate_all_statements(PFS_statement_stat *from_array,
}
}
+void aggregate_all_transactions(PFS_transaction_stat *from_array,
+ PFS_transaction_stat *to_array)
+{
+ DBUG_ASSERT(from_array != NULL);
+ DBUG_ASSERT(to_array != NULL);
+
+ if (from_array->count() > 0)
+ {
+ to_array->aggregate(from_array);
+ from_array->reset();
+ }
+}
+
+void aggregate_all_transactions(PFS_transaction_stat *from_array,
+ PFS_transaction_stat *to_array_1,
+ PFS_transaction_stat *to_array_2)
+{
+ DBUG_ASSERT(from_array != NULL);
+ DBUG_ASSERT(to_array_1 != NULL);
+ DBUG_ASSERT(to_array_2 != NULL);
+
+ if (from_array->count() > 0)
+ {
+ to_array_1->aggregate(from_array);
+ to_array_2->aggregate(from_array);
+ from_array->reset();
+ }
+}
+
+void aggregate_all_memory(bool alive,
+ PFS_memory_stat *from_array,
+ PFS_memory_stat *to_array)
+{
+ PFS_memory_stat *from;
+ PFS_memory_stat *from_last;
+ PFS_memory_stat *to;
+
+ from= from_array;
+ from_last= from_array + memory_class_max;
+ to= to_array;
+
+ if (alive)
+ {
+ for ( ; from < from_last ; from++, to++)
+ {
+ from->partial_aggregate_to(to);
+ }
+ }
+ else
+ {
+ for ( ; from < from_last ; from++, to++)
+ {
+ from->full_aggregate_to(to);
+ from->reset();
+ }
+ }
+}
+
+void aggregate_all_memory(bool alive,
+ PFS_memory_stat *from_array,
+ PFS_memory_stat *to_array_1,
+ PFS_memory_stat *to_array_2)
+{
+ PFS_memory_stat *from;
+ PFS_memory_stat *from_last;
+ PFS_memory_stat *to_1;
+ PFS_memory_stat *to_2;
+
+ from= from_array;
+ from_last= from_array + memory_class_max;
+ to_1= to_array_1;
+ to_2= to_array_2;
+
+ if (alive)
+ {
+ for ( ; from < from_last ; from++, to_1++, to_2++)
+ {
+ from->partial_aggregate_to(to_1, to_2);
+ }
+ }
+ else
+ {
+ for ( ; from < from_last ; from++, to_1++, to_2++)
+ {
+ from->full_aggregate_to(to_1, to_2);
+ from->reset();
+ }
+ }
+}
+
+void aggregate_thread_status(PFS_thread *thread,
+ PFS_account *safe_account,
+ PFS_user *safe_user,
+ PFS_host *safe_host)
+{
+ THD *thd= thread->m_thd;
+
+ if (thd == NULL)
+ return;
+
+ if (likely(safe_account != NULL))
+ {
+ safe_account->aggregate_status_stats(&thd->status_var);
+ return;
+ }
+
+ if (safe_user != NULL)
+ {
+ safe_user->aggregate_status_stats(&thd->status_var);
+ }
+
+ if (safe_host != NULL)
+ {
+ safe_host->aggregate_status_stats(&thd->status_var);
+ }
+ return;
+}
+
void aggregate_thread_stats(PFS_thread *thread,
PFS_account *safe_account,
PFS_user *safe_user,
@@ -1917,14 +1756,17 @@ void aggregate_thread_stats(PFS_thread *thread,
if (likely(safe_account != NULL))
{
safe_account->m_disconnected_count++;
- return;
}
if (safe_user != NULL)
+ {
safe_user->m_disconnected_count++;
+ }
if (safe_host != NULL)
+ {
safe_host->m_disconnected_count++;
+ }
/* There is no global table for connections statistics. */
return;
@@ -1935,9 +1777,28 @@ void aggregate_thread(PFS_thread *thread,
PFS_user *safe_user,
PFS_host *safe_host)
{
+ /* No HAVE_PSI_???_INTERFACE flag, waits cover multiple instrumentations */
aggregate_thread_waits(thread, safe_account, safe_user, safe_host);
+
+#ifdef HAVE_PSI_STAGE_INTERFACE
aggregate_thread_stages(thread, safe_account, safe_user, safe_host);
+#endif
+
+#ifdef HAVE_PSI_STATEMENT_INTERFACE
aggregate_thread_statements(thread, safe_account, safe_user, safe_host);
+#endif
+
+#ifdef HAVE_PSI_TRANSACTION_INTERFACE
+ aggregate_thread_transactions(thread, safe_account, safe_user, safe_host);
+#endif
+
+#ifdef HAVE_PSI_MEMORY_INTERFACE
+ aggregate_thread_memory(false, thread, safe_account, safe_user, safe_host);
+#endif
+
+ if (!show_compatibility_56)
+ aggregate_thread_status(thread, safe_account, safe_user, safe_host);
+
aggregate_thread_stats(thread, safe_account, safe_user, safe_host);
}
@@ -1946,14 +1807,17 @@ void aggregate_thread_waits(PFS_thread *thread,
PFS_user *safe_user,
PFS_host *safe_host)
{
+ if (thread->read_instr_class_waits_stats() == NULL)
+ return;
+
if (likely(safe_account != NULL))
{
/*
Aggregate EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME
to EVENTS_WAITS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME.
*/
- aggregate_all_event_names(thread->m_instr_class_waits_stats,
- safe_account->m_instr_class_waits_stats);
+ aggregate_all_event_names(thread->write_instr_class_waits_stats(),
+ safe_account->write_instr_class_waits_stats());
return;
}
@@ -1966,9 +1830,9 @@ void aggregate_thread_waits(PFS_thread *thread,
- EVENTS_WAITS_SUMMARY_BY_HOST_BY_EVENT_NAME
in parallel.
*/
- aggregate_all_event_names(thread->m_instr_class_waits_stats,
- safe_user->m_instr_class_waits_stats,
- safe_host->m_instr_class_waits_stats);
+ aggregate_all_event_names(thread->write_instr_class_waits_stats(),
+ safe_user->write_instr_class_waits_stats(),
+ safe_host->write_instr_class_waits_stats());
return;
}
@@ -1978,8 +1842,8 @@ void aggregate_thread_waits(PFS_thread *thread,
Aggregate EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME
to EVENTS_WAITS_SUMMARY_BY_USER_BY_EVENT_NAME, directly.
*/
- aggregate_all_event_names(thread->m_instr_class_waits_stats,
- safe_user->m_instr_class_waits_stats);
+ aggregate_all_event_names(thread->write_instr_class_waits_stats(),
+ safe_user->write_instr_class_waits_stats());
return;
}
@@ -1989,8 +1853,8 @@ void aggregate_thread_waits(PFS_thread *thread,
Aggregate EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME
to EVENTS_WAITS_SUMMARY_BY_HOST_BY_EVENT_NAME, directly.
*/
- aggregate_all_event_names(thread->m_instr_class_waits_stats,
- safe_host->m_instr_class_waits_stats);
+ aggregate_all_event_names(thread->write_instr_class_waits_stats(),
+ safe_host->write_instr_class_waits_stats());
return;
}
@@ -2003,14 +1867,17 @@ void aggregate_thread_stages(PFS_thread *thread,
PFS_user *safe_user,
PFS_host *safe_host)
{
+ if (thread->read_instr_class_stages_stats() == NULL)
+ return;
+
if (likely(safe_account != NULL))
{
/*
Aggregate EVENTS_STAGES_SUMMARY_BY_THREAD_BY_EVENT_NAME
to EVENTS_STAGES_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME.
*/
- aggregate_all_stages(thread->m_instr_class_stages_stats,
- safe_account->m_instr_class_stages_stats);
+ aggregate_all_stages(thread->write_instr_class_stages_stats(),
+ safe_account->write_instr_class_stages_stats());
return;
}
@@ -2023,9 +1890,9 @@ void aggregate_thread_stages(PFS_thread *thread,
- EVENTS_STAGES_SUMMARY_BY_HOST_BY_EVENT_NAME
in parallel.
*/
- aggregate_all_stages(thread->m_instr_class_stages_stats,
- safe_user->m_instr_class_stages_stats,
- safe_host->m_instr_class_stages_stats);
+ aggregate_all_stages(thread->write_instr_class_stages_stats(),
+ safe_user->write_instr_class_stages_stats(),
+ safe_host->write_instr_class_stages_stats());
return;
}
@@ -2037,8 +1904,8 @@ void aggregate_thread_stages(PFS_thread *thread,
- EVENTS_STAGES_SUMMARY_GLOBAL_BY_EVENT_NAME
in parallel.
*/
- aggregate_all_stages(thread->m_instr_class_stages_stats,
- safe_user->m_instr_class_stages_stats,
+ aggregate_all_stages(thread->write_instr_class_stages_stats(),
+ safe_user->write_instr_class_stages_stats(),
global_instr_class_stages_array);
return;
}
@@ -2049,8 +1916,8 @@ void aggregate_thread_stages(PFS_thread *thread,
Aggregate EVENTS_STAGES_SUMMARY_BY_THREAD_BY_EVENT_NAME
to EVENTS_STAGES_SUMMARY_BY_HOST_BY_EVENT_NAME, directly.
*/
- aggregate_all_stages(thread->m_instr_class_stages_stats,
- safe_host->m_instr_class_stages_stats);
+ aggregate_all_stages(thread->write_instr_class_stages_stats(),
+ safe_host->write_instr_class_stages_stats());
return;
}
@@ -2058,7 +1925,7 @@ void aggregate_thread_stages(PFS_thread *thread,
Aggregate EVENTS_STAGES_SUMMARY_BY_THREAD_BY_EVENT_NAME
to EVENTS_STAGES_SUMMARY_GLOBAL_BY_EVENT_NAME.
*/
- aggregate_all_stages(thread->m_instr_class_stages_stats,
+ aggregate_all_stages(thread->write_instr_class_stages_stats(),
global_instr_class_stages_array);
}
@@ -2067,14 +1934,17 @@ void aggregate_thread_statements(PFS_thread *thread,
PFS_user *safe_user,
PFS_host *safe_host)
{
+ if (thread->read_instr_class_statements_stats() == NULL)
+ return;
+
if (likely(safe_account != NULL))
{
/*
Aggregate EVENTS_STATEMENTS_SUMMARY_BY_THREAD_BY_EVENT_NAME
to EVENTS_STATEMENTS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME.
*/
- aggregate_all_statements(thread->m_instr_class_statements_stats,
- safe_account->m_instr_class_statements_stats);
+ aggregate_all_statements(thread->write_instr_class_statements_stats(),
+ safe_account->write_instr_class_statements_stats());
return;
}
@@ -2087,9 +1957,9 @@ void aggregate_thread_statements(PFS_thread *thread,
- EVENTS_STATEMENT_SUMMARY_BY_HOST_BY_EVENT_NAME
in parallel.
*/
- aggregate_all_statements(thread->m_instr_class_statements_stats,
- safe_user->m_instr_class_statements_stats,
- safe_host->m_instr_class_statements_stats);
+ aggregate_all_statements(thread->write_instr_class_statements_stats(),
+ safe_user->write_instr_class_statements_stats(),
+ safe_host->write_instr_class_statements_stats());
return;
}
@@ -2101,8 +1971,8 @@ void aggregate_thread_statements(PFS_thread *thread,
- EVENTS_STATEMENTS_SUMMARY_GLOBAL_BY_EVENT_NAME
in parallel.
*/
- aggregate_all_statements(thread->m_instr_class_statements_stats,
- safe_user->m_instr_class_statements_stats,
+ aggregate_all_statements(thread->write_instr_class_statements_stats(),
+ safe_user->write_instr_class_statements_stats(),
global_instr_class_statements_array);
return;
}
@@ -2113,8 +1983,8 @@ void aggregate_thread_statements(PFS_thread *thread,
Aggregate EVENTS_STATEMENTS_SUMMARY_BY_THREAD_BY_EVENT_NAME
to EVENTS_STATEMENTS_SUMMARY_BY_HOST_BY_EVENT_NAME, directly.
*/
- aggregate_all_statements(thread->m_instr_class_statements_stats,
- safe_host->m_instr_class_statements_stats);
+ aggregate_all_statements(thread->write_instr_class_statements_stats(),
+ safe_host->write_instr_class_statements_stats());
return;
}
@@ -2122,10 +1992,149 @@ void aggregate_thread_statements(PFS_thread *thread,
Aggregate EVENTS_STATEMENTS_SUMMARY_BY_THREAD_BY_EVENT_NAME
to EVENTS_STATEMENTS_SUMMARY_GLOBAL_BY_EVENT_NAME.
*/
- aggregate_all_statements(thread->m_instr_class_statements_stats,
+ aggregate_all_statements(thread->write_instr_class_statements_stats(),
global_instr_class_statements_array);
}
+void aggregate_thread_transactions(PFS_thread *thread,
+ PFS_account *safe_account,
+ PFS_user *safe_user,
+ PFS_host *safe_host)
+{
+ if (thread->read_instr_class_transactions_stats() == NULL)
+ return;
+
+ if (likely(safe_account != NULL))
+ {
+ /*
+ Aggregate EVENTS_TRANSACTIONS_SUMMARY_BY_THREAD_BY_EVENT_NAME
+ to EVENTS_TRANSACTIONS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME.
+ */
+ aggregate_all_transactions(thread->write_instr_class_transactions_stats(),
+ safe_account->write_instr_class_transactions_stats());
+
+ return;
+ }
+
+ if ((safe_user != NULL) && (safe_host != NULL))
+ {
+ /*
+ Aggregate EVENTS_TRANSACTION_SUMMARY_BY_THREAD_BY_EVENT_NAME to:
+ - EVENTS_TRANSACTION_SUMMARY_BY_USER_BY_EVENT_NAME
+ - EVENTS_TRANSACTION_SUMMARY_BY_HOST_BY_EVENT_NAME
+ in parallel.
+ */
+ aggregate_all_transactions(thread->write_instr_class_transactions_stats(),
+ safe_user->write_instr_class_transactions_stats(),
+ safe_host->write_instr_class_transactions_stats());
+ return;
+ }
+
+ if (safe_user != NULL)
+ {
+ /*
+ Aggregate EVENTS_TRANSACTIONS_SUMMARY_BY_THREAD_BY_EVENT_NAME to:
+ - EVENTS_TRANSACTIONS_SUMMARY_BY_USER_BY_EVENT_NAME
+ - EVENTS_TRANSACTIONS_SUMMARY_GLOBAL_BY_EVENT_NAME
+ in parallel.
+ */
+ aggregate_all_transactions(thread->write_instr_class_transactions_stats(),
+ safe_user->write_instr_class_transactions_stats(),
+ &global_transaction_stat);
+ return;
+ }
+
+ if (safe_host != NULL)
+ {
+ /*
+ Aggregate EVENTS_TRANSACTIONS_SUMMARY_BY_THREAD_BY_EVENT_NAME
+ to EVENTS_TRANSACTIONS_SUMMARY_BY_HOST_BY_EVENT_NAME, directly.
+ */
+ aggregate_all_transactions(thread->write_instr_class_transactions_stats(),
+ safe_host->write_instr_class_transactions_stats());
+ return;
+ }
+
+ /*
+ Aggregate EVENTS_TRANSACTIONS_SUMMARY_BY_THREAD_BY_EVENT_NAME
+ to EVENTS_TRANSACTIONS_SUMMARY_GLOBAL_BY_EVENT_NAME.
+ */
+ aggregate_all_transactions(thread->write_instr_class_transactions_stats(),
+ &global_transaction_stat);
+}
+
+void aggregate_thread_memory(bool alive, PFS_thread *thread,
+ PFS_account *safe_account,
+ PFS_user *safe_user,
+ PFS_host *safe_host)
+{
+ if (thread->read_instr_class_memory_stats() == NULL)
+ return;
+
+ if (likely(safe_account != NULL))
+ {
+ /*
+ Aggregate MEMORY_SUMMARY_BY_THREAD_BY_EVENT_NAME
+ to MEMORY_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME.
+ */
+ aggregate_all_memory(alive,
+ thread->write_instr_class_memory_stats(),
+ safe_account->write_instr_class_memory_stats());
+
+ return;
+ }
+
+ if ((safe_user != NULL) && (safe_host != NULL))
+ {
+ /*
+ Aggregate MEMORY_SUMMARY_BY_THREAD_BY_EVENT_NAME to:
+ - MEMORY_SUMMARY_BY_USER_BY_EVENT_NAME
+ - MEMORY_SUMMARY_BY_HOST_BY_EVENT_NAME
+ in parallel.
+ */
+ aggregate_all_memory(alive,
+ thread->write_instr_class_memory_stats(),
+ safe_user->write_instr_class_memory_stats(),
+ safe_host->write_instr_class_memory_stats());
+ return;
+ }
+
+ if (safe_user != NULL)
+ {
+ /*
+ Aggregate MEMORY_SUMMARY_BY_THREAD_BY_EVENT_NAME to:
+ - MEMORY_SUMMARY_BY_USER_BY_EVENT_NAME
+ - MEMORY_SUMMARY_GLOBAL_BY_EVENT_NAME
+ in parallel.
+ */
+ aggregate_all_memory(alive,
+ thread->write_instr_class_memory_stats(),
+ safe_user->write_instr_class_memory_stats(),
+ global_instr_class_memory_array);
+ return;
+ }
+
+ if (safe_host != NULL)
+ {
+ /*
+ Aggregate MEMORY_SUMMARY_BY_THREAD_BY_EVENT_NAME
+ to MEMORY_SUMMARY_BY_HOST_BY_EVENT_NAME, directly.
+ */
+ aggregate_all_memory(alive,
+ thread->write_instr_class_memory_stats(),
+ safe_host->write_instr_class_memory_stats());
+ return;
+ }
+
+ /*
+ Aggregate MEMORY_SUMMARY_BY_THREAD_BY_EVENT_NAME
+ to MEMORY_SUMMARY_GLOBAL_BY_EVENT_NAME.
+ */
+ aggregate_all_memory(alive,
+ thread->write_instr_class_memory_stats(),
+ global_instr_class_memory_array);
+}
+
void clear_thread_account(PFS_thread *thread)
{
if (thread->m_account != NULL)
@@ -2170,142 +2179,151 @@ void set_thread_account(PFS_thread *thread)
thread->m_hostname_length);
}
+static void fct_update_mutex_derived_flags(PFS_mutex *pfs)
+{
+ PFS_mutex_class *klass= sanitize_mutex_class(pfs->m_class);
+ if (likely(klass != NULL))
+ {
+ pfs->m_enabled= klass->m_enabled && flag_global_instrumentation;
+ pfs->m_timed= klass->m_timed;
+ }
+ else
+ {
+ pfs->m_enabled= false;
+ pfs->m_timed= false;
+ }
+}
+
void update_mutex_derived_flags()
{
- PFS_mutex *pfs= mutex_array;
- PFS_mutex *pfs_last= mutex_array + mutex_max;
- PFS_mutex_class *klass;
+ global_mutex_container.apply_all(fct_update_mutex_derived_flags);
+}
- for ( ; pfs < pfs_last; pfs++)
+static void fct_update_rwlock_derived_flags(PFS_rwlock *pfs)
+{
+ PFS_rwlock_class *klass= sanitize_rwlock_class(pfs->m_class);
+ if (likely(klass != NULL))
{
- klass= sanitize_mutex_class(pfs->m_class);
- if (likely(klass != NULL))
- {
- pfs->m_enabled= klass->m_enabled && flag_global_instrumentation;
- pfs->m_timed= klass->m_timed;
- }
- else
- {
- pfs->m_enabled= false;
- pfs->m_timed= false;
- }
+ pfs->m_enabled= klass->m_enabled && flag_global_instrumentation;
+ pfs->m_timed= klass->m_timed;
+ }
+ else
+ {
+ pfs->m_enabled= false;
+ pfs->m_timed= false;
}
}
void update_rwlock_derived_flags()
{
- PFS_rwlock *pfs= rwlock_array;
- PFS_rwlock *pfs_last= rwlock_array + rwlock_max;
- PFS_rwlock_class *klass;
+ global_rwlock_container.apply_all(fct_update_rwlock_derived_flags);
+}
- for ( ; pfs < pfs_last; pfs++)
+static void fct_update_cond_derived_flags(PFS_cond *pfs)
+{
+ PFS_cond_class *klass= sanitize_cond_class(pfs->m_class);
+ if (likely(klass != NULL))
{
- klass= sanitize_rwlock_class(pfs->m_class);
- if (likely(klass != NULL))
- {
- pfs->m_enabled= klass->m_enabled && flag_global_instrumentation;
- pfs->m_timed= klass->m_timed;
- }
- else
- {
- pfs->m_enabled= false;
- pfs->m_timed= false;
- }
+ pfs->m_enabled= klass->m_enabled && flag_global_instrumentation;
+ pfs->m_timed= klass->m_timed;
+ }
+ else
+ {
+ pfs->m_enabled= false;
+ pfs->m_timed= false;
}
}
void update_cond_derived_flags()
{
- PFS_cond *pfs= cond_array;
- PFS_cond *pfs_last= cond_array + cond_max;
- PFS_cond_class *klass;
+ global_cond_container.apply_all(fct_update_cond_derived_flags);
+}
- for ( ; pfs < pfs_last; pfs++)
+static void fct_update_file_derived_flags(PFS_file *pfs)
+{
+ PFS_file_class *klass= sanitize_file_class(pfs->m_class);
+ if (likely(klass != NULL))
{
- klass= sanitize_cond_class(pfs->m_class);
- if (likely(klass != NULL))
- {
- pfs->m_enabled= klass->m_enabled && flag_global_instrumentation;
- pfs->m_timed= klass->m_timed;
- }
- else
- {
- pfs->m_enabled= false;
- pfs->m_timed= false;
- }
+ pfs->m_enabled= klass->m_enabled && flag_global_instrumentation;
+ pfs->m_timed= klass->m_timed;
+ }
+ else
+ {
+ pfs->m_enabled= false;
+ pfs->m_timed= false;
}
}
void update_file_derived_flags()
{
- PFS_file *pfs= file_array;
- PFS_file *pfs_last= file_array + file_max;
- PFS_file_class *klass;
+ global_file_container.apply_all(fct_update_file_derived_flags);
+}
- for ( ; pfs < pfs_last; pfs++)
+void fct_update_table_derived_flags(PFS_table *pfs)
+{
+ PFS_table_share *share= sanitize_table_share(pfs->m_share);
+ if (likely(share != NULL))
{
- klass= sanitize_file_class(pfs->m_class);
- if (likely(klass != NULL))
- {
- pfs->m_enabled= klass->m_enabled && flag_global_instrumentation;
- pfs->m_timed= klass->m_timed;
- }
- else
- {
- pfs->m_enabled= false;
- pfs->m_timed= false;
- }
+ pfs->m_io_enabled= share->m_enabled &&
+ flag_global_instrumentation && global_table_io_class.m_enabled;
+ pfs->m_io_timed= share->m_timed && global_table_io_class.m_timed;
+ pfs->m_lock_enabled= share->m_enabled &&
+ flag_global_instrumentation && global_table_lock_class.m_enabled;
+ pfs->m_lock_timed= share->m_timed && global_table_lock_class.m_timed;
+ }
+ else
+ {
+ pfs->m_io_enabled= false;
+ pfs->m_io_timed= false;
+ pfs->m_lock_enabled= false;
+ pfs->m_lock_timed= false;
}
}
void update_table_derived_flags()
{
- PFS_table *pfs= table_array;
- PFS_table *pfs_last= table_array + table_max;
- PFS_table_share *share;
+ global_table_container.apply_all(fct_update_table_derived_flags);
+}
- for ( ; pfs < pfs_last; pfs++)
+static void fct_update_socket_derived_flags(PFS_socket *pfs)
+{
+ PFS_socket_class *klass= sanitize_socket_class(pfs->m_class);
+ if (likely(klass != NULL))
{
- share= sanitize_table_share(pfs->m_share);
- if (likely(share != NULL))
- {
- pfs->m_io_enabled= share->m_enabled &&
- flag_global_instrumentation && global_table_io_class.m_enabled;
- pfs->m_io_timed= share->m_timed && global_table_io_class.m_timed;
- pfs->m_lock_enabled= share->m_enabled &&
- flag_global_instrumentation && global_table_lock_class.m_enabled;
- pfs->m_lock_timed= share->m_timed && global_table_lock_class.m_timed;
- }
- else
- {
- pfs->m_io_enabled= false;
- pfs->m_io_timed= false;
- pfs->m_lock_enabled= false;
- pfs->m_lock_timed= false;
- }
+ pfs->m_enabled= klass->m_enabled && flag_global_instrumentation;
+ pfs->m_timed= klass->m_timed;
+ }
+ else
+ {
+ pfs->m_enabled= false;
+ pfs->m_timed= false;
}
}
void update_socket_derived_flags()
{
- PFS_socket *pfs= socket_array;
- PFS_socket *pfs_last= socket_array + socket_max;
- PFS_socket_class *klass;
+ global_socket_container.apply_all(fct_update_socket_derived_flags);
+}
- for ( ; pfs < pfs_last; pfs++)
- {
- klass= sanitize_socket_class(pfs->m_class);
- if (likely(klass != NULL))
- {
- pfs->m_enabled= klass->m_enabled && flag_global_instrumentation;
- pfs->m_timed= klass->m_timed;
- }
- else
- {
- pfs->m_enabled= false;
- pfs->m_timed= false;
- }
- }
+static void fct_update_metadata_derived_flags(PFS_metadata_lock *pfs)
+{
+ pfs->m_enabled= global_metadata_class.m_enabled && flag_global_instrumentation;
+ pfs->m_timed= global_metadata_class.m_timed;
+}
+
+void update_metadata_derived_flags()
+{
+ global_mdl_container.apply_all(fct_update_metadata_derived_flags);
+}
+
+static void fct_update_thread_derived_flags(PFS_thread *pfs)
+{
+ pfs->set_history_derived_flags();
+}
+
+void update_thread_derived_flags()
+{
+ global_thread_container.apply(fct_update_thread_derived_flags);
}
void update_instruments_derived_flags()
@@ -2316,7 +2334,8 @@ void update_instruments_derived_flags()
update_file_derived_flags();
update_table_derived_flags();
update_socket_derived_flags();
- /* nothing for stages and statements (no instances) */
+ update_metadata_derived_flags();
+ /* nothing for stages, statements and transactions (no instances) */
}
/** @} */
diff --git a/storage/perfschema/pfs_instr.h b/storage/perfschema/pfs_instr.h
index 81bc52d1d75..c15d30b50e9 100644
--- a/storage/perfschema/pfs_instr.h
+++ b/storage/perfschema/pfs_instr.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2017, 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, version 2.0,
@@ -35,11 +35,15 @@ struct PFS_file_class;
struct PFS_table_share;
struct PFS_thread_class;
struct PFS_socket_class;
+class PFS_opaque_container_page;
+
+class THD;
#include "my_global.h"
-#ifdef __WIN__
+#ifdef _WIN32
#include <winsock2.h>
-#else
+#endif
+#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#include "my_compiler.h"
@@ -49,9 +53,17 @@ struct PFS_socket_class;
#include "pfs_events_waits.h"
#include "pfs_events_stages.h"
#include "pfs_events_statements.h"
+#include "pfs_events_transactions.h"
#include "pfs_server.h"
#include "lf.h"
#include "pfs_con_slice.h"
+#include "pfs_column_types.h"
+#include "mdl.h"
+#include "violite.h" /* enum_vio_type */
+
+extern PFS_single_stat *thread_instr_class_waits_array_start;
+extern PFS_single_stat *thread_instr_class_waits_array_end;
+extern my_bool show_compatibility_56;
/**
@addtogroup Performance_schema_buffers
@@ -72,6 +84,8 @@ struct PFS_instr
bool m_enabled;
/** Timed flag. */
bool m_timed;
+ /** Container page. */
+ PFS_opaque_container_page *m_page;
};
/** Instrumented mutex implementation. @see PSI_mutex. */
@@ -124,8 +138,6 @@ struct PFS_ALIGNED PFS_cond : public PFS_instr
const void *m_identity;
/** Condition class. */
PFS_cond_class *m_class;
- /** Instrument wait statistics. */
- PFS_single_stat m_wait_stat;
/** Condition instance usage statistics. */
PFS_cond_stat m_cond_stat;
};
@@ -146,6 +158,8 @@ struct PFS_ALIGNED PFS_file : public PFS_instr
PFS_file_class *m_class;
/** File usage statistics. */
PFS_file_stat m_file_stat;
+ /** True if a temporary file. */
+ bool m_temporary;
};
/** Instrumented table implementation. @see PSI_table. */
@@ -184,20 +198,14 @@ public:
Only use this method for handles owned by the calling code.
@sa sanitized_aggregate.
*/
- void aggregate(void)
+ void aggregate(const TABLE_SHARE *server_share)
{
- if (m_has_io_stats && m_has_lock_stats)
- {
- safe_aggregate(& m_table_stat, m_share);
- m_has_io_stats= false;
- m_has_lock_stats= false;
- }
- else if (m_has_io_stats)
+ if (m_has_io_stats)
{
- safe_aggregate_io(& m_table_stat, m_share);
+ safe_aggregate_io(server_share, & m_table_stat, m_share);
m_has_io_stats= false;
}
- else if (m_has_lock_stats)
+ if (m_has_lock_stats)
{
safe_aggregate_lock(& m_table_stat, m_share);
m_has_lock_stats= false;
@@ -227,19 +235,26 @@ public:
/** Internal lock. */
pfs_lock m_lock;
- /** Owner. */
+ /** Thread Owner. */
PFS_thread *m_thread_owner;
+ /** Event Owner. */
+ ulonglong m_owner_event_id;
/** Table share. */
PFS_table_share *m_share;
/** Table identity, typically a handler. */
const void *m_identity;
/** Table statistics. */
PFS_table_stat m_table_stat;
+ /** Current internal lock. */
+ PFS_TL_LOCK_TYPE m_internal_lock;
+ /** Current external lock. */
+ PFS_TL_LOCK_TYPE m_external_lock;
+ /** Container page. */
+ PFS_opaque_container_page *m_page;
private:
- static void safe_aggregate(PFS_table_stat *stat,
- PFS_table_share *safe_share);
- static void safe_aggregate_io(PFS_table_stat *stat,
+ static void safe_aggregate_io(const TABLE_SHARE *optional_server_share,
+ PFS_table_stat *stat,
PFS_table_share *safe_share);
static void safe_aggregate_lock(PFS_table_stat *stat,
PFS_table_share *safe_share);
@@ -269,6 +284,24 @@ struct PFS_ALIGNED PFS_socket : public PFS_instr
PFS_socket_stat m_socket_stat;
};
+/** Instrumented metadata lock implementation. @see PSI_metadata_lock. */
+struct PFS_ALIGNED PFS_metadata_lock : public PFS_instr
+{
+ uint32 get_version()
+ { return m_lock.get_version(); }
+
+ /** Lock identity. */
+ const void *m_identity;
+ MDL_key m_mdl_key;
+ opaque_mdl_type m_mdl_type;
+ opaque_mdl_duration m_mdl_duration;
+ opaque_mdl_status m_mdl_status;
+ const char *m_src_file;
+ uint m_src_line;
+ ulonglong m_owner_thread_id;
+ ulonglong m_owner_event_id;
+};
+
/**
@def WAIT_STACK_LOGICAL_SIZE
Maximum number of nested waits.
@@ -293,7 +326,7 @@ struct PFS_ALIGNED PFS_socket : public PFS_instr
/**
@def WAIT_STACK_BOTTOM
Maximum number dummy waits records.
- One dummy record is reserved for the parent stage / statement,
+ One dummy record is reserved for the parent stage / statement / transaction,
at the bottom of the wait stack.
*/
#define WAIT_STACK_BOTTOM 1
@@ -307,75 +340,84 @@ struct PFS_ALIGNED PFS_socket : public PFS_instr
extern uint statement_stack_max;
/** Max size of the digests token array. */
extern size_t pfs_max_digest_length;
+/** Max size of SQL TEXT. */
+extern size_t pfs_max_sqltext;
-/**
- @def PFS_MAX_ALLOC_RETRY
- Maximum number of times the code attempts to allocate an item
- from internal buffers, before giving up.
-*/
-#define PFS_MAX_ALLOC_RETRY 1000
+/** Instrumented thread implementation. @see PSI_thread. */
+struct PFS_ALIGNED PFS_thread : PFS_connection_slice
+{
+ static PFS_thread* get_current_thread(void);
-/** The maximun number of passes in @sa PFS_scan. */
-#define PFS_MAX_SCAN_PASS 2
+ /** Thread instrumentation flag. */
+ bool m_enabled;
+ /** Thread history instrumentation flag. */
+ bool m_history;
-/**
- Helper to scan circular buffers.
- Given a buffer of size [0, max_size - 1],
- and a random starting point in the buffer,
- this helper returns up to two [first, last -1] intervals that:
- - fit into the [0, max_size - 1] range,
- - have a maximum combined length of at most PFS_MAX_ALLOC_RETRY.
-*/
-struct PFS_scan
-{
-public:
/**
- Initialize a new scan.
- @param random a random index to start from
- @param max_size the max size of the interval to scan
+ Derived flag flag_events_waits_history, per thread.
+ Cached computation of
+ TABLE SETUP_CONSUMERS[EVENTS_WAITS_HISTORY].ENABLED == 'YES'
+ AND
+ TABLE THREADS[THREAD_ID].HISTORY == 'YES'
*/
- void init(uint random, uint max_size);
-
+ bool m_flag_events_waits_history;
/**
- Predicate, has a next pass.
- @return true if there is a next pass to perform.
+ Derived flag flag_events_waits_history_long, per thread.
+ Cached computation of
+ TABLE SETUP_CONSUMERS[EVENTS_WAITS_HISTORY_LONG].ENABLED == 'YES'
+ AND
+ TABLE THREADS[THREAD_ID].HISTORY == 'YES'
*/
- bool has_pass() const
- { return (m_pass < m_pass_max); }
-
+ bool m_flag_events_waits_history_long;
/**
- Iterator, proceed to the next pass.
+ Derived flag flag_events_stages_history, per thread.
+ Cached computation of
+ TABLE SETUP_CONSUMERS[EVENTS_STAGES_HISTORY].ENABLED == 'YES'
+ AND
+ TABLE THREADS[THREAD_ID].HISTORY == 'YES'
*/
- void next_pass()
- { m_pass++; }
-
- /** First index for this pass. */
- uint first() const
- { return m_first[m_pass]; }
-
- /** Last index for this pass. */
- uint last() const
- { return m_last[m_pass]; }
-
-private:
- /** Current pass. */
- uint m_pass;
- /** Maximum number of passes. */
- uint m_pass_max;
- /** First element for each pass. */
- uint m_first[PFS_MAX_SCAN_PASS];
- /** Last element for each pass. */
- uint m_last[PFS_MAX_SCAN_PASS];
-};
-
-
-/** Instrumented thread implementation. @see PSI_thread. */
-struct PFS_ALIGNED PFS_thread : PFS_connection_slice
-{
- static PFS_thread* get_current_thread(void);
+ bool m_flag_events_stages_history;
+ /**
+ Derived flag flag_events_stages_history_long, per thread.
+ Cached computation of
+ TABLE SETUP_CONSUMERS[EVENTS_STAGES_HISTORY_LONG].ENABLED == 'YES'
+ AND
+ TABLE THREADS[THREAD_ID].HISTORY == 'YES'
+ */
+ bool m_flag_events_stages_history_long;
+ /**
+ Derived flag flag_events_statements_history, per thread.
+ Cached computation of
+ TABLE SETUP_CONSUMERS[EVENTS_STATEMENTS_HISTORY].ENABLED == 'YES'
+ AND
+ TABLE THREADS[THREAD_ID].HISTORY == 'YES'
+ */
+ bool m_flag_events_statements_history;
+ /**
+ Derived flag flag_events_statements_history_long, per thread.
+ Cached computation of
+ TABLE SETUP_CONSUMERS[EVENTS_STATEMENTS_HISTORY_LONG].ENABLED == 'YES'
+ AND
+ TABLE THREADS[THREAD_ID].HISTORY == 'YES'
+ */
+ bool m_flag_events_statements_history_long;
+ /**
+ Derived flag flag_events_transactions_history, per thread.
+ Cached computation of
+ TABLE SETUP_CONSUMERS[EVENTS_TRANSACTIONS_HISTORY].ENABLED == 'YES'
+ AND
+ TABLE THREADS[THREAD_ID].HISTORY == 'YES'
+ */
+ bool m_flag_events_transactions_history;
+ /**
+ Derived flag flag_events_transactions_history_long, per thread.
+ Cached computation of
+ TABLE SETUP_CONSUMERS[EVENTS_TRANSACTIONS_HISTORY_LONG].ENABLED == 'YES'
+ AND
+ TABLE THREADS[THREAD_ID].HISTORY == 'YES'
+ */
+ bool m_flag_events_transactions_history_long;
- /** Thread instrumentation flag. */
- bool m_enabled;
/** Current wait event in the event stack. */
PFS_events_waits *m_events_waits_current;
/** Event ID counter */
@@ -404,18 +446,22 @@ struct PFS_ALIGNED PFS_thread : PFS_connection_slice
LF_PINS *m_account_hash_pins;
/** Pins for digest_hash. */
LF_PINS *m_digest_hash_pins;
+ /** Pins for routine_hash. */
+ LF_PINS *m_program_hash_pins;
/** Internal thread identifier, unique. */
ulonglong m_thread_internal_id;
/** Parent internal thread identifier. */
ulonglong m_parent_thread_internal_id;
/** External (SHOW PROCESSLIST) thread identifier, not unique. */
ulong m_processlist_id;
+ /** External (Operating system) thread identifier, if any. */
+ uint32 m_thread_os_id;
/** Thread class. */
PFS_thread_class *m_class;
/**
Stack of events waits.
This member holds the data for the table PERFORMANCE_SCHEMA.EVENTS_WAITS_CURRENT.
- Note that stack[0] is a dummy record that represents the parent stage/statement.
+ Note that stack[0] is a dummy record that represents the parent stage/statement/transaction.
For example, assuming the following tree:
- STAGE ID 100
- WAIT ID 101, parent STAGE 100
@@ -475,12 +521,24 @@ struct PFS_ALIGNED PFS_thread : PFS_connection_slice
*/
PFS_events_statements *m_statements_history;
+ /** True if the circular buffer @c m_transactions_history is full. */
+ bool m_transactions_history_full;
+ /** Current index in the circular buffer @c m_transactions_history. */
+ uint m_transactions_history_index;
+ /**
+ Statements history circular buffer.
+ This member holds the data for the table
+ PERFORMANCE_SCHEMA.EVENTS_TRANSACTIONS_HISTORY.
+ */
+ PFS_events_transactions *m_transactions_history;
+
/**
Internal lock, for session attributes.
Statement attributes are expected to be updated in frequently,
typically per session execution.
*/
pfs_lock m_session_lock;
+
/**
User name.
Protected by @c m_session_lock.
@@ -513,6 +571,8 @@ struct PFS_ALIGNED PFS_thread : PFS_connection_slice
uint m_dbname_length;
/** Current command. */
int m_command;
+ /** Connection type. */
+ enum_vio_type m_connection_type;
/** Start time. */
time_t m_start_time;
/**
@@ -523,6 +583,8 @@ struct PFS_ALIGNED PFS_thread : PFS_connection_slice
pfs_lock m_stmt_lock;
/** Processlist state (derived from stage). */
PFS_stage_key m_stage;
+ /** Current stage progress. */
+ PSI_stage_progress* m_stage_progress;
/**
Processlist info.
Protected by @c m_stmt_lock.
@@ -540,6 +602,9 @@ struct PFS_ALIGNED PFS_thread : PFS_connection_slice
uint m_events_statements_count;
PFS_events_statements *m_statement_stack;
+ PFS_events_transactions m_transaction_current;
+
+ THD *m_thd;
PFS_host *m_host;
PFS_user *m_user;
PFS_account *m_account;
@@ -562,10 +627,28 @@ struct PFS_ALIGNED PFS_thread : PFS_connection_slice
Protected by @c m_session_lock.
*/
uint m_session_connect_attrs_cs_number;
+
+ void carry_memory_stat_delta(PFS_memory_stat_delta *delta, uint index);
+
+ void set_enabled(bool enabled)
+ {
+ m_enabled= enabled;
+ }
+
+ void set_history(bool history)
+ {
+ m_history= history;
+ set_history_derived_flags();
+ }
+
+ void set_history_derived_flags();
};
+void carry_global_memory_stat_delta(PFS_memory_stat_delta *delta, uint index);
+
extern PFS_stage_stat *global_instr_class_stages_array;
extern PFS_statement_stat *global_instr_class_statements_array;
+extern PFS_memory_stat *global_instr_class_memory_array;
PFS_mutex *sanitize_mutex(PFS_mutex *unsafe);
PFS_rwlock *sanitize_rwlock(PFS_rwlock *unsafe);
@@ -573,10 +656,11 @@ PFS_cond *sanitize_cond(PFS_cond *unsafe);
PFS_thread *sanitize_thread(PFS_thread *unsafe);
PFS_file *sanitize_file(PFS_file *unsafe);
PFS_socket *sanitize_socket(PFS_socket *unsafe);
+PFS_metadata_lock *sanitize_metadata_lock(PFS_metadata_lock *unsafe);
int init_instruments(const PFS_global_param *param);
void cleanup_instruments();
-int init_file_hash();
+int init_file_hash(const PFS_global_param *param);
void cleanup_file_hash();
PFS_mutex* create_mutex(PFS_mutex_class *mutex_class, const void *identity);
void destroy_mutex(PFS_mutex *pfs);
@@ -592,6 +676,9 @@ void destroy_thread(PFS_thread *pfs);
PFS_file* find_or_create_file(PFS_thread *thread, PFS_file_class *klass,
const char *filename, uint len, bool create);
+void find_and_rename_file(PFS_thread *thread, const char *old_filename,
+ uint old_len, const char *new_filename,
+ uint new_len);
void release_file(PFS_file *pfs);
void destroy_file(PFS_thread *thread, PFS_file *pfs);
@@ -605,27 +692,23 @@ PFS_socket* create_socket(PFS_socket_class *socket_class,
socklen_t addr_len);
void destroy_socket(PFS_socket *pfs);
+PFS_metadata_lock* create_metadata_lock(void *identity,
+ const MDL_key *mdl_key,
+ opaque_mdl_type mdl_type,
+ opaque_mdl_duration mdl_duration,
+ opaque_mdl_status mdl_status,
+ const char *src_file,
+ uint src_line);
+void destroy_metadata_lock(PFS_metadata_lock *pfs);
+
/* For iterators and show status. */
-extern ulong mutex_max;
-extern ulong mutex_lost;
-extern ulong rwlock_max;
-extern ulong rwlock_lost;
-extern ulong cond_max;
-extern ulong cond_lost;
-extern ulong thread_max;
-extern ulong thread_lost;
-extern ulong file_max;
-extern ulong file_lost;
extern long file_handle_max;
extern ulong file_handle_lost;
-extern ulong table_max;
-extern ulong table_lost;
-extern ulong socket_max;
-extern ulong socket_lost;
extern ulong events_waits_history_per_thread;
extern ulong events_stages_history_per_thread;
extern ulong events_statements_history_per_thread;
+extern ulong events_transactions_history_per_thread;
extern ulong locker_lost;
extern ulong statement_lost;
extern ulong session_connect_attrs_lost;
@@ -633,14 +716,7 @@ extern ulong session_connect_attrs_size_per_thread;
/* Exposing the data directly, for iterators. */
-extern PFS_mutex *mutex_array;
-extern PFS_rwlock *rwlock_array;
-extern PFS_cond *cond_array;
-extern PFS_thread *thread_array;
-extern PFS_file *file_array;
extern PFS_file **file_handle_array;
-extern PFS_table *table_array;
-extern PFS_socket *socket_array;
void reset_events_waits_by_instance();
void reset_file_instance_io();
@@ -664,6 +740,20 @@ void aggregate_all_statements(PFS_statement_stat *from_array,
PFS_statement_stat *to_array_1,
PFS_statement_stat *to_array_2);
+void aggregate_all_transactions(PFS_transaction_stat *from_array,
+ PFS_transaction_stat *to_array);
+void aggregate_all_transactions(PFS_transaction_stat *from_array,
+ PFS_transaction_stat *to_array_1,
+ PFS_transaction_stat *to_array_2);
+
+void aggregate_all_memory(bool alive,
+ PFS_memory_stat *from_array,
+ PFS_memory_stat *to_array);
+void aggregate_all_memory(bool alive,
+ PFS_memory_stat *from_array,
+ PFS_memory_stat *to_array_1,
+ PFS_memory_stat *to_array_2);
+
void aggregate_thread(PFS_thread *thread,
PFS_account *safe_account,
PFS_user *safe_user,
@@ -680,6 +770,21 @@ void aggregate_thread_statements(PFS_thread *thread,
PFS_account *safe_account,
PFS_user *safe_user,
PFS_host *safe_host);
+void aggregate_thread_transactions(PFS_thread *thread,
+ PFS_account *safe_account,
+ PFS_user *safe_user,
+ PFS_host *safe_host);
+
+void aggregate_thread_memory(bool alive, PFS_thread *thread,
+ PFS_account *safe_account,
+ PFS_user *safe_user,
+ PFS_host *safe_host);
+
+void aggregate_thread_status(PFS_thread *thread,
+ PFS_account *safe_account,
+ PFS_user *safe_user,
+ PFS_host *safe_host);
+
void clear_thread_account(PFS_thread *thread);
void set_thread_account(PFS_thread *thread);
@@ -695,6 +800,10 @@ void update_file_derived_flags();
void update_table_derived_flags();
/** Update derived flags for all socket instances. */
void update_socket_derived_flags();
+/** Update derived flags for all metadata instances. */
+void update_metadata_derived_flags();
+/** Update derived flags for all thread instances. */
+void update_thread_derived_flags();
/** Update derived flags for all instruments. */
void update_instruments_derived_flags();
diff --git a/storage/perfschema/pfs_instr_class.cc b/storage/perfschema/pfs_instr_class.cc
index 2757369cad3..1a6a8b86f03 100644
--- a/storage/perfschema/pfs_instr_class.cc
+++ b/storage/perfschema/pfs_instr_class.cc
@@ -28,15 +28,17 @@
#include "my_global.h"
#include "my_sys.h"
-#include "structs.h"
#include "table.h"
#include "pfs_instr_class.h"
+#include "pfs_builtin_memory.h"
#include "pfs_instr.h"
#include "pfs_global.h"
#include "pfs_timer.h"
#include "pfs_events_waits.h"
#include "pfs_setup_object.h"
#include "pfs_atomic.h"
+#include "pfs_program.h"
+#include "pfs_buffer_container.h"
#include "mysql/psi/mysql_thread.h"
#include "lf.h"
@@ -49,11 +51,16 @@
*/
/**
- PFS_INSTRUMENT option settings array and associated state variable to
- serialize access during shutdown.
+ Global performance schema flag.
+ Indicate if the performance schema is enabled.
+ This flag is set at startup, and never changes.
+*/
+my_bool pfs_enabled= TRUE;
+
+/**
+ PFS_INSTRUMENT option settings array
*/
-DYNAMIC_ARRAY pfs_instr_config_array;
-int pfs_instr_config_state= PFS_INSTR_CONFIG_NOT_INITIALIZED;
+Pfs_instr_config_array *pfs_instr_config_array= NULL;
static void configure_instr_class(PFS_instr_class *entry);
@@ -69,12 +76,12 @@ static void init_instr_class(PFS_instr_class *klass,
- the performance schema initialization
- a plugin initialization
*/
-static volatile uint32 mutex_class_dirty_count= 0;
-static volatile uint32 mutex_class_allocated_count= 0;
-static volatile uint32 rwlock_class_dirty_count= 0;
-static volatile uint32 rwlock_class_allocated_count= 0;
-static volatile uint32 cond_class_dirty_count= 0;
-static volatile uint32 cond_class_allocated_count= 0;
+static uint32 mutex_class_dirty_count= 0;
+static uint32 mutex_class_allocated_count= 0;
+static uint32 rwlock_class_dirty_count= 0;
+static uint32 rwlock_class_allocated_count= 0;
+static uint32 cond_class_dirty_count= 0;
+static uint32 cond_class_allocated_count= 0;
/** Size of the mutex class array. @sa mutex_class_array */
ulong mutex_class_max= 0;
@@ -104,14 +111,21 @@ ulong stage_class_lost= 0;
ulong statement_class_max= 0;
/** Number of statement class lost. @sa statement_class_array */
ulong statement_class_lost= 0;
-/** Size of the table share array. @sa table_share_array */
-ulong table_share_max= 0;
-/** Number of table share lost. @sa table_share_array */
-ulong table_share_lost= 0;
/** Size of the socket class array. @sa socket_class_array */
ulong socket_class_max= 0;
/** Number of socket class lost. @sa socket_class_array */
ulong socket_class_lost= 0;
+/** Size of the memory class array. @sa memory_class_array */
+ulong memory_class_max= 0;
+/** Number of memory class lost. @sa memory_class_array */
+ulong memory_class_lost= 0;
+
+/**
+ Number of transaction classes. Although there is only one transaction class,
+ this is used for sizing by other event classes.
+ @sa global_transaction_class
+*/
+ulong transaction_class_max= 0;
PFS_mutex_class *mutex_class_array= NULL;
PFS_rwlock_class *rwlock_class_array= NULL;
@@ -123,47 +137,45 @@ PFS_cond_class *cond_class_array= NULL;
- the performance schema initialization
- a plugin initialization
*/
-static volatile uint32 thread_class_dirty_count= 0;
-static volatile uint32 thread_class_allocated_count= 0;
+static uint32 thread_class_dirty_count= 0;
+static uint32 thread_class_allocated_count= 0;
static PFS_thread_class *thread_class_array= NULL;
-/**
- Table instance array.
- @sa table_share_max
- @sa table_share_lost
- @sa table_share_hash
-*/
-PFS_table_share *table_share_array= NULL;
-
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_single_stat global_metadata_stat;
+PFS_ALIGNED PFS_transaction_stat global_transaction_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;
+PFS_ALIGNED PFS_instr_class global_metadata_class;
+PFS_ALIGNED PFS_transaction_class global_transaction_class;
/** Class-timer map */
enum_timer_name *class_timers[] =
-{&wait_timer, /* PFS_CLASS_NONE */
- &wait_timer, /* PFS_CLASS_MUTEX */
- &wait_timer, /* PFS_CLASS_RWLOCK */
- &wait_timer, /* PFS_CLASS_COND */
- &wait_timer, /* PFS_CLASS_FILE */
- &wait_timer, /* PFS_CLASS_TABLE */
- &stage_timer, /* PFS_CLASS_STAGE */
- &statement_timer, /* PFS_CLASS_STATEMENT */
- &wait_timer, /* PFS_CLASS_SOCKET */
- &wait_timer, /* PFS_CLASS_TABLE_IO */
- &wait_timer, /* PFS_CLASS_TABLE_LOCK */
- &idle_timer /* PFS_CLASS_IDLE */
+{&wait_timer, /* PFS_CLASS_NONE */
+ &wait_timer, /* PFS_CLASS_MUTEX */
+ &wait_timer, /* PFS_CLASS_RWLOCK */
+ &wait_timer, /* PFS_CLASS_COND */
+ &wait_timer, /* PFS_CLASS_FILE */
+ &wait_timer, /* PFS_CLASS_TABLE */
+ &stage_timer, /* PFS_CLASS_STAGE */
+ &statement_timer, /* PFS_CLASS_STATEMENT */
+ &transaction_timer, /* PFS_CLASS_TRANSACTION */
+ &wait_timer, /* PFS_CLASS_SOCKET */
+ &wait_timer, /* PFS_CLASS_TABLE_IO */
+ &wait_timer, /* PFS_CLASS_TABLE_LOCK */
+ &idle_timer, /* PFS_CLASS_IDLE */
+ &wait_timer, /* PFS_CLASS_METADATA */
+ &wait_timer /* PFS_CLASS_MEMORY */
};
/**
Hash index for instrumented table shares.
This index is searched by table fully qualified name (@c PFS_table_share_key),
and points to instrumented table shares (@c PFS_table_share).
- @sa table_share_array
@sa PFS_table_share_key
@sa PFS_table_share
@sa table_share_hash_get_key
@@ -173,26 +185,31 @@ LF_HASH table_share_hash;
/** True if table_share_hash is initialized. */
static bool table_share_hash_inited= false;
-static volatile uint32 file_class_dirty_count= 0;
-static volatile uint32 file_class_allocated_count= 0;
+static uint32 file_class_dirty_count= 0;
+static uint32 file_class_allocated_count= 0;
PFS_file_class *file_class_array= NULL;
-static volatile uint32 stage_class_dirty_count= 0;
-static volatile uint32 stage_class_allocated_count= 0;
+static uint32 stage_class_dirty_count= 0;
+static uint32 stage_class_allocated_count= 0;
static PFS_stage_class *stage_class_array= NULL;
-static volatile uint32 statement_class_dirty_count= 0;
-static volatile uint32 statement_class_allocated_count= 0;
+static uint32 statement_class_dirty_count= 0;
+static uint32 statement_class_allocated_count= 0;
static PFS_statement_class *statement_class_array= NULL;
-static volatile uint32 socket_class_dirty_count= 0;
-static volatile uint32 socket_class_allocated_count= 0;
+static uint32 socket_class_dirty_count= 0;
+static uint32 socket_class_allocated_count= 0;
static PFS_socket_class *socket_class_array= NULL;
+static uint32 memory_class_dirty_count= 0;
+static uint32 memory_class_allocated_count= 0;
+
+static PFS_memory_class *memory_class_array= NULL;
+
uint mutex_class_start= 0;
uint rwlock_class_start= 0;
uint cond_class_start= 0;
@@ -202,7 +219,8 @@ uint socket_class_start= 0;
void init_event_name_sizing(const PFS_global_param *param)
{
- mutex_class_start= 3; /* global table io, table lock, idle */
+ /* global table io, table lock, idle, metadata */
+ mutex_class_start= COUNT_GLOBAL_EVENT_INDEX;
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;
@@ -223,12 +241,29 @@ void register_global_classes()
0, PFS_CLASS_TABLE_LOCK);
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= GLOBAL_IDLE_EVENT_INDEX;
configure_instr_class(&global_idle_class);
+
+ /* Metadata class */
+ init_instr_class(&global_metadata_class, "wait/lock/metadata/sql/mdl", 26,
+ 0, PFS_CLASS_METADATA);
+ global_metadata_class.m_event_name_index= GLOBAL_METADATA_EVENT_INDEX;
+ global_metadata_class.m_enabled= false; /* Disabled by default */
+ global_metadata_class.m_timed= false;
+ configure_instr_class(&global_metadata_class);
+
+ /* Transaction class */
+ init_instr_class(&global_transaction_class, "transaction", 11,
+ 0, PFS_CLASS_TRANSACTION);
+ global_transaction_class.m_event_name_index= GLOBAL_TRANSACTION_INDEX;
+ global_transaction_class.m_enabled= false; /* Disabled by default */
+ global_transaction_class.m_timed= false;
+ configure_instr_class(&global_transaction_class);
+ transaction_class_max= 1; /* used for sizing by other event classes */
}
/**
@@ -256,24 +291,30 @@ int init_sync_class(uint mutex_class_sizing,
if (mutex_class_max > 0)
{
- mutex_class_array= PFS_MALLOC_ARRAY(mutex_class_max, sizeof(PFS_mutex_class),
- PFS_mutex_class, MYF(MY_ZEROFILL));
+ mutex_class_array= PFS_MALLOC_ARRAY(& builtin_memory_mutex_class,
+ mutex_class_max,
+ sizeof(PFS_mutex_class), PFS_mutex_class,
+ MYF(MY_ZEROFILL));
if (unlikely(mutex_class_array == NULL))
return 1;
}
if (rwlock_class_max > 0)
{
- rwlock_class_array= PFS_MALLOC_ARRAY(rwlock_class_max, sizeof(PFS_rwlock_class),
- PFS_rwlock_class, MYF(MY_ZEROFILL));
+ rwlock_class_array= PFS_MALLOC_ARRAY(& builtin_memory_rwlock_class,
+ rwlock_class_max,
+ sizeof(PFS_rwlock_class), PFS_rwlock_class,
+ MYF(MY_ZEROFILL));
if (unlikely(rwlock_class_array == NULL))
return 1;
}
if (cond_class_max > 0)
{
- cond_class_array= PFS_MALLOC_ARRAY(cond_class_max, sizeof(PFS_cond_class),
- PFS_cond_class, MYF(MY_ZEROFILL));
+ cond_class_array= PFS_MALLOC_ARRAY(& builtin_memory_cond_class,
+ cond_class_max,
+ sizeof(PFS_cond_class), PFS_cond_class,
+ MYF(MY_ZEROFILL));
if (unlikely(cond_class_array == NULL))
return 1;
}
@@ -284,13 +325,21 @@ int init_sync_class(uint mutex_class_sizing,
/** Cleanup the instrument synch class buffers. */
void cleanup_sync_class(void)
{
- pfs_free(mutex_class_array);
+ PFS_FREE_ARRAY(& builtin_memory_mutex_class,
+ mutex_class_max, sizeof(PFS_mutex_class),
+ mutex_class_array);
mutex_class_array= NULL;
mutex_class_dirty_count= mutex_class_allocated_count= mutex_class_max= 0;
- pfs_free(rwlock_class_array);
+
+ PFS_FREE_ARRAY(& builtin_memory_rwlock_class,
+ rwlock_class_max, sizeof(PFS_rwlock_class),
+ rwlock_class_array);
rwlock_class_array= NULL;
rwlock_class_dirty_count= rwlock_class_allocated_count= rwlock_class_max= 0;
- pfs_free(cond_class_array);
+
+ PFS_FREE_ARRAY(& builtin_memory_cond_class,
+ cond_class_max, sizeof(PFS_cond_class),
+ cond_class_array);
cond_class_array= NULL;
cond_class_dirty_count= cond_class_allocated_count= cond_class_max= 0;
}
@@ -309,8 +358,10 @@ int init_thread_class(uint thread_class_sizing)
if (thread_class_max > 0)
{
- thread_class_array= PFS_MALLOC_ARRAY(thread_class_max, sizeof(PFS_thread_class),
- PFS_thread_class, MYF(MY_ZEROFILL));
+ thread_class_array= PFS_MALLOC_ARRAY(& builtin_memory_thread_class,
+ thread_class_max,
+ sizeof(PFS_thread_class), PFS_thread_class,
+ MYF(MY_ZEROFILL));
if (unlikely(thread_class_array == NULL))
result= 1;
}
@@ -323,7 +374,9 @@ int init_thread_class(uint thread_class_sizing)
/** Cleanup the thread class buffers. */
void cleanup_thread_class(void)
{
- pfs_free(thread_class_array);
+ PFS_FREE_ARRAY(& builtin_memory_thread_class,
+ thread_class_max, sizeof(PFS_thread_class),
+ thread_class_array);
thread_class_array= NULL;
thread_class_dirty_count= thread_class_allocated_count= 0;
thread_class_max= 0;
@@ -336,29 +389,16 @@ void cleanup_thread_class(void)
*/
int init_table_share(uint table_share_sizing)
{
- int result= 0;
- table_share_max= table_share_sizing;
- table_share_lost= 0;
-
- if (table_share_max > 0)
- {
- table_share_array= PFS_MALLOC_ARRAY(table_share_max, sizeof(PFS_table_share),
- PFS_table_share, MYF(MY_ZEROFILL));
- if (unlikely(table_share_array == NULL))
- result= 1;
- }
- else
- table_share_array= NULL;
+ if (global_table_share_container.init(table_share_sizing))
+ return 1;
- return result;
+ return 0;
}
/** Cleanup the table share buffers. */
void cleanup_table_share(void)
{
- pfs_free(table_share_array);
- table_share_array= NULL;
- table_share_max= 0;
+ global_table_share_container.cleanup();
}
C_MODE_START
@@ -380,13 +420,12 @@ static uchar *table_share_hash_get_key(const uchar *entry, size_t *length,
C_MODE_END
/** Initialize the table share hash table. */
-int init_table_share_hash(void)
+int init_table_share_hash(const PFS_global_param *param)
{
- if ((! table_share_hash_inited) && (table_share_max > 0))
+ if ((! table_share_hash_inited) && (param->m_table_share_sizing != 0))
{
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;
@@ -429,8 +468,8 @@ LF_PINS* get_table_share_hash_pins(PFS_thread *thread)
*/
static void set_table_share_key(PFS_table_share_key *key,
bool temporary,
- const char *schema_name, uint schema_name_length,
- const char *table_name, uint table_name_length)
+ const char *schema_name, size_t schema_name_length,
+ const char *table_name, size_t table_name_length)
{
DBUG_ASSERT(schema_name_length <= NAME_LEN);
DBUG_ASSERT(table_name_length <= NAME_LEN);
@@ -459,13 +498,315 @@ static void set_table_share_key(PFS_table_share_key *key,
}
}
+/**
+ Find an existing table share lock instrumentation.
+ @return a table share lock.
+*/
+PFS_table_share_lock*
+PFS_table_share::find_lock_stat() const
+{
+ PFS_table_share *that= const_cast<PFS_table_share*>(this);
+ void *addr= & that->m_race_lock_stat;
+ void * volatile * typed_addr= static_cast<void * volatile *>(addr);
+ void *ptr;
+
+ /* Atomic Load */
+ ptr= my_atomic_loadptr(typed_addr);
+
+ PFS_table_share_lock *pfs;
+ pfs= static_cast<PFS_table_share_lock *>(ptr);
+ return pfs;
+}
+
+/**
+ Find or create a table share lock instrumentation.
+ @return a table share lock, or NULL.
+*/
+PFS_table_share_lock*
+PFS_table_share::find_or_create_lock_stat()
+{
+ void *addr= & this->m_race_lock_stat;
+ void * volatile * typed_addr= static_cast<void * volatile *>(addr);
+ void *ptr;
+
+ /* (1) Atomic Load */
+ ptr= my_atomic_loadptr(typed_addr);
+
+ PFS_table_share_lock *pfs;
+ if (ptr != NULL)
+ {
+ pfs= static_cast<PFS_table_share_lock *>(ptr);
+ return pfs;
+ }
+
+ /* (2) Create a lock stat */
+ pfs= create_table_share_lock_stat();
+ if (pfs == NULL)
+ return NULL;
+ pfs->m_owner= this;
+
+ void *old_ptr= NULL;
+ ptr= pfs;
+
+ /* (3) Atomic CAS */
+ if (my_atomic_casptr(typed_addr, & old_ptr, ptr))
+ {
+ /* Ok. */
+ return pfs;
+ }
+
+ /* Collision with another thread that also executed (2) and (3). */
+ release_table_share_lock_stat(pfs);
+
+ pfs= static_cast<PFS_table_share_lock *>(old_ptr);
+ return pfs;
+}
+
+/** Destroy a table share lock instrumentation. */
+void PFS_table_share::destroy_lock_stat()
+{
+ void *addr= & this->m_race_lock_stat;
+ void * volatile * typed_addr= static_cast<void * volatile *>(addr);
+ void *new_ptr= NULL;
+ void *old_ptr;
+
+ old_ptr= my_atomic_fasptr(typed_addr, new_ptr);
+ if (old_ptr != NULL)
+ {
+ PFS_table_share_lock *pfs;
+ pfs= static_cast<PFS_table_share_lock *>(old_ptr);
+ release_table_share_lock_stat(pfs);
+ }
+}
+
+/**
+ Find an existing table share index instrumentation.
+ @return a table share index
+*/
+PFS_table_share_index*
+PFS_table_share::find_index_stat(uint index) const
+{
+ DBUG_ASSERT(index <= MAX_INDEXES);
+
+ PFS_table_share *that= const_cast<PFS_table_share*>(this);
+ void *addr= & that->m_race_index_stat[index];
+ void * volatile * typed_addr= static_cast<void * volatile *>(addr);
+ void *ptr;
+
+ /* Atomic Load */
+ ptr= my_atomic_loadptr(typed_addr);
+
+ PFS_table_share_index *pfs;
+ pfs= static_cast<PFS_table_share_index *>(ptr);
+ return pfs;
+}
+
+/**
+ Find or create a table share index instrumentation.
+ @param server_share
+ @index index
+ @return a table share index, or NULL
+*/
+PFS_table_share_index*
+PFS_table_share::find_or_create_index_stat(const TABLE_SHARE *server_share, uint index)
+{
+ DBUG_ASSERT(index <= MAX_INDEXES);
+
+ void *addr= & this->m_race_index_stat[index];
+ void * volatile * typed_addr= static_cast<void * volatile *>(addr);
+ void *ptr;
+
+ /* (1) Atomic Load */
+ ptr= my_atomic_loadptr(typed_addr);
+
+ PFS_table_share_index *pfs;
+ if (ptr != NULL)
+ {
+ pfs= static_cast<PFS_table_share_index *>(ptr);
+ return pfs;
+ }
+
+ /* (2) Create an index stat */
+ pfs= create_table_share_index_stat(server_share, index);
+ if (pfs == NULL)
+ return NULL;
+ pfs->m_owner= this;
+
+ void *old_ptr= NULL;
+ ptr= pfs;
+
+ /* (3) Atomic CAS */
+ if (my_atomic_casptr(typed_addr, & old_ptr, ptr))
+ {
+ /* Ok. */
+ return pfs;
+ }
+
+ /* Collision with another thread that also executed (2) and (3). */
+ release_table_share_index_stat(pfs);
+
+ pfs= static_cast<PFS_table_share_index *>(old_ptr);
+ return pfs;
+}
+
+/** Destroy table share index instrumentation. */
+void PFS_table_share::destroy_index_stats()
+{
+ uint index;
+
+ for (index= 0; index <= MAX_INDEXES; index++)
+ {
+ void *addr= & this->m_race_index_stat[index];
+ void * volatile * typed_addr= static_cast<void * volatile *>(addr);
+ void *new_ptr= NULL;
+ void *old_ptr;
+
+ old_ptr= my_atomic_fasptr(typed_addr, new_ptr);
+ if (old_ptr != NULL)
+ {
+ PFS_table_share_index *pfs;
+ pfs= static_cast<PFS_table_share_index *>(old_ptr);
+ release_table_share_index_stat(pfs);
+ }
+ }
+}
+
void PFS_table_share::refresh_setup_object_flags(PFS_thread *thread)
{
+ bool old_enabled= m_enabled;
+
lookup_setup_object(thread,
OBJECT_TYPE_TABLE,
m_schema_name, m_schema_name_length,
m_table_name, m_table_name_length,
&m_enabled, &m_timed);
+
+ /*
+ If instrumentation for this table was enabled earlier and is disabled now,
+ cleanup slots reserved for lock stats and index stats.
+ */
+ if (old_enabled && ! m_enabled)
+ {
+ destroy_lock_stat();
+ destroy_index_stats();
+ }
+}
+
+/**
+ Initialize the table lock stat buffer.
+ @param table_stat_sizing max number of table lock statistics
+ @return 0 on success
+*/
+int init_table_share_lock_stat(uint table_stat_sizing)
+{
+ if (global_table_share_lock_container.init(table_stat_sizing))
+ return 1;
+
+ return 0;
+}
+
+/**
+ Create a table share lock instrumentation.
+ @return table share lock instrumentation, or NULL
+*/
+PFS_table_share_lock*
+create_table_share_lock_stat()
+{
+ PFS_table_share_lock *pfs= NULL;
+ pfs_dirty_state dirty_state;
+
+ /* Create a new record in table stat array. */
+ pfs= global_table_share_lock_container.allocate(& dirty_state);
+ if (pfs != NULL)
+ {
+ /* Reset the stats. */
+ pfs->m_stat.reset();
+
+ /* Use this stat buffer. */
+ pfs->m_lock.dirty_to_allocated(& dirty_state);
+ }
+
+ return pfs;
+}
+
+/** Release a table share lock instrumentation. */
+void release_table_share_lock_stat(PFS_table_share_lock *pfs)
+{
+ pfs->m_owner= NULL;
+ global_table_share_lock_container.deallocate(pfs);
+ return;
+}
+
+/** Cleanup the table stat buffers. */
+void cleanup_table_share_lock_stat(void)
+{
+ global_table_share_lock_container.cleanup();
+}
+
+/**
+ Initialize table index stat buffer.
+ @param index_stat_sizing max number of index statistics
+ @return 0 on success
+*/
+int init_table_share_index_stat(uint index_stat_sizing)
+{
+ if (global_table_share_index_container.init(index_stat_sizing))
+ return 1;
+
+ return 0;
+}
+
+/**
+ Create a table share index instrumentation.
+ @return table share index instrumentation, or NULL
+*/
+PFS_table_share_index*
+create_table_share_index_stat(const TABLE_SHARE *server_share, uint server_index)
+{
+ DBUG_ASSERT((server_share != NULL) || (server_index == MAX_INDEXES));
+
+ PFS_table_share_index *pfs= NULL;
+ pfs_dirty_state dirty_state;
+
+ /* Create a new record in index stat array. */
+ pfs= global_table_share_index_container.allocate(& dirty_state);
+ if (pfs != NULL)
+ {
+ if (server_index == MAX_INDEXES)
+ {
+ pfs->m_key.m_name_length= 0;
+ }
+ else
+ {
+ KEY *key_info= server_share->key_info + server_index;
+ size_t len= strlen(key_info->name);
+
+ memcpy(pfs->m_key.m_name, key_info->name, len);
+ pfs->m_key.m_name_length= len;
+ }
+
+ /* Reset the stats. */
+ pfs->m_stat.reset();
+
+ /* Use this stat buffer. */
+ pfs->m_lock.dirty_to_allocated(& dirty_state);
+ }
+
+ return pfs;
+}
+
+/** Release a table share index instrumentation. */
+void release_table_share_index_stat(PFS_table_share_index *pfs)
+{
+ pfs->m_owner= NULL;
+ global_table_share_index_container.deallocate(pfs);
+ return;
+}
+
+/** Cleanup the table stat buffers. */
+void cleanup_table_share_index_stat(void)
+{
+ global_table_share_index_container.cleanup();
}
/**
@@ -482,8 +823,10 @@ int init_file_class(uint file_class_sizing)
if (file_class_max > 0)
{
- file_class_array= PFS_MALLOC_ARRAY(file_class_max, sizeof(PFS_file_class),
- PFS_file_class, MYF(MY_ZEROFILL));
+ file_class_array= PFS_MALLOC_ARRAY(& builtin_memory_file_class,
+ file_class_max,
+ sizeof(PFS_file_class), PFS_file_class,
+ MYF(MY_ZEROFILL));
if (unlikely(file_class_array == NULL))
return 1;
}
@@ -496,7 +839,9 @@ int init_file_class(uint file_class_sizing)
/** Cleanup the file class buffers. */
void cleanup_file_class(void)
{
- pfs_free(file_class_array);
+ PFS_FREE_ARRAY(& builtin_memory_file_class,
+ file_class_max, sizeof(PFS_file_class),
+ file_class_array);
file_class_array= NULL;
file_class_dirty_count= file_class_allocated_count= 0;
file_class_max= 0;
@@ -516,8 +861,10 @@ int init_stage_class(uint stage_class_sizing)
if (stage_class_max > 0)
{
- stage_class_array= PFS_MALLOC_ARRAY(stage_class_max, sizeof(PFS_stage_class),
- PFS_stage_class, MYF(MY_ZEROFILL));
+ stage_class_array= PFS_MALLOC_ARRAY(& builtin_memory_stage_class,
+ stage_class_max,
+ sizeof(PFS_stage_class), PFS_stage_class,
+ MYF(MY_ZEROFILL));
if (unlikely(stage_class_array == NULL))
return 1;
}
@@ -530,7 +877,9 @@ int init_stage_class(uint stage_class_sizing)
/** Cleanup the stage class buffers. */
void cleanup_stage_class(void)
{
- pfs_free(stage_class_array);
+ PFS_FREE_ARRAY(& builtin_memory_stage_class,
+ stage_class_max, sizeof(PFS_stage_class),
+ stage_class_array);
stage_class_array= NULL;
stage_class_dirty_count= stage_class_allocated_count= 0;
stage_class_max= 0;
@@ -550,8 +899,10 @@ int init_statement_class(uint statement_class_sizing)
if (statement_class_max > 0)
{
- statement_class_array= PFS_MALLOC_ARRAY(statement_class_max, sizeof(PFS_statement_class),
- PFS_statement_class, MYF(MY_ZEROFILL));
+ statement_class_array= PFS_MALLOC_ARRAY(& builtin_memory_statement_class,
+ statement_class_max,
+ sizeof(PFS_statement_class), PFS_statement_class,
+ MYF(MY_ZEROFILL));
if (unlikely(statement_class_array == NULL))
return 1;
}
@@ -564,7 +915,9 @@ int init_statement_class(uint statement_class_sizing)
/** Cleanup the statement class buffers. */
void cleanup_statement_class(void)
{
- pfs_free(statement_class_array);
+ PFS_FREE_ARRAY(& builtin_memory_statement_class,
+ statement_class_max, sizeof(PFS_statement_class),
+ statement_class_array);
statement_class_array= NULL;
statement_class_dirty_count= statement_class_allocated_count= 0;
statement_class_max= 0;
@@ -584,8 +937,10 @@ int init_socket_class(uint socket_class_sizing)
if (socket_class_max > 0)
{
- socket_class_array= PFS_MALLOC_ARRAY(socket_class_max, sizeof(PFS_socket_class),
- PFS_socket_class, MYF(MY_ZEROFILL));
+ socket_class_array= PFS_MALLOC_ARRAY(& builtin_memory_socket_class,
+ socket_class_max,
+ sizeof(PFS_socket_class), PFS_socket_class,
+ MYF(MY_ZEROFILL));
if (unlikely(socket_class_array == NULL))
return 1;
}
@@ -598,12 +953,52 @@ int init_socket_class(uint socket_class_sizing)
/** Cleanup the socket class buffers. */
void cleanup_socket_class(void)
{
- pfs_free(socket_class_array);
+ PFS_FREE_ARRAY(& builtin_memory_socket_class,
+ socket_class_max, sizeof(PFS_socket_class),
+ socket_class_array);
socket_class_array= NULL;
socket_class_dirty_count= socket_class_allocated_count= 0;
socket_class_max= 0;
}
+/**
+ Initialize the memory class buffer.
+ @param memory_class_sizing max number of memory class
+ @return 0 on success
+*/
+int init_memory_class(uint memory_class_sizing)
+{
+ int result= 0;
+ memory_class_dirty_count= memory_class_allocated_count= 0;
+ memory_class_max= memory_class_sizing;
+ memory_class_lost= 0;
+
+ if (memory_class_max > 0)
+ {
+ memory_class_array= PFS_MALLOC_ARRAY(& builtin_memory_memory_class,
+ memory_class_max,
+ sizeof(PFS_memory_class), PFS_memory_class,
+ MYF(MY_ZEROFILL));
+ if (unlikely(memory_class_array == NULL))
+ return 1;
+ }
+ else
+ memory_class_array= NULL;
+
+ return result;
+}
+
+/** Cleanup the memory class buffers. */
+void cleanup_memory_class(void)
+{
+ PFS_FREE_ARRAY(& builtin_memory_memory_class,
+ memory_class_max, sizeof(PFS_memory_class),
+ memory_class_array);
+ memory_class_array= NULL;
+ memory_class_dirty_count= memory_class_allocated_count= 0;
+ memory_class_max= 0;
+}
+
static void init_instr_class(PFS_instr_class *klass,
const char *name,
uint name_length,
@@ -612,7 +1007,7 @@ static void init_instr_class(PFS_instr_class *klass,
{
DBUG_ASSERT(name_length <= PFS_MAX_INFO_NAME_LENGTH);
memset(klass, 0, sizeof(PFS_instr_class));
- strncpy(klass->m_name, name, name_length);
+ memcpy(klass->m_name, name, name_length);
klass->m_name_length= name_length;
klass->m_flags= flags;
klass->m_enabled= true;
@@ -628,10 +1023,13 @@ static void configure_instr_class(PFS_instr_class *entry)
{
uint match_length= 0; /* length of matching pattern */
- for (uint i= 0; i < pfs_instr_config_array.elements; i++)
+ // May be NULL in unit tests
+ if (pfs_instr_config_array == NULL)
+ return;
+ PFS_instr_config **it= pfs_instr_config_array->front();
+ for ( ; it != pfs_instr_config_array->end(); it++)
{
- PFS_instr_config* e;
- get_dynamic(&pfs_instr_config_array, (uchar*)&e, i);
+ PFS_instr_config* e= *it;
/**
Compare class name to all configuration entries. In case of multiple
@@ -757,7 +1155,8 @@ PFS_sync_key register_mutex_class(const char *name, uint name_length,
Out of space, report to SHOW STATUS that
the allocated memory was too small.
*/
- mutex_class_lost++;
+ if (pfs_enabled)
+ mutex_class_lost++;
return 0;
}
@@ -795,7 +1194,8 @@ PFS_sync_key register_rwlock_class(const char *name, uint name_length,
return (index + 1);
}
- rwlock_class_lost++;
+ if (pfs_enabled)
+ rwlock_class_lost++;
return 0;
}
@@ -832,7 +1232,8 @@ PFS_sync_key register_cond_class(const char *name, uint name_length,
return (index + 1);
}
- cond_class_lost++;
+ if (pfs_enabled)
+ cond_class_lost++;
return 0;
}
@@ -922,7 +1323,8 @@ PFS_thread_key register_thread_class(const char *name, uint name_length,
return (index + 1);
}
- thread_class_lost++;
+ if (pfs_enabled)
+ thread_class_lost++;
return 0;
}
@@ -971,10 +1373,12 @@ PFS_file_key register_file_class(const char *name, uint name_length,
/* Set user-defined configuration options for this instrument */
configure_instr_class(entry);
PFS_atomic::add_u32(&file_class_allocated_count, 1);
+
return (index + 1);
}
- file_class_lost++;
+ if (pfs_enabled)
+ file_class_lost++;
return 0;
}
@@ -1006,8 +1410,20 @@ PFS_stage_key register_stage_class(const char *name,
init_instr_class(entry, name, name_length, flags, PFS_CLASS_STAGE);
entry->m_prefix_length= prefix_length;
entry->m_event_name_index= index;
- entry->m_enabled= false; /* disabled by default */
- entry->m_timed= false;
+
+ if (flags & PSI_FLAG_STAGE_PROGRESS)
+ {
+ /* Stages with progress information are enabled and timed by default */
+ entry->m_enabled= true;
+ entry->m_timed= true;
+ }
+ else
+ {
+ /* Stages without progress information are disabled by default */
+ entry->m_enabled= false;
+ entry->m_timed= false;
+ }
+
/* Set user-defined configuration options for this instrument */
configure_instr_class(entry);
PFS_atomic::add_u32(&stage_class_allocated_count, 1);
@@ -1015,7 +1431,8 @@ PFS_stage_key register_stage_class(const char *name,
return (index + 1);
}
- stage_class_lost++;
+ if (pfs_enabled)
+ stage_class_lost++;
return 0;
}
@@ -1052,7 +1469,8 @@ PFS_statement_key register_statement_class(const char *name, uint name_length,
return (index + 1);
}
- statement_class_lost++;
+ if (pfs_enabled)
+ statement_class_lost++;
return 0;
}
@@ -1134,7 +1552,8 @@ PFS_socket_key register_socket_class(const char *name, uint name_length,
return (index + 1);
}
- socket_class_lost++;
+ if (pfs_enabled)
+ socket_class_lost++;
return 0;
}
@@ -1153,6 +1572,58 @@ PFS_socket_class *sanitize_socket_class(PFS_socket_class *unsafe)
SANITIZE_ARRAY_BODY(PFS_socket_class, socket_class_array, socket_class_max, unsafe);
}
+/**
+ Register a memory instrumentation metadata.
+ @param name the instrumented name
+ @param name_length length in bytes of name
+ @param flags the instrumentation flags
+ @return a memory instrumentation key
+*/
+PFS_memory_key register_memory_class(const char *name, uint name_length,
+ int flags)
+{
+ /* See comments in register_mutex_class */
+ uint32 index;
+ PFS_memory_class *entry;
+
+ REGISTER_CLASS_BODY_PART(index, memory_class_array, memory_class_max,
+ name, name_length)
+
+ index= PFS_atomic::add_u32(&memory_class_dirty_count, 1);
+
+ if (index < memory_class_max)
+ {
+ entry= &memory_class_array[index];
+ init_instr_class(entry, name, name_length, flags, PFS_CLASS_MEMORY);
+ entry->m_event_name_index= index;
+ entry->m_enabled= false; /* disabled by default */
+ /* Set user-defined configuration options for this instrument */
+ configure_instr_class(entry);
+ entry->m_timed= false; /* Immutable */
+ PFS_atomic::add_u32(&memory_class_allocated_count, 1);
+ return (index + 1);
+ }
+
+ if (pfs_enabled)
+ memory_class_lost++;
+ return 0;
+}
+
+/**
+ Find a memory instrumentation class by key.
+ @param key the instrument key
+ @return the instrument class, or NULL
+*/
+PFS_memory_class *find_memory_class(PFS_memory_key key)
+{
+ FIND_CLASS_BODY(key, memory_class_allocated_count, memory_class_array);
+}
+
+PFS_memory_class *sanitize_memory_class(PFS_memory_class *unsafe)
+{
+ SANITIZE_ARRAY_BODY(PFS_memory_class, memory_class_array, memory_class_max, unsafe);
+}
+
PFS_instr_class *find_table_class(uint index)
{
if (index == 1)
@@ -1184,49 +1655,64 @@ PFS_instr_class *sanitize_idle_class(PFS_instr_class *unsafe)
return NULL;
}
-static void set_keys(PFS_table_share *pfs, const TABLE_SHARE *share)
+PFS_instr_class *find_metadata_class(uint index)
{
- uint len;
- KEY *key_info= share->key_info;
- PFS_table_key *pfs_key= pfs->m_keys;
- PFS_table_key *pfs_key_last= pfs->m_keys + share->keys;
- pfs->m_key_count= share->keys;
+ if (index == 1)
+ return & global_metadata_class;
+ return NULL;
+}
- for ( ; pfs_key < pfs_key_last; pfs_key++, key_info++)
- {
- len= (uint)key_info->name.length;
- memcpy(pfs_key->m_name, key_info->name.str, len);
- pfs_key->m_name_length= len;
- }
+PFS_instr_class *sanitize_metadata_class(PFS_instr_class *unsafe)
+{
+ if (likely(& global_metadata_class == unsafe))
+ return unsafe;
+ return NULL;
+}
- pfs_key_last= pfs->m_keys + MAX_INDEXES;
- for ( ; pfs_key < pfs_key_last; pfs_key++)
- pfs_key->m_name_length= 0;
+PFS_transaction_class *find_transaction_class(uint index)
+{
+ if (index == 1)
+ return &global_transaction_class;
+ return NULL;
}
-static int compare_keys(PFS_table_share *pfs, const TABLE_SHARE *share)
+PFS_transaction_class *sanitize_transaction_class(PFS_transaction_class *unsafe)
{
- uint len;
- KEY *key_info= share->key_info;
- PFS_table_key *pfs_key= pfs->m_keys;
- PFS_table_key *pfs_key_last= pfs->m_keys + share->keys;
+ if (likely(&global_transaction_class == unsafe))
+ return unsafe;
+ return NULL;
+}
+static int compare_keys(PFS_table_share *pfs, const TABLE_SHARE *share)
+{
if (pfs->m_key_count != share->keys)
return 1;
- for ( ; pfs_key < pfs_key_last; pfs_key++, key_info++)
+ size_t len;
+ uint index= 0;
+ uint key_count= share->keys;
+ KEY *key_info= share->key_info;
+ PFS_table_share_index *index_stat;
+
+ for ( ; index < key_count; key_info++, index++)
{
- len= (uint)key_info->name.length;
- if (len != pfs_key->m_name_length)
- return 1;
+ index_stat= pfs->find_index_stat(index);
+ if (index_stat != NULL)
+ {
+ len= key_info->name.length;
- if (memcmp(pfs_key->m_name, key_info->name.str, len) != 0)
- return 1;
+ if (len != index_stat->m_key.m_name_length)
+ return 1;
+
+ if (memcmp(index_stat->m_key.m_name, key_info->name.str, len) != 0)
+ return 1;
+ }
}
return 0;
}
+
/**
Find or create a table share instrumentation.
@param thread the executing instrumented thread
@@ -1244,14 +1730,14 @@ PFS_table_share* find_or_create_table_share(PFS_thread *thread,
LF_PINS *pins= get_table_share_hash_pins(thread);
if (unlikely(pins == NULL))
{
- table_share_lost++;
+ global_table_share_container.m_lost++;
return NULL;
}
const char *schema_name= share->db.str;
- uint schema_name_length= (uint)share->db.length;
+ size_t schema_name_length= share->db.length;
const char *table_name= share->table_name.str;
- uint table_name_length= (uint)share->table_name.length;
+ size_t table_name_length= share->table_name.length;
set_table_share_key(&key, temporary,
schema_name, schema_name_length,
@@ -1262,10 +1748,8 @@ PFS_table_share* find_or_create_table_share(PFS_thread *thread,
const uint retry_max= 3;
bool enabled= true;
bool timed= true;
- static uint PFS_ALIGNED table_share_monotonic_index= 0;
- uint index;
- uint attempts= 0;
PFS_table_share *pfs;
+ pfs_dirty_state dirty_state;
search:
entry= reinterpret_cast<PFS_table_share**>
@@ -1277,9 +1761,19 @@ search:
pfs->inc_refcount() ;
if (compare_keys(pfs, share) != 0)
{
- set_keys(pfs, share);
- /* FIXME: aggregate to table_share sink ? */
- pfs->m_table_stat.fast_reset();
+ /*
+ Some DDL was detected.
+ - keep the lock stats, they are unaffected
+ - destroy the index stats, indexes changed.
+ - adjust the expected key count
+ - recreate index stats
+ */
+ pfs->destroy_index_stats();
+ pfs->m_key_count= share->keys;
+ for (uint index= 0; index < pfs->m_key_count; index++)
+ {
+ (void)pfs->find_or_create_index_stat(share, index);
+ }
}
lf_hash_search_unpin(pins);
return pfs;
@@ -1302,85 +1796,136 @@ search:
*/
}
- while (++attempts <= table_share_max)
+ pfs= global_table_share_container.allocate(& dirty_state);
+ if (pfs != NULL)
{
- /* See create_mutex() */
- index= PFS_atomic::add_u32(& table_share_monotonic_index, 1) % table_share_max;
- pfs= table_share_array + index;
-
- if (pfs->m_lock.is_free())
+ pfs->m_key= key;
+ pfs->m_schema_name= &pfs->m_key.m_hash_key[1];
+ pfs->m_schema_name_length= schema_name_length;
+ pfs->m_table_name= &pfs->m_key.m_hash_key[schema_name_length + 2];
+ pfs->m_table_name_length= table_name_length;
+ pfs->m_enabled= enabled;
+ pfs->m_timed= timed;
+ pfs->init_refcount();
+ pfs->destroy_lock_stat();
+ pfs->destroy_index_stats();
+ pfs->m_key_count= share->keys;
+
+ int res;
+ pfs->m_lock.dirty_to_allocated(& dirty_state);
+ res= lf_hash_insert(&table_share_hash, pins, &pfs);
+
+ if (likely(res == 0))
{
- if (pfs->m_lock.free_to_dirty())
+ /* Create table share index stats. */
+ for (uint index= 0; index < pfs->m_key_count; index++)
{
- pfs->m_key= key;
- pfs->m_schema_name= &pfs->m_key.m_hash_key[1];
- pfs->m_schema_name_length= schema_name_length;
- pfs->m_table_name= &pfs->m_key.m_hash_key[schema_name_length + 2];
- pfs->m_table_name_length= table_name_length;
- pfs->m_enabled= enabled;
- pfs->m_timed= timed;
- pfs->init_refcount();
- pfs->m_table_stat.fast_reset();
- set_keys(pfs, share);
-
- int res;
- res= lf_hash_insert(&table_share_hash, pins, &pfs);
- if (likely(res == 0))
- {
- pfs->m_lock.dirty_to_allocated();
- return pfs;
- }
-
- pfs->m_lock.dirty_to_free();
+ (void)pfs->find_or_create_index_stat(share, index);
+ }
+ return pfs;
+ }
- if (res > 0)
- {
- /* Duplicate insert by another thread */
- if (++retry_count > retry_max)
- {
- /* Avoid infinite loops */
- table_share_lost++;
- return NULL;
- }
- goto search;
- }
+ global_table_share_container.deallocate(pfs);
- /* OOM in lf_hash_insert */
- table_share_lost++;
+ if (res > 0)
+ {
+ /* Duplicate insert by another thread */
+ if (++retry_count > retry_max)
+ {
+ /* Avoid infinite loops */
+ global_table_share_container.m_lost++;
return NULL;
}
+ goto search;
}
+
+ /* OOM in lf_hash_insert */
+ global_table_share_container.m_lost++;
+ return NULL;
}
- table_share_lost++;
return NULL;
}
void PFS_table_share::aggregate_io(void)
{
+ uint index;
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_share_index *from_stat;
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);
+ for (index= 0; index < safe_key_count; index++)
+ {
+ from_stat= find_index_stat(index);
+ if (from_stat != NULL)
+ {
+ sum_io.aggregate(& from_stat->m_stat);
+ from_stat->m_stat.reset();
+ }
+ }
/* Aggregate stats for the table */
- sum_io.aggregate(& m_table_stat.m_index_stat[MAX_INDEXES]);
+ from_stat= find_index_stat(MAX_INDEXES);
+ if (from_stat != NULL)
+ {
+ sum_io.aggregate(& from_stat->m_stat);
+ from_stat->m_stat.reset();
+ }
/* 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::sum_io(PFS_single_stat *result, uint key_count)
+{
+ uint index;
+ PFS_table_share_index *stat;
+
+ DBUG_ASSERT(key_count <= MAX_INDEXES);
+
+ /* Sum stats for each index, if any */
+ for (index= 0; index < key_count; index++)
+ {
+ stat= find_index_stat(index);
+ if (stat != NULL)
+ {
+ stat->m_stat.sum(result);
+ }
+ }
+
+ /* Sum stats for the table */
+ stat= find_index_stat(MAX_INDEXES);
+ if (stat != NULL)
+ {
+ stat->m_stat.sum(result);
+ }
+}
+
+void PFS_table_share::sum_lock(PFS_single_stat *result)
+{
+ PFS_table_share_lock *lock_stat;
+ lock_stat= find_lock_stat();
+ if (lock_stat != NULL)
+ lock_stat->m_stat.sum(result);
+}
+
+void PFS_table_share::sum(PFS_single_stat *result, uint key_count)
+{
+ sum_io(result, key_count);
+ sum_lock(result);
}
void PFS_table_share::aggregate_lock(void)
{
- global_table_lock_stat.aggregate(& m_table_stat.m_lock_stat);
- m_table_stat.fast_reset_lock();
+ PFS_table_share_lock *lock_stat;
+ lock_stat= find_lock_stat();
+ if (lock_stat != NULL)
+ {
+ global_table_lock_stat.aggregate(& lock_stat->m_stat);
+ /* Reset lock stat. */
+ lock_stat->m_stat.reset();
+ }
}
void release_table_share(PFS_table_share *pfs)
@@ -1418,6 +1963,9 @@ void drop_table_share(PFS_thread *thread,
PFS_table_share *pfs= *entry;
lf_hash_delete(&table_share_hash, pins,
pfs->m_key.m_hash_key, pfs->m_key.m_key_length);
+ pfs->destroy_lock_stat();
+ pfs->destroy_index_stats();
+
pfs->m_lock.allocated_to_free();
}
@@ -1431,7 +1979,7 @@ void drop_table_share(PFS_thread *thread,
*/
PFS_table_share *sanitize_table_share(PFS_table_share *unsafe)
{
- SANITIZE_ARRAY_BODY(PFS_table_share, table_share_array, table_share_max, unsafe);
+ return global_table_share_container.sanitize(unsafe);
}
/** Reset the wait statistics per instrument class. */
@@ -1442,6 +1990,7 @@ void reset_events_waits_by_class()
global_idle_stat.reset();
global_table_io_stat.reset();
global_table_lock_stat.reset();
+ global_metadata_stat.reset();
}
/** Reset the io statistics per file class. */
@@ -1464,16 +2013,50 @@ void reset_socket_class_io(void)
pfs->m_socket_stat.m_io_stat.reset();
}
+class Proc_table_share_derived_flags
+ : public PFS_buffer_processor<PFS_table_share>
+{
+public:
+ Proc_table_share_derived_flags(PFS_thread *thread)
+ : m_thread(thread)
+ {}
+
+ virtual void operator()(PFS_table_share *pfs)
+ {
+ pfs->refresh_setup_object_flags(m_thread);
+ }
+
+private:
+ PFS_thread* m_thread;
+};
+
void update_table_share_derived_flags(PFS_thread *thread)
{
- PFS_table_share *pfs= table_share_array;
- PFS_table_share *pfs_last= table_share_array + table_share_max;
+ Proc_table_share_derived_flags proc(thread);
+ global_table_share_container.apply(proc);
+}
- for ( ; pfs < pfs_last; pfs++)
+class Proc_program_share_derived_flags
+ : public PFS_buffer_processor<PFS_program>
+{
+public:
+ Proc_program_share_derived_flags(PFS_thread *thread)
+ : m_thread(thread)
+ {}
+
+ virtual void operator()(PFS_program *pfs)
{
- if (pfs->m_lock.is_populated())
- pfs->refresh_setup_object_flags(thread);
+ pfs->refresh_setup_object_flags(m_thread);
}
+
+private:
+ PFS_thread* m_thread;
+};
+
+void update_program_share_derived_flags(PFS_thread *thread)
+{
+ Proc_program_share_derived_flags proc(thread);
+ global_program_container.apply(proc);
}
/** @} */
diff --git a/storage/perfschema/pfs_instr_class.h b/storage/perfschema/pfs_instr_class.h
index 9d256fac78a..573cfe33ffb 100644
--- a/storage/perfschema/pfs_instr_class.h
+++ b/storage/perfschema/pfs_instr_class.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2016, 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, version 2.0,
@@ -27,6 +27,8 @@
#include "mysql_com.h" /* NAME_LEN */
#include "lf.h"
#include "pfs_global.h"
+#include "pfs_atomic.h"
+#include "sql_array.h"
/**
@file storage/perfschema/pfs_instr_class.h
@@ -48,7 +50,6 @@
*/
#define PFS_MAX_FULL_PREFIX_NAME_LENGTH 32
-#include <my_global.h>
#include <my_sys.h>
#include <mysql/psi/psi.h>
#include "pfs_lock.h"
@@ -56,6 +57,8 @@
#include "pfs_column_types.h"
struct PFS_global_param;
+struct PFS_table_share;
+class PFS_opaque_container_page;
/**
@addtogroup Performance_schema_buffers
@@ -75,8 +78,12 @@ typedef unsigned int PFS_file_key;
typedef unsigned int PFS_stage_key;
/** Key, naming a statement instrument. */
typedef unsigned int PFS_statement_key;
+/** Key, naming a transaction instrument. */
+typedef unsigned int PFS_transaction_key;
/** Key, naming a socket instrument. */
typedef unsigned int PFS_socket_key;
+/** Key, naming a memory instrument. */
+typedef unsigned int PFS_memory_key;
enum PFS_class_type
{
@@ -88,11 +95,14 @@ enum PFS_class_type
PFS_CLASS_TABLE= 5,
PFS_CLASS_STAGE= 6,
PFS_CLASS_STATEMENT= 7,
- PFS_CLASS_SOCKET= 8,
- PFS_CLASS_TABLE_IO= 9,
- PFS_CLASS_TABLE_LOCK= 10,
- PFS_CLASS_IDLE= 11,
- PFS_CLASS_LAST= PFS_CLASS_IDLE,
+ PFS_CLASS_TRANSACTION= 8,
+ PFS_CLASS_SOCKET= 9,
+ PFS_CLASS_TABLE_IO= 10,
+ PFS_CLASS_TABLE_LOCK= 11,
+ PFS_CLASS_IDLE= 12,
+ PFS_CLASS_MEMORY= 13,
+ PFS_CLASS_METADATA= 14,
+ PFS_CLASS_LAST= PFS_CLASS_METADATA,
PFS_CLASS_MAX= PFS_CLASS_LAST + 1
};
@@ -109,12 +119,8 @@ struct PFS_instr_config
bool m_timed;
};
-extern DYNAMIC_ARRAY pfs_instr_config_array;
-extern int pfs_instr_config_state;
-
-static const int PFS_INSTR_CONFIG_NOT_INITIALIZED= 0;
-static const int PFS_INSTR_CONFIG_ALLOCATED= 1;
-static const int PFS_INSTR_CONFIG_DEALLOCATED= 2;
+typedef Dynamic_array<PFS_instr_config*> Pfs_instr_config_array;
+extern Pfs_instr_config_array *pfs_instr_config_array;
struct PFS_thread;
@@ -136,12 +142,15 @@ struct PFS_instr_class
bool m_timed;
/** Instrument flags. */
int m_flags;
+ /** Volatility index. */
+ int m_volatility;
/**
Instrument name index.
Self index in:
- EVENTS_WAITS_SUMMARY_*_BY_EVENT_NAME for waits
- EVENTS_STAGES_SUMMARY_*_BY_EVENT_NAME for stages
- EVENTS_STATEMENTS_SUMMARY_*_BY_EVENT_NAME for statements
+ - EVENTS_TRANSACTIONS_SUMMARY_*_BY_EVENT_NAME for transactions
*/
uint m_event_name_index;
/** Instrument name. */
@@ -161,6 +170,18 @@ struct PFS_instr_class
return m_flags & PSI_FLAG_MUTABLE;
}
+ bool is_progress() const
+ {
+ DBUG_ASSERT(m_type == PFS_CLASS_STAGE);
+ return m_flags & PSI_FLAG_STAGE_PROGRESS;
+ }
+
+ bool is_shared_exclusive() const
+ {
+ DBUG_ASSERT(m_type == PFS_CLASS_RWLOCK);
+ return m_flags & PSI_RWLOCK_FLAG_SX;
+ }
+
static void set_enabled(PFS_instr_class *pfs, bool enabled);
static void set_timed(PFS_instr_class *pfs, bool timed);
@@ -252,6 +273,32 @@ struct PFS_table_key
uint m_name_length;
};
+/** Index statistics of a table.*/
+struct PFS_table_share_index
+{
+ pfs_lock m_lock;
+ /** The index name */
+ PFS_table_key m_key;
+ /** The index stat */
+ PFS_table_io_stat m_stat;
+ /** Owner table share. To be used later. */
+ PFS_table_share* m_owner;
+ /** Container page. */
+ PFS_opaque_container_page *m_page;
+};
+
+/** Lock statistics of a table.*/
+struct PFS_table_share_lock
+{
+ pfs_lock m_lock;
+ /** Lock stats. */
+ PFS_table_lock_stat m_stat;
+ /** Owner table share. To be used later. */
+ PFS_table_share* m_owner;
+ /** Container page. */
+ PFS_opaque_container_page *m_page;
+};
+
/** Instrumentation metadata for a table share. */
struct PFS_ALIGNED PFS_table_share
{
@@ -267,6 +314,10 @@ public:
void aggregate_io(void);
void aggregate_lock(void);
+ void sum_io(PFS_single_stat *result, uint key_count);
+ void sum_lock(PFS_single_stat *result);
+ void sum(PFS_single_stat *result, uint key_count);
+
inline void aggregate(void)
{
aggregate_io();
@@ -307,6 +358,7 @@ public:
This flag is computed from the content of table setup_objects.
*/
bool m_timed;
+
/** Search key. */
PFS_table_share_key m_key;
/** Schema name. */
@@ -319,14 +371,24 @@ public:
uint m_table_name_length;
/** Number of indexes. */
uint m_key_count;
- /** Table statistics. */
- PFS_table_stat m_table_stat;
- /** Index names. */
- PFS_table_key m_keys[MAX_INDEXES];
+ /** Container page. */
+ PFS_opaque_container_page *m_page;
+
+ PFS_table_share_lock *find_lock_stat() const;
+ PFS_table_share_lock *find_or_create_lock_stat();
+ void destroy_lock_stat();
+
+ PFS_table_share_index *find_index_stat(uint index) const;
+ PFS_table_share_index *find_or_create_index_stat(const TABLE_SHARE *server_share, uint index);
+ void destroy_index_stats();
private:
/** Number of opened table handles. */
int m_refcount;
+ /** Table locks statistics. */
+ PFS_table_share_lock *m_race_lock_stat;
+ /** Table indexes' stats. */
+ PFS_table_share_index *m_race_index_stat[MAX_INDEXES + 1];
};
/** Statistics for the IDLE instrument. */
@@ -335,6 +397,10 @@ extern PFS_single_stat global_idle_stat;
extern PFS_table_io_stat global_table_io_stat;
/** Statistics for dropped table lock. */
extern PFS_table_lock_stat global_table_lock_stat;
+/** Statistics for the METADATA instrument. */
+extern PFS_single_stat global_metadata_stat;
+/** Statistics for the transaction instrument. */
+extern PFS_transaction_stat global_transaction_stat;
inline uint sanitize_index_count(uint count)
{
@@ -346,6 +412,12 @@ inline uint sanitize_index_count(uint count)
#define GLOBAL_TABLE_IO_EVENT_INDEX 0
#define GLOBAL_TABLE_LOCK_EVENT_INDEX 1
#define GLOBAL_IDLE_EVENT_INDEX 2
+#define GLOBAL_METADATA_EVENT_INDEX 3
+/** Number of global wait events. */
+#define COUNT_GLOBAL_EVENT_INDEX 4
+
+/** Transaction events are not wait events .*/
+#define GLOBAL_TRANSACTION_INDEX 0
/**
Instrument controlling all table io.
@@ -364,6 +436,8 @@ extern PFS_instr_class global_table_lock_class;
*/
extern PFS_instr_class global_idle_class;
+extern PFS_instr_class global_metadata_class;
+
struct PFS_file;
/** Instrumentation metadata for a file. */
@@ -392,7 +466,14 @@ struct PFS_ALIGNED PFS_statement_class : public PFS_instr_class
{
};
-struct PFS_socket;
+/** Instrumentation metadata for a transaction. */
+struct PFS_ALIGNED PFS_transaction_class : public PFS_instr_class
+{
+};
+
+extern PFS_transaction_class global_transaction_class;
+
+struct PFS_socket;
/** Instrumentation metadata for a socket. */
struct PFS_ALIGNED PFS_socket_class : public PFS_instr_class
@@ -403,6 +484,20 @@ struct PFS_ALIGNED PFS_socket_class : public PFS_instr_class
PFS_socket *m_singleton;
};
+/** Instrumentation metadata for a memory. */
+struct PFS_ALIGNED PFS_memory_class : public PFS_instr_class
+{
+ bool is_global() const
+ {
+ return m_flags & PSI_FLAG_GLOBAL;
+ }
+
+ bool is_transferable() const
+ {
+ return m_flags & PSI_FLAG_TRANSFER;
+ }
+};
+
void init_event_name_sizing(const PFS_global_param *param);
void register_global_classes();
@@ -416,7 +511,18 @@ int init_thread_class(uint thread_class_sizing);
void cleanup_thread_class();
int init_table_share(uint table_share_sizing);
void cleanup_table_share();
-int init_table_share_hash();
+
+int init_table_share_lock_stat(uint table_stat_sizing);
+void cleanup_table_share_lock_stat();
+PFS_table_share_lock* create_table_share_lock_stat();
+void release_table_share_lock_stat(PFS_table_share_lock *pfs);
+
+int init_table_share_index_stat(uint index_stat_sizing);
+void cleanup_table_share_index_stat();
+PFS_table_share_index* create_table_share_index_stat(const TABLE_SHARE *share, uint index);
+void release_table_share_index_stat(PFS_table_share_index *pfs);
+
+int init_table_share_hash(const PFS_global_param *param);
void cleanup_table_share_hash();
int init_file_class(uint file_class_sizing);
void cleanup_file_class();
@@ -426,6 +532,8 @@ int init_statement_class(uint statement_class_sizing);
void cleanup_statement_class();
int init_socket_class(uint socket_class_sizing);
void cleanup_socket_class();
+int init_memory_class(uint memory_class_sizing);
+void cleanup_memory_class();
PFS_sync_key register_mutex_class(const char *name, uint name_length,
int flags);
@@ -453,6 +561,9 @@ PFS_statement_key register_statement_class(const char *name, uint name_length,
PFS_socket_key register_socket_class(const char *name, uint name_length,
int flags);
+PFS_memory_key register_memory_class(const char *name, uint name_length,
+ int flags);
+
PFS_mutex_class *find_mutex_class(PSI_mutex_key key);
PFS_mutex_class *sanitize_mutex_class(PFS_mutex_class *unsafe);
PFS_rwlock_class *find_rwlock_class(PSI_rwlock_key key);
@@ -471,8 +582,14 @@ PFS_instr_class *find_table_class(uint index);
PFS_instr_class *sanitize_table_class(PFS_instr_class *unsafe);
PFS_socket_class *find_socket_class(PSI_socket_key key);
PFS_socket_class *sanitize_socket_class(PFS_socket_class *unsafe);
+PFS_memory_class *find_memory_class(PSI_memory_key key);
+PFS_memory_class *sanitize_memory_class(PFS_memory_class *unsafe);
PFS_instr_class *find_idle_class(uint index);
PFS_instr_class *sanitize_idle_class(PFS_instr_class *unsafe);
+PFS_instr_class *find_metadata_class(uint index);
+PFS_instr_class *sanitize_metadata_class(PFS_instr_class *unsafe);
+PFS_transaction_class *find_transaction_class(uint index);
+PFS_transaction_class *sanitize_transaction_class(PFS_transaction_class *unsafe);
PFS_table_share *find_or_create_table_share(PFS_thread *thread,
bool temporary,
@@ -499,10 +616,11 @@ extern ulong stage_class_max;
extern ulong stage_class_lost;
extern ulong statement_class_max;
extern ulong statement_class_lost;
+extern ulong transaction_class_max;
extern ulong socket_class_max;
extern ulong socket_class_lost;
-extern ulong table_share_max;
-extern ulong table_share_lost;
+extern ulong memory_class_max;
+extern ulong memory_class_lost;
/* Exposing the data directly, for iterators. */
@@ -510,7 +628,6 @@ extern PFS_mutex_class *mutex_class_array;
extern PFS_rwlock_class *rwlock_class_array;
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();
@@ -519,6 +636,9 @@ void reset_socket_class_io();
/** Update derived flags for all table shares. */
void update_table_share_derived_flags(PFS_thread *thread);
+/** Update derived flags for all stored procedure shares. */
+void update_program_share_derived_flags(PFS_thread *thread);
+
extern LF_HASH table_share_hash;
/** @} */
diff --git a/storage/perfschema/pfs_lock.h b/storage/perfschema/pfs_lock.h
index b74131c79e1..836c64ec992 100644
--- a/storage/perfschema/pfs_lock.h
+++ b/storage/perfschema/pfs_lock.h
@@ -28,8 +28,15 @@
Performance schema internal locks (declarations).
*/
+#include "my_global.h"
+
#include "pfs_atomic.h"
+/* to cause bugs, testing */
+// #define MEM(X) std::memory_order_relaxed
+/* correct code */
+#define MEM(X) X
+
/**
@addtogroup Performance_schema_buffers
@{
@@ -61,6 +68,16 @@
#define STATE_MASK 0x00000003
#define VERSION_INC 4
+struct pfs_optimistic_state
+{
+ uint32 m_version_state;
+};
+
+struct pfs_dirty_state
+{
+ uint32 m_version_state;
+};
+
/**
A 'lock' protecting performance schema internal buffers.
This lock is used to mark the state of a record.
@@ -86,19 +103,34 @@ struct pfs_lock
The version number is stored in the high 30 bits.
The state is stored in the low 2 bits.
*/
- volatile uint32 m_version_state;
+ uint32 m_version_state;
+
+ uint32 copy_version_state()
+ {
+ uint32 copy;
+
+ copy= m_version_state; /* dirty read */
+
+ return copy;
+ }
/** Returns true if the record is free. */
bool is_free(void)
{
- uint32 copy= m_version_state; /* non volatile copy, and dirty read */
+ uint32 copy;
+
+ copy= PFS_atomic::load_u32(&m_version_state);
+
return ((copy & STATE_MASK) == PFS_LOCK_FREE);
}
/** Returns true if the record contains values that can be read. */
bool is_populated(void)
{
- uint32 copy= m_version_state; /* non volatile copy, and dirty read */
+ uint32 copy;
+
+ copy= PFS_atomic::load_u32(&m_version_state);
+
return ((copy & STATE_MASK) == PFS_LOCK_ALLOCATED);
}
@@ -108,13 +140,28 @@ struct pfs_lock
Only one writer will succeed to acquire the record.
@return true if the operation succeed
*/
- bool free_to_dirty(void)
+ bool free_to_dirty(pfs_dirty_state *copy_ptr)
{
- 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;
+ uint32 old_val;
+
+ old_val= PFS_atomic::load_u32(&m_version_state);
+
+ if ((old_val & STATE_MASK) != PFS_LOCK_FREE)
+ {
+ return false;
+ }
- return (PFS_atomic::cas_u32(&m_version_state, &old_val, new_val));
+ uint32 new_val= (old_val & VERSION_MASK) + PFS_LOCK_DIRTY;
+ bool pass;
+
+ pass= PFS_atomic::cas_u32(&m_version_state, &old_val, new_val);
+
+ if (pass)
+ {
+ copy_ptr->m_version_state= new_val;
+ }
+
+ return pass;
}
/**
@@ -122,15 +169,18 @@ struct pfs_lock
This transition should be executed by the writer that owns the record,
before the record is modified.
*/
- void allocated_to_dirty(void)
+ void allocated_to_dirty(pfs_dirty_state *copy_ptr)
{
- uint32 copy= PFS_atomic::load_u32(&m_version_state);
+ uint32 copy= copy_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);
+
+ copy_ptr->m_version_state= new_val;
}
/**
@@ -138,13 +188,13 @@ struct pfs_lock
This transition should be executed by the writer that owns the record,
after the record is in a state ready to be read.
*/
- void dirty_to_allocated(void)
+ void dirty_to_allocated(const pfs_dirty_state *copy)
{
- uint32 copy= PFS_atomic::load_u32(&m_version_state);
/* Make sure the record was DIRTY. */
- DBUG_ASSERT((copy & STATE_MASK) == PFS_LOCK_DIRTY);
+ DBUG_ASSERT((copy->m_version_state & STATE_MASK) == PFS_LOCK_DIRTY);
/* Increment the version, set the ALLOCATED state */
- uint32 new_val= (copy & VERSION_MASK) + VERSION_INC + PFS_LOCK_ALLOCATED;
+ uint32 new_val= (copy->m_version_state & VERSION_MASK) + VERSION_INC + PFS_LOCK_ALLOCATED;
+
PFS_atomic::store_u32(&m_version_state, new_val);
}
@@ -156,35 +206,52 @@ struct pfs_lock
void set_allocated(void)
{
/* Do not set the version to 0, read the previous value. */
- uint32 copy= PFS_atomic::load_u32(&m_version_state);
+ uint32 copy= copy_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);
}
/**
Initialize a lock to dirty.
*/
- void set_dirty(void)
+ void set_dirty(pfs_dirty_state *copy_ptr)
{
/* 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 DIRTY state */
uint32 new_val= (copy & VERSION_MASK) + VERSION_INC + PFS_LOCK_DIRTY;
PFS_atomic::store_u32(&m_version_state, new_val);
+
+ copy_ptr->m_version_state= new_val;
+ }
+
+ /**
+ Initialize a lock to dirty.
+ */
+ void set_dirty(pfs_dirty_state *copy_ptr)
+ {
+ /* 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 DIRTY state */
+ uint32 new_val= (copy & VERSION_MASK) + VERSION_INC + PFS_LOCK_DIRTY;
+ PFS_atomic::store_u32(&m_version_state, new_val);
+
+ copy_ptr->m_version_state= new_val;
}
/**
Execute a dirty to free transition.
This transition should be executed by the writer that owns the record.
*/
- void dirty_to_free(void)
+ void dirty_to_free(const pfs_dirty_state *copy)
{
- uint32 copy= PFS_atomic::load_u32(&m_version_state);
/* Make sure the record was DIRTY. */
- DBUG_ASSERT((copy & STATE_MASK) == PFS_LOCK_DIRTY);
+ DBUG_ASSERT((copy->m_version_state & STATE_MASK) == PFS_LOCK_DIRTY);
/* Keep the same version, set the FREE state */
- uint32 new_val= (copy & VERSION_MASK) + PFS_LOCK_FREE;
+ uint32 new_val= (copy->m_version_state & VERSION_MASK) + PFS_LOCK_FREE;
+
PFS_atomic::store_u32(&m_version_state, new_val);
}
@@ -198,22 +265,22 @@ struct pfs_lock
If this record is not in the ALLOCATED state and the caller is trying
to free it, this is a bug: the caller is confused,
and potentially damaging data owned by another thread or object.
- The correct assert to use here to guarantee data integrity is simply:
- DBUG_ASSERT(m_state == PFS_LOCK_ALLOCATED);
*/
- uint32 copy= PFS_atomic::load_u32(&m_version_state);
+ uint32 copy= copy_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);
}
/**
Start an optimistic read operation.
+ @param [out] copy Saved lock state
@sa end_optimist_lock.
*/
- void begin_optimistic_lock(struct pfs_lock *copy)
+ void begin_optimistic_lock(struct pfs_optimistic_state *copy)
{
copy->m_version_state= PFS_atomic::load_u32(&m_version_state);
}
@@ -221,16 +288,21 @@ struct pfs_lock
/**
End an optimistic read operation.
@sa begin_optimist_lock.
+ @param copy Saved lock state
@return true if the data read is safe to use.
*/
- bool end_optimistic_lock(struct pfs_lock *copy)
+ bool end_optimistic_lock(const struct pfs_optimistic_state *copy)
{
+ uint32 version_state;
+
/* Check there was valid data to look at. */
if ((copy->m_version_state & STATE_MASK) != PFS_LOCK_ALLOCATED)
return false;
+ version_state= PFS_atomic::load_u32(&m_version_state);
+
/* Check the version + state has not changed. */
- if (copy->m_version_state != PFS_atomic::load_u32(&m_version_state))
+ if (copy->m_version_state != version_state)
return false;
return true;
@@ -238,7 +310,11 @@ struct pfs_lock
uint32 get_version()
{
- return (PFS_atomic::load_u32(&m_version_state) & VERSION_MASK);
+ uint32 version_state;
+
+ version_state= PFS_atomic::load_u32(&m_version_state);
+
+ return (version_state & VERSION_MASK);
}
};
diff --git a/storage/perfschema/pfs_memory.cc b/storage/perfschema/pfs_memory.cc
new file mode 100644
index 00000000000..c4e92d7d6b0
--- /dev/null
+++ b/storage/perfschema/pfs_memory.cc
@@ -0,0 +1,98 @@
+/* Copyright (c) 2013, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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_memory.cc
+ Memory statistics aggregation (implementation).
+*/
+
+#include "my_global.h"
+#include "my_sys.h"
+#include "pfs_global.h"
+#include "pfs_instr_class.h"
+#include "pfs_instr.h"
+#include "pfs_account.h"
+#include "pfs_host.h"
+#include "pfs_user.h"
+#include "pfs_atomic.h"
+#include "pfs_buffer_container.h"
+#include "m_string.h"
+
+static void fct_reset_memory_by_thread(PFS_thread *pfs)
+{
+ PFS_account *account= sanitize_account(pfs->m_account);
+ PFS_user *user= sanitize_user(pfs->m_user);
+ PFS_host *host= sanitize_host(pfs->m_host);
+ aggregate_thread_memory(true, pfs, account, user, host);
+}
+
+/** Reset table MEMORY_SUMMARY_BY_THREAD_BY_EVENT_NAME data. */
+void reset_memory_by_thread()
+{
+ global_thread_container.apply(fct_reset_memory_by_thread);
+}
+
+static void fct_reset_memory_by_account(PFS_account *pfs)
+{
+ PFS_user *user= sanitize_user(pfs->m_user);
+ PFS_host *host= sanitize_host(pfs->m_host);
+ pfs->aggregate_memory(true, user, host);
+}
+
+/** Reset table MEMORY_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME data. */
+void reset_memory_by_account()
+{
+ global_account_container.apply(fct_reset_memory_by_account);
+}
+
+static void fct_reset_memory_by_user(PFS_user *pfs)
+{
+ pfs->aggregate_memory(true);
+}
+
+/** Reset table MEMORY_SUMMARY_BY_USER_BY_EVENT_NAME data. */
+void reset_memory_by_user()
+{
+ global_user_container.apply(fct_reset_memory_by_user);
+}
+
+static void fct_reset_memory_by_host(PFS_host *pfs)
+{
+ pfs->aggregate_memory(true);
+}
+
+/** Reset table MEMORY_SUMMARY_BY_HOST_BY_EVENT_NAME data. */
+void reset_memory_by_host()
+{
+ global_host_container.apply(fct_reset_memory_by_host);
+}
+
+/** Reset table MEMORY_GLOBAL_BY_EVENT_NAME data. */
+void reset_memory_global()
+{
+ PFS_memory_stat *stat= global_instr_class_memory_array;
+ PFS_memory_stat *stat_last= global_instr_class_memory_array + memory_class_max;
+
+ for ( ; stat < stat_last; stat++)
+ stat->rebase();
+}
+
diff --git a/storage/perfschema/pfs_memory.h b/storage/perfschema/pfs_memory.h
new file mode 100644
index 00000000000..4dc21b892d5
--- /dev/null
+++ b/storage/perfschema/pfs_memory.h
@@ -0,0 +1,38 @@
+/* Copyright (c) 2013, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#ifndef PFS_MEMORY_H
+#define PFS_MEMORY_H
+
+/**
+ @file storage/perfschema/pfs_memory.h
+ Memory statistics aggregation (declarations).
+*/
+
+void reset_memory_by_thread();
+void reset_memory_by_account();
+void reset_memory_by_user();
+void reset_memory_by_host();
+void reset_memory_global();
+
+#endif
+
diff --git a/storage/perfschema/pfs_prepared_stmt.cc b/storage/perfschema/pfs_prepared_stmt.cc
new file mode 100644
index 00000000000..e3440560691
--- /dev/null
+++ b/storage/perfschema/pfs_prepared_stmt.cc
@@ -0,0 +1,149 @@
+/* Copyright (c) 2014, 2017, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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_prepared_stmt.cc
+ Prepared Statement data structures (implementation).
+*/
+
+/*
+ This code needs extra visibility in the lexer structures
+*/
+
+#include "my_global.h"
+#include "my_sys.h"
+#include "pfs_instr.h"
+#include "pfs_prepared_stmt.h"
+#include "pfs_global.h"
+#include "sql_string.h"
+#include "pfs_buffer_container.h"
+#include <string.h>
+
+/**
+ Initialize table PREPARED_STATEMENTS_INSTANCE.
+ @param param performance schema sizing
+*/
+int init_prepared_stmt(const PFS_global_param *param)
+{
+ if (global_prepared_stmt_container.init(param->m_prepared_stmt_sizing))
+ return 1;
+
+ reset_prepared_stmt_instances();
+ return 0;
+}
+
+/** Cleanup table PREPARED_STATEMENTS_INSTANCE. */
+void cleanup_prepared_stmt(void)
+{
+ global_prepared_stmt_container.cleanup();
+}
+
+void PFS_prepared_stmt::reset_data()
+{
+ m_prepare_stat.reset();
+ m_reprepare_stat.reset();
+ m_execute_stat.reset();
+}
+
+static void fct_reset_prepared_stmt_instances(PFS_prepared_stmt *pfs)
+{
+ pfs->reset_data();
+}
+
+void reset_prepared_stmt_instances()
+{
+ global_prepared_stmt_container.apply_all(fct_reset_prepared_stmt_instances);
+}
+
+PFS_prepared_stmt*
+create_prepared_stmt(void *identity,
+ PFS_thread *thread, PFS_program *pfs_program,
+ PFS_events_statements *pfs_stmt, uint stmt_id,
+ const char* stmt_name, uint stmt_name_length,
+ const char* sqltext, uint sqltext_length)
+{
+ PFS_prepared_stmt *pfs= NULL;
+ pfs_dirty_state dirty_state;
+
+ /* Create a new record in prepared stmt stat array. */
+ pfs= global_prepared_stmt_container.allocate(& dirty_state);
+ if (pfs != NULL)
+ {
+ /* Reset the stats. */
+ pfs->reset_data();
+ /* Do the assignments. */
+ pfs->m_identity= identity;
+ /* Set query text if available, else it will be set later. */
+ if (sqltext_length > 0)
+ strncpy(pfs->m_sqltext, sqltext, sqltext_length);
+
+ pfs->m_sqltext_length= sqltext_length;
+
+ if (stmt_name != NULL)
+ {
+ pfs->m_stmt_name_length= stmt_name_length;
+ if (pfs->m_stmt_name_length > PS_NAME_LENGTH)
+ pfs->m_stmt_name_length= PS_NAME_LENGTH;
+ strncpy(pfs->m_stmt_name, stmt_name, pfs->m_stmt_name_length);
+ }
+ else
+ pfs->m_stmt_name_length= 0;
+
+ pfs->m_stmt_id= stmt_id;
+ pfs->m_owner_thread_id= thread->m_thread_internal_id;
+
+ /* If this statement prepare is called from a SP. */
+ if (pfs_program)
+ {
+ pfs->m_owner_object_type= pfs_program->m_type;
+ strncpy(pfs->m_owner_object_schema, pfs_program->m_schema_name, pfs_program->m_schema_name_length);
+ pfs->m_owner_object_schema_length= pfs_program->m_schema_name_length;
+ strncpy(pfs->m_owner_object_name, pfs_program->m_object_name, pfs_program->m_object_name_length);
+ pfs->m_owner_object_name_length= pfs_program->m_object_name_length;
+ }
+ else
+ {
+ pfs->m_owner_object_type= NO_OBJECT_TYPE;
+ pfs->m_owner_object_schema_length= 0;
+ pfs->m_owner_object_name_length= 0;
+ }
+
+ if (pfs_stmt)
+ {
+ if (pfs_program)
+ pfs->m_owner_event_id= pfs_stmt->m_nesting_event_id;
+ else
+ pfs->m_owner_event_id= pfs_stmt->m_event_id;
+ }
+
+ /* Insert this record. */
+ pfs->m_lock.dirty_to_allocated(& dirty_state);
+ }
+
+ return pfs;
+}
+
+void delete_prepared_stmt(PFS_prepared_stmt *pfs)
+{
+ global_prepared_stmt_container.deallocate(pfs);
+ return;
+}
diff --git a/storage/perfschema/pfs_prepared_stmt.h b/storage/perfschema/pfs_prepared_stmt.h
new file mode 100644
index 00000000000..4638266cce7
--- /dev/null
+++ b/storage/perfschema/pfs_prepared_stmt.h
@@ -0,0 +1,96 @@
+/* Copyright (c) 2014, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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 PFS_PS_H
+#define PFS_PS_H
+
+/**
+ @file storage/perfschema/pfs_prepared_statement.h
+ Stored Program data structures (declarations).
+*/
+
+#include "pfs_stat.h"
+#include "include/mysql/psi/psi.h"
+#include "include/mysql/psi/mysql_ps.h"
+#include "pfs_program.h"
+
+#define PS_NAME_LENGTH NAME_LEN
+
+struct PFS_ALIGNED PFS_prepared_stmt : public PFS_instr
+{
+ /** Column OBJECT_INSTANCE_BEGIN */
+ const void *m_identity;
+
+ /** STATEMENT_ID */
+ ulonglong m_stmt_id;
+
+ /** STATEMENT_NAME */
+ char m_stmt_name[PS_NAME_LENGTH];
+ uint m_stmt_name_length;
+
+ /** SQL_TEXT */
+ char m_sqltext[COL_INFO_SIZE];
+ uint m_sqltext_length;
+
+ /** Column OWNER_THREAD_ID */
+ ulonglong m_owner_thread_id;
+
+ /** Column OWNER_EVENT_ID. */
+ ulonglong m_owner_event_id;
+
+ /** Column OBJECT_OWNER_TYPE. */
+ enum_object_type m_owner_object_type;
+
+ /** Column OBJECT_OWNER_SCHEMA. */
+ char m_owner_object_schema[COL_OBJECT_SCHEMA_SIZE];
+ uint m_owner_object_schema_length;
+
+ /** Column OBJECT_OWNER_NAME. */
+ char m_owner_object_name[COL_OBJECT_NAME_SIZE];
+ uint m_owner_object_name_length;
+
+ /** COLUMN TIMER_PREPARE. Prepared stmt prepare stat. */
+ PFS_single_stat m_prepare_stat;
+
+ /** COLUMN COUNT_REPREPARE. Prepared stmt reprepare stat. */
+ PFS_single_stat m_reprepare_stat;
+
+ /** Prepared stmt execution stat. */
+ PFS_statement_stat m_execute_stat;
+
+ /** Reset data for this record. */
+ void reset_data();
+};
+
+int init_prepared_stmt(const PFS_global_param *param);
+void cleanup_prepared_stmt(void);
+
+void reset_prepared_stmt_instances();
+
+PFS_prepared_stmt*
+create_prepared_stmt(void *identity,
+ PFS_thread *thread, PFS_program *pfs_program,
+ PFS_events_statements *pfs_stmt, uint stmt_id,
+ const char* stmt_name, uint stmt_name_length,
+ const char* sqltext, uint sqltext_length);
+void delete_prepared_stmt(PFS_prepared_stmt *pfs_ps);
+#endif
diff --git a/storage/perfschema/pfs_program.cc b/storage/perfschema/pfs_program.cc
new file mode 100644
index 00000000000..e8808b0b63a
--- /dev/null
+++ b/storage/perfschema/pfs_program.cc
@@ -0,0 +1,322 @@
+/* Copyright (c) 2013, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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_program.cc
+ Statement Digest data structures (implementation).
+*/
+
+/*
+ This code needs extra visibility in the lexer structures
+*/
+
+#include "my_global.h"
+#include "my_sys.h"
+#include "pfs_instr.h"
+#include "pfs_program.h"
+#include "pfs_global.h"
+#include "sql_string.h"
+#include "pfs_setup_object.h"
+#include "pfs_buffer_container.h"
+#include "mysqld.h" //system_charset_info
+#include <string.h>
+
+LF_HASH program_hash;
+static bool program_hash_inited= false;
+
+/**
+ Initialize table EVENTS_STATEMENTS_SUMMARY_BY_PROGRAM.
+ @param param performance schema sizing
+*/
+int init_program(const PFS_global_param *param)
+{
+ if (global_program_container.init(param->m_program_sizing))
+ return 1;
+
+ reset_esms_by_program();
+ return 0;
+}
+
+/** Cleanup table EVENTS_STATEMENTS_SUMMARY_BY_PROGRAM. */
+void cleanup_program(void)
+{
+ global_program_container.cleanup();
+}
+
+C_MODE_START
+static uchar *program_hash_get_key(const uchar *entry, size_t *length,
+ my_bool)
+{
+ const PFS_program * const *typed_entry;
+ const PFS_program *program;
+ const void *result;
+ typed_entry= reinterpret_cast<const PFS_program* const *> (entry);
+ DBUG_ASSERT(typed_entry != NULL);
+ program= *typed_entry;
+ DBUG_ASSERT(program != NULL);
+ *length= program->m_key.m_key_length;
+ result= program->m_key.m_hash_key;
+ return const_cast<uchar*> (reinterpret_cast<const uchar*> (result));
+}
+C_MODE_END
+
+/**
+ Initialize the program hash.
+ @return 0 on success
+*/
+int init_program_hash(const PFS_global_param *param)
+{
+ if ((! program_hash_inited) && (param->m_program_sizing != 0))
+ {
+ lf_hash_init(&program_hash, sizeof(PFS_program*), LF_HASH_UNIQUE,
+ 0, 0, program_hash_get_key, &my_charset_bin);
+ program_hash_inited= true;
+ }
+ return 0;
+}
+
+/** Cleanup the program hash. */
+void cleanup_program_hash(void)
+{
+ if (program_hash_inited)
+ {
+ lf_hash_destroy(&program_hash);
+ program_hash_inited= false;
+ }
+}
+
+static void set_program_key(PFS_program_key *key,
+ enum_object_type object_type,
+ const char *object_name, uint object_name_length,
+ const char *schema_name, uint schema_name_length)
+{
+ DBUG_ASSERT(object_name_length <= COL_OBJECT_NAME_SIZE);
+ DBUG_ASSERT(schema_name_length <= COL_OBJECT_SCHEMA_SIZE);
+
+ /*
+ To make sure generated key is case insensitive,
+ convert object_name/schema_name to lowercase.
+ */
+
+ char *ptr= &key->m_hash_key[0];
+
+ ptr[0]= object_type;
+ ptr++;
+
+ if (object_name_length > 0)
+ {
+ char tmp_object_name[COL_OBJECT_NAME_SIZE + 1];
+ memcpy(tmp_object_name, object_name, object_name_length);
+ tmp_object_name[object_name_length]= '\0';
+ my_casedn_str(system_charset_info, tmp_object_name);
+ memcpy(ptr, tmp_object_name, object_name_length);
+ ptr+= object_name_length;
+ }
+ ptr[0]= 0;
+ ptr++;
+
+ if (schema_name_length > 0)
+ {
+ char tmp_schema_name[COL_OBJECT_SCHEMA_SIZE + 1];
+ memcpy(tmp_schema_name, schema_name, schema_name_length);
+ tmp_schema_name[schema_name_length]='\0';
+ my_casedn_str(system_charset_info, tmp_schema_name);
+ memcpy(ptr, tmp_schema_name, schema_name_length);
+ ptr+= schema_name_length;
+ }
+ ptr[0]= 0;
+ ptr++;
+
+ key->m_key_length= ptr - &key->m_hash_key[0];
+}
+
+
+
+void PFS_program::reset_data()
+{
+ m_sp_stat.reset();
+ m_stmt_stat.reset();
+}
+
+static void fct_reset_esms_by_program(PFS_program *pfs)
+{
+ pfs->reset_data();
+}
+
+void reset_esms_by_program()
+{
+ global_program_container.apply_all(fct_reset_esms_by_program);
+}
+
+static LF_PINS* get_program_hash_pins(PFS_thread *thread)
+{
+ if (unlikely(thread->m_program_hash_pins == NULL))
+ {
+ if (! program_hash_inited)
+ return NULL;
+ thread->m_program_hash_pins= lf_hash_get_pins(&program_hash);
+ }
+ return thread->m_program_hash_pins;
+}
+
+PFS_program*
+find_or_create_program(PFS_thread *thread,
+ enum_object_type object_type,
+ const char *object_name,
+ uint object_name_length,
+ const char *schema_name,
+ uint schema_name_length)
+{
+ bool is_enabled, is_timed;
+
+ LF_PINS *pins= get_program_hash_pins(thread);
+ if (unlikely(pins == NULL))
+ {
+ global_program_container.m_lost++;
+ return NULL;
+ }
+
+ /* Prepare program key */
+ PFS_program_key key;
+ set_program_key(&key, object_type,
+ object_name, object_name_length,
+ schema_name, schema_name_length);
+
+ PFS_program **entry;
+ PFS_program *pfs= NULL;
+ uint retry_count= 0;
+ const uint retry_max= 3;
+ pfs_dirty_state dirty_state;
+
+search:
+ entry= reinterpret_cast<PFS_program**>
+ (lf_hash_search(&program_hash, pins,
+ key.m_hash_key, key.m_key_length));
+
+ if (entry && (entry != MY_ERRPTR))
+ {
+ /* If record already exists then return its pointer. */
+ pfs= *entry;
+ lf_hash_search_unpin(pins);
+ return pfs;
+ }
+
+ lf_hash_search_unpin(pins);
+
+ /*
+ First time while inserting this record to program array we need to
+ find out if it is enabled and timed.
+ */
+ lookup_setup_object(thread, object_type,
+ schema_name, schema_name_length,
+ object_name, object_name_length,
+ &is_enabled, &is_timed);
+
+ /* Else create a new record in program stat array. */
+ pfs= global_program_container.allocate(& dirty_state);
+ if (pfs != NULL)
+ {
+ /* Do the assignments. */
+ memcpy(pfs->m_key.m_hash_key, key.m_hash_key, key.m_key_length);
+ pfs->m_key.m_key_length= key.m_key_length;
+ pfs->m_type= object_type;
+
+ pfs->m_object_name= pfs->m_key.m_hash_key + 1;
+ pfs->m_object_name_length= object_name_length;
+ pfs->m_schema_name= pfs->m_object_name + object_name_length + 1;
+ pfs->m_schema_name_length= schema_name_length;
+ pfs->m_enabled= is_enabled;
+ pfs->m_timed= is_timed;
+
+ /* Insert this record. */
+ pfs->m_lock.dirty_to_allocated(& dirty_state);
+ int res= lf_hash_insert(&program_hash, pins, &pfs);
+
+ if (likely(res == 0))
+ {
+ return pfs;
+ }
+
+ global_program_container.deallocate(pfs);
+
+ if (res > 0)
+ {
+ /* Duplicate insert by another thread */
+ if (++retry_count > retry_max)
+ {
+ /* Avoid infinite loops */
+ global_program_container.m_lost++;
+ return NULL;
+ }
+ goto search;
+ }
+ /* OOM in lf_hash_insert */
+ global_program_container.m_lost++;
+ return NULL;
+ }
+
+ return NULL;
+}
+
+void drop_program(PFS_thread *thread,
+ enum_object_type object_type,
+ const char *object_name,
+ uint object_name_length,
+ const char *schema_name,
+ uint schema_name_length)
+{
+ LF_PINS *pins= get_program_hash_pins(thread);
+ if (unlikely(pins == NULL))
+ return;
+
+ /* Prepare program key */
+ PFS_program_key key;
+ set_program_key(&key, object_type,
+ object_name, object_name_length,
+ schema_name, schema_name_length);
+
+ PFS_program **entry;
+ entry= reinterpret_cast<PFS_program**>
+ (lf_hash_search(&program_hash, pins,
+ key.m_hash_key, key.m_key_length));
+
+ if (entry && (entry != MY_ERRPTR))
+ {
+ PFS_program *pfs= NULL;
+ pfs= *entry;
+
+ lf_hash_delete(&program_hash, pins,
+ key.m_hash_key, key.m_key_length);
+ global_program_container.deallocate(pfs);
+ }
+
+ lf_hash_search_unpin(pins);
+ return;
+}
+
+void PFS_program::refresh_setup_object_flags(PFS_thread *thread)
+{
+ lookup_setup_object(thread, m_type,
+ m_schema_name, m_schema_name_length,
+ m_object_name, m_object_name_length,
+ &m_enabled, &m_timed);
+}
diff --git a/storage/perfschema/pfs_program.h b/storage/perfschema/pfs_program.h
new file mode 100644
index 00000000000..0cbd24b8699
--- /dev/null
+++ b/storage/perfschema/pfs_program.h
@@ -0,0 +1,103 @@
+/* Copyright (c) 2013, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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 PFS_PROGRAM_H
+#define PFS_PROGRAM_H
+
+/**
+ @file storage/perfschema/pfs_program.h
+ Stored Program data structures (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_stat.h"
+
+#define PROGRAM_HASH_KEY_LENGTH sizeof(enum_object_type) + COL_OBJECT_NAME_SIZE + 1 + COL_OBJECT_SCHEMA_SIZE + 1
+
+extern LF_HASH program_hash;
+
+/**
+ Hash key for a program.
+*/
+struct PFS_program_key
+{
+ /**
+ Hash search key.
+ This has to be a string for LF_HASH,
+ the format is "<object_type><0x00><object_name><0x00><schema_name><0x00>"
+ */
+ char m_hash_key[PROGRAM_HASH_KEY_LENGTH];
+ uint m_key_length;
+};
+
+struct PFS_ALIGNED PFS_program : public PFS_instr
+{
+ /** Object type. */
+ enum_object_type m_type;
+
+ /** Object name. */
+ const char *m_object_name;
+ int m_object_name_length;
+
+ /** Object Schema name. */
+ const char *m_schema_name;
+ int m_schema_name_length;
+
+ /** Hash key */
+ PFS_program_key m_key;
+
+ /** Sub statement stat. */
+ PFS_statement_stat m_stmt_stat;
+
+ /** Stored program stat. */
+ PFS_sp_stat m_sp_stat;
+
+ /** Referesh setup object flags. */
+ void refresh_setup_object_flags(PFS_thread* thread);
+
+ /** Reset data for this record. */
+ void reset_data();
+};
+
+int init_program(const PFS_global_param *param);
+void cleanup_program(void);
+int init_program_hash(const PFS_global_param *param);
+void cleanup_program_hash(void);
+
+void reset_esms_by_program();
+
+PFS_program*
+find_or_create_program(PFS_thread *thread,
+ enum_object_type object_type,
+ const char *object_name,
+ uint object_name_length,
+ const char *schema,
+ uint schema_length);
+
+void
+drop_program(PFS_thread *thread,
+ enum_object_type object_type,
+ const char *object_name,
+ uint object_name_length,
+ const char *schema_name,
+ uint schema_name_length);
+#endif
diff --git a/storage/perfschema/pfs_server.cc b/storage/perfschema/pfs_server.cc
index f3f22bbcf4f..63deba92de8 100644
--- a/storage/perfschema/pfs_server.cc
+++ b/storage/perfschema/pfs_server.cc
@@ -32,10 +32,12 @@
#include "pfs.h"
#include "pfs_global.h"
#include "pfs_instr_class.h"
+#include "pfs_builtin_memory.h"
#include "pfs_instr.h"
#include "pfs_events_waits.h"
#include "pfs_events_stages.h"
#include "pfs_events_statements.h"
+#include "pfs_events_transactions.h"
#include "pfs_timer.h"
#include "pfs_setup_actor.h"
#include "pfs_setup_object.h"
@@ -44,6 +46,9 @@
#include "pfs_account.h"
#include "pfs_defaults.h"
#include "pfs_digest.h"
+#include "pfs_program.h"
+//#include "template_utils.h"
+#include "pfs_prepared_stmt.h"
PFS_global_param pfs_param;
@@ -56,48 +61,69 @@ C_MODE_END
static void cleanup_performance_schema(void);
void cleanup_instrument_config(void);
-struct PSI_bootstrap*
-initialize_performance_schema(PFS_global_param *param)
+void pre_initialize_performance_schema()
{
pfs_initialized= false;
+ init_all_builtin_memory_class();
+
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 (my_create_thread_local_key(&THR_PFS, destroy_pfs_thread))
+ return;
+ if (my_create_thread_local_key(&THR_PFS_VG, NULL)) // global_variables
+ return;
+ if (my_create_thread_local_key(&THR_PFS_SV, NULL)) // session_variables
+ return;
+ if (my_create_thread_local_key(&THR_PFS_VBT, NULL)) // variables_by_thread
+ return;
+ if (my_create_thread_local_key(&THR_PFS_SG, NULL)) // global_status
+ return;
+ if (my_create_thread_local_key(&THR_PFS_SS, NULL)) // session_status
+ return;
+ if (my_create_thread_local_key(&THR_PFS_SBT, NULL)) // status_by_thread
+ return;
+ if (my_create_thread_local_key(&THR_PFS_SBU, NULL)) // status_by_user
+ return;
+ if (my_create_thread_local_key(&THR_PFS_SBH, NULL)) // status_by_host
+ return;
+ if (my_create_thread_local_key(&THR_PFS_SBA, NULL)) // status_by_account
+ return;
+
+ THR_PFS_initialized= true;
+}
- if (! param->m_enabled)
+struct PSI_bootstrap*
+initialize_performance_schema(PFS_global_param *param)
+{
+ if (!THR_PFS_initialized)
{
- /*
- The performance schema is disabled in the startup command line.
- All the instrumentation is turned off.
- */
- pfs_enabled= 0;
+ /* Pre-initialization failed. */
return NULL;
}
- pfs_enabled= TRUE;
- init_timers();
+ pfs_enabled= param->m_enabled;
+ pfs_automated_sizing(param);
+ init_timers();
init_event_name_sizing(param);
register_global_classes();
- if (pthread_key_create(&THR_PFS, destroy_pfs_thread))
- return NULL;
-
- THR_PFS_initialized= true;
-
if (init_sync_class(param->m_mutex_class_sizing,
param->m_rwlock_class_sizing,
param->m_cond_class_sizing) ||
init_thread_class(param->m_thread_class_sizing) ||
init_table_share(param->m_table_share_sizing) ||
+ init_table_share_lock_stat(param->m_table_lock_stat_sizing) ||
+ init_table_share_index_stat(param->m_index_stat_sizing) ||
init_file_class(param->m_file_class_sizing) ||
init_stage_class(param->m_stage_class_sizing) ||
init_statement_class(param->m_statement_class_sizing) ||
init_socket_class(param->m_socket_class_sizing) ||
+ init_memory_class(param->m_memory_class_sizing) ||
init_instruments(param) ||
init_events_waits_history_long(
param->m_events_waits_history_long_sizing) ||
@@ -105,20 +131,25 @@ initialize_performance_schema(PFS_global_param *param)
param->m_events_stages_history_long_sizing) ||
init_events_statements_history_long(
param->m_events_statements_history_long_sizing) ||
- init_file_hash() ||
- init_table_share_hash() ||
+ init_events_transactions_history_long(
+ param->m_events_transactions_history_long_sizing) ||
+ init_file_hash(param) ||
+ init_table_share_hash(param) ||
init_setup_actor(param) ||
- init_setup_actor_hash() ||
+ init_setup_actor_hash(param) ||
init_setup_object(param) ||
- init_setup_object_hash() ||
+ init_setup_object_hash(param) ||
init_host(param) ||
- init_host_hash() ||
+ init_host_hash(param) ||
init_user(param) ||
- init_user_hash() ||
+ init_user_hash(param) ||
init_account(param) ||
- init_account_hash() ||
+ init_account_hash(param) ||
init_digest(param) ||
- init_digest_hash())
+ init_digest_hash(param) ||
+ init_program(param) ||
+ init_program_hash(param) ||
+ init_prepared_stmt(param))
{
/*
The performance schema initialization failed.
@@ -128,24 +159,53 @@ initialize_performance_schema(PFS_global_param *param)
return NULL;
}
+ if (param->m_enabled)
+ {
+ /** Default values for SETUP_CONSUMERS */
+ flag_events_stages_current= param->m_consumer_events_stages_current_enabled;
+ flag_events_stages_history= param->m_consumer_events_stages_history_enabled;
+ flag_events_stages_history_long= param->m_consumer_events_stages_history_long_enabled;
+ flag_events_statements_current= param->m_consumer_events_statements_current_enabled;
+ flag_events_statements_history= param->m_consumer_events_statements_history_enabled;
+ flag_events_statements_history_long= param->m_consumer_events_statements_history_long_enabled;
+ flag_events_transactions_current= param->m_consumer_events_transactions_current_enabled;
+ flag_events_transactions_history= param->m_consumer_events_transactions_history_enabled;
+ flag_events_transactions_history_long= param->m_consumer_events_transactions_history_long_enabled;
+ flag_events_waits_current= param->m_consumer_events_waits_current_enabled;
+ flag_events_waits_history= param->m_consumer_events_waits_history_enabled;
+ flag_events_waits_history_long= param->m_consumer_events_waits_history_long_enabled;
+ flag_global_instrumentation= param->m_consumer_global_instrumentation_enabled;
+ flag_thread_instrumentation= param->m_consumer_thread_instrumentation_enabled;
+ flag_statements_digest= param->m_consumer_statement_digest_enabled;
+ }
+ else
+ {
+ flag_events_stages_current= false;
+ flag_events_stages_history= false;
+ flag_events_stages_history_long= false;
+ flag_events_statements_current= false;
+ flag_events_statements_history= false;
+ flag_events_statements_history_long= false;
+ flag_events_transactions_current= false;
+ flag_events_transactions_history= false;
+ flag_events_transactions_history_long= false;
+ flag_events_waits_current= false;
+ flag_events_waits_history= false;
+ flag_events_waits_history_long= false;
+ flag_global_instrumentation= false;
+ flag_thread_instrumentation= false;
+ flag_statements_digest= false;
+ }
+
pfs_initialized= true;
- /** Default values for SETUP_CONSUMERS */
- flag_events_stages_current= param->m_consumer_events_stages_current_enabled;
- flag_events_stages_history= param->m_consumer_events_stages_history_enabled;
- flag_events_stages_history_long= param->m_consumer_events_stages_history_long_enabled;
- flag_events_statements_current= param->m_consumer_events_statements_current_enabled;
- flag_events_statements_history= param->m_consumer_events_statements_history_enabled;
- flag_events_statements_history_long= param->m_consumer_events_statements_history_long_enabled;
- flag_events_waits_current= param->m_consumer_events_waits_current_enabled;
- flag_events_waits_history= param->m_consumer_events_waits_history_enabled;
- flag_events_waits_history_long= param->m_consumer_events_waits_history_long_enabled;
- flag_global_instrumentation= param->m_consumer_global_instrumentation_enabled;
- flag_thread_instrumentation= param->m_consumer_thread_instrumentation_enabled;
- flag_statements_digest= param->m_consumer_statement_digest_enabled;
-
- install_default_setup(&PFS_bootstrap);
- return &PFS_bootstrap;
+ if (param->m_enabled)
+ {
+ install_default_setup(&PFS_bootstrap);
+ return &PFS_bootstrap;
+ }
+
+ return NULL;
}
static void destroy_pfs_thread(void *key)
@@ -169,50 +229,131 @@ static void destroy_pfs_thread(void *key)
static void cleanup_performance_schema(void)
{
+ /*
+ my.cnf options
+ */
+
cleanup_instrument_config();
- cleanup_instruments();
+
+ /*
+ All the LF_HASH
+ */
+
+ cleanup_setup_actor_hash();
+ cleanup_setup_object_hash();
+ cleanup_account_hash();
+ cleanup_host_hash();
+ cleanup_user_hash();
+ cleanup_program_hash();
+ cleanup_table_share_hash();
+ cleanup_file_hash();
+ cleanup_digest_hash();
+
+ /*
+ Then the lookup tables
+ */
+
+ cleanup_setup_actor();
+ cleanup_setup_object();
+
+ /*
+ Then the history tables
+ */
+
+ cleanup_events_waits_history_long();
+ cleanup_events_stages_history_long();
+ cleanup_events_statements_history_long();
+ cleanup_events_transactions_history_long();
+
+ /*
+ Then the various aggregations
+ */
+
+ cleanup_digest();
+ cleanup_account();
+ cleanup_host();
+ cleanup_user();
+
+ /*
+ Then the instrument classes.
+ Once a class is cleaned up,
+ find_XXX_class(key)
+ will return PSI_NOT_INSTRUMENTED
+ */
+ cleanup_program();
+ cleanup_prepared_stmt();
cleanup_sync_class();
cleanup_thread_class();
cleanup_table_share();
+ cleanup_table_share_lock_stat();
+ cleanup_table_share_index_stat();
cleanup_file_class();
cleanup_stage_class();
cleanup_statement_class();
cleanup_socket_class();
- cleanup_events_waits_history_long();
- cleanup_events_stages_history_long();
- cleanup_events_statements_history_long();
- cleanup_table_share_hash();
- cleanup_file_hash();
- cleanup_setup_actor();
- cleanup_setup_actor_hash();
- cleanup_setup_object();
- cleanup_setup_object_hash();
- cleanup_host();
- cleanup_host_hash();
- cleanup_user();
- cleanup_user_hash();
- cleanup_account();
- cleanup_account_hash();
- cleanup_digest();
- cleanup_digest_hash();
+ cleanup_memory_class();
+
+ cleanup_instruments();
}
void shutdown_performance_schema(void)
{
pfs_initialized= false;
+
+ /* disable everything, especially for this thread. */
+ flag_events_stages_current= false;
+ flag_events_stages_history= false;
+ flag_events_stages_history_long= false;
+ flag_events_statements_current= false;
+ flag_events_statements_history= false;
+ flag_events_statements_history_long= false;
+ flag_events_transactions_current= false;
+ flag_events_transactions_history= false;
+ flag_events_transactions_history_long= false;
+ flag_events_waits_current= false;
+ flag_events_waits_history= false;
+ flag_events_waits_history_long= false;
+ flag_global_instrumentation= false;
+ flag_thread_instrumentation= false;
+ flag_statements_digest= false;
+
+ global_table_io_class.m_enabled= false;
+ global_table_lock_class.m_enabled= false;
+ global_idle_class.m_enabled= false;
+ global_metadata_class.m_enabled= false;
+ global_transaction_class.m_enabled= false;
+
cleanup_performance_schema();
-#if 0
/*
Be careful to not delete un-initialized keys,
this would affect key 0, which is THR_KEY_mysys,
*/
if (THR_PFS_initialized)
{
- my_pthread_setspecific_ptr(THR_PFS, NULL);
- pthread_key_delete(THR_PFS);
+ my_set_thread_local(THR_PFS, NULL);
+ my_set_thread_local(THR_PFS_VG, NULL); // global_variables
+ my_set_thread_local(THR_PFS_SV, NULL); // session_variables
+ my_set_thread_local(THR_PFS_VBT, NULL); // variables_by_thread
+ my_set_thread_local(THR_PFS_SG, NULL); // global_status
+ my_set_thread_local(THR_PFS_SS, NULL); // session_status
+ my_set_thread_local(THR_PFS_SBT, NULL); // status_by_thread
+ my_set_thread_local(THR_PFS_SBU, NULL); // status_by_user
+ my_set_thread_local(THR_PFS_SBH, NULL); // status_by_host
+ my_set_thread_local(THR_PFS_SBA, NULL); // status_by_account
+
+ my_delete_thread_local_key(THR_PFS);
+ my_delete_thread_local_key(THR_PFS_VG);
+ my_delete_thread_local_key(THR_PFS_SV);
+ my_delete_thread_local_key(THR_PFS_VBT);
+ my_delete_thread_local_key(THR_PFS_SG);
+ my_delete_thread_local_key(THR_PFS_SS);
+ my_delete_thread_local_key(THR_PFS_SBT);
+ my_delete_thread_local_key(THR_PFS_SBU);
+ my_delete_thread_local_key(THR_PFS_SBH);
+ my_delete_thread_local_key(THR_PFS_SBA);
+
THR_PFS_initialized= false;
}
-#endif
}
/**
@@ -221,27 +362,22 @@ void shutdown_performance_schema(void)
*/
void init_pfs_instrument_array()
{
- my_init_dynamic_array(&pfs_instr_config_array, sizeof(PFS_instr_config*),
- 10, 10, MYF(0));
- pfs_instr_config_state= PFS_INSTR_CONFIG_ALLOCATED;
+ pfs_instr_config_array= new Pfs_instr_config_array((PSI_memory_key)PSI_NOT_INSTRUMENTED);
}
/**
- Deallocate the PFS_INSTRUMENT array. Use an atomic compare-and-swap to ensure
- that it is deallocated only once in the chaotic environment of server shutdown.
+ Deallocate the PFS_INSTRUMENT array.
*/
void cleanup_instrument_config()
{
- int desired_state= PFS_INSTR_CONFIG_ALLOCATED;
-
- /* Ignore if another thread has already deallocated the array */
- if (my_atomic_cas32(&pfs_instr_config_state, &desired_state, PFS_INSTR_CONFIG_DEALLOCATED))
+ if (pfs_instr_config_array != NULL)
{
- PFS_instr_config **array=dynamic_element(&pfs_instr_config_array, 0, PFS_instr_config**);
- for (uint i=0; i < pfs_instr_config_array.elements; i++)
- my_free(array[i]);
- delete_dynamic(&pfs_instr_config_array);
+ PFS_instr_config **it= pfs_instr_config_array->front();
+ for ( ; it != pfs_instr_config_array->end(); it++)
+ my_free(*it);
}
+ delete pfs_instr_config_array;
+ pfs_instr_config_array= NULL;
}
/**
@@ -260,16 +396,17 @@ int add_pfs_instr_to_array(const char* name, const char* value)
size_t value_length= strlen(value);
/* Allocate structure plus string buffers plus null terminators */
- PFS_instr_config* e = (PFS_instr_config*)my_malloc(sizeof(PFS_instr_config)
+ PFS_instr_config* e = (PFS_instr_config*)my_malloc(PSI_NOT_INSTRUMENTED,
+ sizeof(PFS_instr_config)
+ name_length + 1 + value_length + 1, MYF(MY_WME));
if (!e) return 1;
-
+
/* Copy the instrument name */
e->m_name= (char*)e + sizeof(PFS_instr_config);
memcpy(e->m_name, name, name_length);
e->m_name_length= (uint)name_length;
e->m_name[name_length]= '\0';
-
+
/* Set flags accordingly */
if (!my_strcasecmp(&my_charset_latin1, value, "counted"))
{
@@ -301,7 +438,7 @@ int add_pfs_instr_to_array(const char* name, const char* value)
}
/* Add to the array of default startup options */
- if (insert_dynamic(&pfs_instr_config_array, &e))
+ if (pfs_instr_config_array->push(e))
{
my_free(e);
return 1;
diff --git a/storage/perfschema/pfs_server.h b/storage/perfschema/pfs_server.h
index 9f904e6545b..68f6f71d619 100644
--- a/storage/perfschema/pfs_server.h
+++ b/storage/perfschema/pfs_server.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2018, 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, version 2.0,
@@ -28,11 +28,14 @@
Private interface for the server (declarations).
*/
+#define PFS_AUTOSCALE_VALUE (-1)
+#define PFS_AUTOSIZE_VALUE (-1)
+
#ifndef PFS_MAX_MUTEX_CLASS
- #define PFS_MAX_MUTEX_CLASS 200
+ #define PFS_MAX_MUTEX_CLASS 210
#endif
#ifndef PFS_MAX_RWLOCK_CLASS
- #define PFS_MAX_RWLOCK_CLASS 40
+ #define PFS_MAX_RWLOCK_CLASS 50
#endif
#ifndef PFS_MAX_COND_CLASS
#define PFS_MAX_COND_CLASS 90
@@ -41,7 +44,7 @@
#define PFS_MAX_THREAD_CLASS 50
#endif
#ifndef PFS_MAX_FILE_CLASS
- #define PFS_MAX_FILE_CLASS 50
+ #define PFS_MAX_FILE_CLASS 80
#endif
#ifndef PFS_MAX_FILE_HANDLE
#define PFS_MAX_FILE_HANDLE 32768
@@ -49,28 +52,29 @@
#ifndef PFS_MAX_SOCKET_CLASS
#define PFS_MAX_SOCKET_CLASS 10
#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_STAGE_CLASS
#define PFS_MAX_STAGE_CLASS 160
#endif
#ifndef PFS_STATEMENTS_STACK_SIZE
#define PFS_STATEMENTS_STACK_SIZE 10
#endif
-#ifndef PFS_CONNECT_ATTRS_SIZE
- #define PFS_SESSION_CONNECT_ATTRS_SIZE 2048
+#ifndef PFS_MAX_MEMORY_CLASS
+ #define PFS_MAX_MEMORY_CLASS 320
#endif
+/** Sizing hints, from the server configuration. */
struct PFS_sizing_hints
{
+ /** Value of @c Sys_table_def_size */
long m_table_definition_cache;
+ /** Value of @c Sys_table_cache_size */
long m_table_open_cache;
+ /** Value of @c Sys_max_connections */
long m_max_connections;
+ /** Value of @c Sys_open_files_limit */
long m_open_files_limit;
+ /** Value of @c Sys_max_prepared_stmt_count */
+ long m_max_prepared_stmt_count;
};
/** Performance schema global sizing parameters. */
@@ -85,6 +89,9 @@ struct PFS_global_param
bool m_consumer_events_statements_current_enabled;
bool m_consumer_events_statements_history_enabled;
bool m_consumer_events_statements_history_long_enabled;
+ bool m_consumer_events_transactions_current_enabled;
+ bool m_consumer_events_transactions_history_enabled;
+ bool m_consumer_events_transactions_history_long_enabled;
bool m_consumer_events_waits_current_enabled;
bool m_consumer_events_waits_history_enabled;
bool m_consumer_events_waits_history_long_enabled;
@@ -121,6 +128,16 @@ struct PFS_global_param
*/
long m_table_share_sizing;
/**
+ Maximum number of lock statistics collected for tables.
+ @sa table_lock_stat_lost.
+ */
+ long m_table_lock_stat_sizing;
+ /**
+ Maximum number of index statistics collected for tables.
+ @sa table_index_lost.
+ */
+ long m_index_stat_sizing;
+ /**
Maximum number of instrumented file classes.
@sa file_class_lost.
*/
@@ -162,7 +179,7 @@ struct PFS_global_param
long m_file_handle_sizing;
/**
Maxium number of instrumented socket instances
- @sa socket_lost
+ @sa socket_lost
*/
long m_socket_sizing;
/**
@@ -175,9 +192,9 @@ struct PFS_global_param
/** Maximum number of rows in table EVENTS_WAITS_HISTORY_LONG. */
long m_events_waits_history_long_sizing;
/** Maximum number of rows in table SETUP_ACTORS. */
- ulong m_setup_actor_sizing;
+ long m_setup_actor_sizing;
/** Maximum number of rows in table SETUP_OBJECTS. */
- ulong m_setup_object_sizing;
+ long m_setup_object_sizing;
/** Maximum number of rows in table HOSTS. */
long m_host_sizing;
/** Maximum number of rows in table USERS. */
@@ -198,16 +215,36 @@ struct PFS_global_param
@sa statement_class_lost.
*/
ulong m_statement_class_sizing;
- /** Maximum number of rows per thread in table EVENTS_STATEMENT_HISTORY. */
+ /** Maximum number of rows per thread in table EVENTS_STATEMENTS_HISTORY. */
long m_events_statements_history_sizing;
/** Maximum number of rows in table EVENTS_STATEMENTS_HISTORY_LONG. */
long m_events_statements_history_long_sizing;
/** Maximum number of digests to be captured */
long m_digest_sizing;
+ /** Maximum number of programs to be captured */
+ long m_program_sizing;
+ /** Maximum number of prepared statements to be captured */
+ long m_prepared_stmt_sizing;
+ /** Maximum number of rows per thread in table EVENTS_TRANSACTIONS_HISTORY. */
+ long m_events_transactions_history_sizing;
+ /** Maximum number of rows in table EVENTS_TRANSACTIONS_HISTORY_LONG. */
+ long m_events_transactions_history_long_sizing;
+
/** Maximum number of session attribute strings per thread */
long m_session_connect_attrs_sizing;
+ /** Maximum size of statement stack */
+ ulong m_statement_stack_sizing;
+
+ /**
+ Maximum number of instrumented memory classes.
+ @sa memory_class_lost.
+ */
+ ulong m_memory_class_sizing;
+
+ long m_metadata_lock_sizing;
long m_max_digest_length;
+ ulong m_max_sql_text_length;
/** Sizing hints, for auto tuning. */
PFS_sizing_hints m_hints;
@@ -220,9 +257,17 @@ struct PFS_global_param
extern PFS_global_param pfs_param;
/**
+ Null initialization.
+ Disable all instrumentation, size all internal buffers to 0.
+ This pre initialization step is needed to ensure that events can be collected
+ and discarded, until such time @c initialize_performance_schema() is called.
+*/
+void pre_initialize_performance_schema();
+
+/**
Initialize the performance schema.
@param param Size parameters to use.
- @return A boostrap handle, or NULL.
+ @return A bootstrap handle, or NULL.
*/
struct PSI_bootstrap*
initialize_performance_schema(PFS_global_param *param);
@@ -233,14 +278,19 @@ void pfs_automated_sizing(PFS_global_param *param);
Initialize the performance schema ACL.
ACL is strictly enforced when the server is running in normal mode,
to enforce that only legal operations are allowed.
- When running in boostrap mode, ACL restrictions are relaxed,
- to allow the boostrap scripts to DROP / CREATE performance schema tables.
+ When running in bootstrap mode, ACL restrictions are relaxed,
+ to allow the bootstrap scripts to DROP / CREATE performance schema tables.
@sa ACL_internal_schema_registry
@param bootstrap True if the server is starting in bootstrap mode.
*/
void initialize_performance_schema_acl(bool bootstrap);
/**
+ Reset the aggregated status counter stats.
+*/
+void reset_pfs_status_stats();
+
+/**
Initialize the dynamic array holding individual instrument settings collected
from the server configuration options.
*/
diff --git a/storage/perfschema/pfs_setup_actor.cc b/storage/perfschema/pfs_setup_actor.cc
index c4cec6c9ff8..96b367b65db 100644
--- a/storage/perfschema/pfs_setup_actor.cc
+++ b/storage/perfschema/pfs_setup_actor.cc
@@ -32,23 +32,15 @@
#include "pfs_stat.h"
#include "pfs_instr.h"
#include "pfs_setup_actor.h"
+#include "pfs_account.h"
#include "pfs_global.h"
+#include "pfs_buffer_container.h"
/**
@addtogroup Performance_schema_buffers
@{
*/
-/** Size of the setup_actor instances array. @sa setup_actor_array */
-ulong setup_actor_max;
-
-/**
- Setup_actor instances array.
- @sa setup_actor_max
-*/
-
-PFS_setup_actor *setup_actor_array= NULL;
-
/** Hash table for setup_actor records. */
LF_HASH setup_actor_hash;
/** True if @c setup_actor_hash is initialized. */
@@ -61,27 +53,13 @@ static bool setup_actor_hash_inited= false;
*/
int init_setup_actor(const PFS_global_param *param)
{
- setup_actor_max= param->m_setup_actor_sizing;
-
- setup_actor_array= NULL;
-
- if (setup_actor_max > 0)
- {
- setup_actor_array= PFS_MALLOC_ARRAY(setup_actor_max, sizeof(PFS_setup_actor),
- PFS_setup_actor, MYF(MY_ZEROFILL));
- if (unlikely(setup_actor_array == NULL))
- return 1;
- }
-
- return 0;
+ return global_setup_actor_container.init(param->m_setup_actor_sizing);
}
/** Cleanup all the setup actor buffers. */
void cleanup_setup_actor(void)
{
- pfs_free(setup_actor_array);
- setup_actor_array= NULL;
- setup_actor_max= 0;
+ global_setup_actor_container.cleanup();
}
C_MODE_START
@@ -105,13 +83,13 @@ C_MODE_END
Initialize the setup actor hash.
@return 0 on success
*/
-int init_setup_actor_hash(void)
+int init_setup_actor_hash(const PFS_global_param *param)
{
- if ((! setup_actor_hash_inited) && (setup_actor_max > 0))
+ if ((! setup_actor_hash_inited) && (param->m_setup_actor_sizing != 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.size= param->m_setup_actor_sizing; */
setup_actor_hash_inited= true;
}
return 0;
@@ -162,11 +140,9 @@ static void set_setup_actor_key(PFS_setup_actor_key *key,
key->m_key_length= (uint)(ptr - &key->m_hash_key[0]);
}
-int insert_setup_actor(const String *user, const String *host, const String *role)
+int insert_setup_actor(const String *user, const String *host, const String *role,
+ bool enabled, bool history)
{
- if (setup_actor_max == 0)
- return HA_ERR_RECORD_FILE_FULL;
-
PFS_thread *thread= PFS_thread::get_current_thread();
if (unlikely(thread == NULL))
return HA_ERR_OUT_OF_MEM;
@@ -175,46 +151,39 @@ 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 PFS_ALIGNED setup_actor_monotonic_index= 0;
- uint index;
- uint attempts= 0;
PFS_setup_actor *pfs;
+ pfs_dirty_state dirty_state;
- while (++attempts <= setup_actor_max)
+ pfs= global_setup_actor_container.allocate(& dirty_state);
+ if (pfs != NULL)
{
- /* See create_mutex() */
- index= PFS_atomic::add_u32(& setup_actor_monotonic_index, 1) % setup_actor_max;
- pfs= setup_actor_array + index;
-
- if (pfs->m_lock.is_free())
+ set_setup_actor_key(&pfs->m_key,
+ user->ptr(), user->length(),
+ host->ptr(), host->length(),
+ role->ptr(), role->length());
+ pfs->m_username= &pfs->m_key.m_hash_key[0];
+ pfs->m_username_length= user->length();
+ pfs->m_hostname= pfs->m_username + pfs->m_username_length + 1;
+ pfs->m_hostname_length= host->length();
+ pfs->m_rolename= pfs->m_hostname + pfs->m_hostname_length + 1;
+ pfs->m_rolename_length= role->length();
+ pfs->m_enabled= enabled;
+ pfs->m_history= history;
+
+ int res;
+ pfs->m_lock.dirty_to_allocated(& dirty_state);
+ res= lf_hash_insert(&setup_actor_hash, pins, &pfs);
+ if (likely(res == 0))
{
- if (pfs->m_lock.free_to_dirty())
- {
- set_setup_actor_key(&pfs->m_key,
- user->ptr(), user->length(),
- host->ptr(), host->length(),
- role->ptr(), role->length());
- pfs->m_username= &pfs->m_key.m_hash_key[0];
- pfs->m_username_length= user->length();
- pfs->m_hostname= pfs->m_username + pfs->m_username_length + 1;
- pfs->m_hostname_length= host->length();
- pfs->m_rolename= pfs->m_hostname + pfs->m_hostname_length + 1;
- pfs->m_rolename_length= role->length();
-
- int res;
- res= lf_hash_insert(&setup_actor_hash, pins, &pfs);
- if (likely(res == 0))
- {
- pfs->m_lock.dirty_to_allocated();
- return 0;
- }
-
- pfs->m_lock.dirty_to_free();
- if (res > 0)
- return HA_ERR_FOUND_DUPP_KEY;
- return HA_ERR_OUT_OF_MEM;
- }
+ update_setup_actors_derived_flags();
+ return 0;
}
+
+ global_setup_actor_container.deallocate(pfs);
+
+ if (res > 0)
+ return HA_ERR_FOUND_DUPP_KEY;
+ return HA_ERR_OUT_OF_MEM;
}
return HA_ERR_RECORD_FILE_FULL;
@@ -244,14 +213,36 @@ int delete_setup_actor(const String *user, const String *host, const String *rol
{
PFS_setup_actor *pfs= *entry;
lf_hash_delete(&setup_actor_hash, pins, key.m_hash_key, key.m_key_length);
- pfs->m_lock.allocated_to_free();
+ global_setup_actor_container.deallocate(pfs);
}
lf_hash_search_unpin(pins);
+ update_setup_actors_derived_flags();
+
return 0;
}
+class Proc_reset_setup_actor
+ : public PFS_buffer_processor<PFS_setup_actor>
+{
+public:
+ Proc_reset_setup_actor(LF_PINS* pins)
+ : m_pins(pins)
+ {}
+
+ virtual void operator()(PFS_setup_actor *pfs)
+ {
+ lf_hash_delete(&setup_actor_hash, m_pins,
+ pfs->m_key.m_hash_key, pfs->m_key.m_key_length);
+
+ global_setup_actor_container.deallocate(pfs);
+ }
+
+private:
+ LF_PINS* m_pins;
+};
+
int reset_setup_actor()
{
PFS_thread *thread= PFS_thread::get_current_thread();
@@ -262,18 +253,11 @@ int reset_setup_actor()
if (unlikely(pins == NULL))
return HA_ERR_OUT_OF_MEM;
- PFS_setup_actor *pfs= setup_actor_array;
- PFS_setup_actor *pfs_last= setup_actor_array + setup_actor_max;
+ Proc_reset_setup_actor proc(pins);
+ // FIXME: delete helper instead
+ global_setup_actor_container.apply(proc);
- for ( ; pfs < pfs_last; pfs++)
- {
- if (pfs->m_lock.is_populated())
- {
- lf_hash_delete(&setup_actor_hash, pins,
- pfs->m_key.m_hash_key, pfs->m_key.m_key_length);
- pfs->m_lock.allocated_to_free();
- }
- }
+ update_setup_actors_derived_flags();
return 0;
}
@@ -291,7 +275,7 @@ long setup_actor_count()
void lookup_setup_actor(PFS_thread *thread,
const char *user, uint user_length,
const char *host, uint host_length,
- bool *enabled)
+ bool *enabled, bool *history)
{
PFS_setup_actor_key key;
PFS_setup_actor **entry;
@@ -301,6 +285,7 @@ void lookup_setup_actor(PFS_thread *thread,
if (unlikely(pins == NULL))
{
*enabled= false;
+ *history= false;
return;
}
@@ -330,15 +315,28 @@ void lookup_setup_actor(PFS_thread *thread,
if (entry && (entry != MY_ERRPTR))
{
+ PFS_setup_actor *pfs= *entry;
lf_hash_search_unpin(pins);
- *enabled= true;
+ *enabled= pfs->m_enabled;
+ *history= pfs->m_history;
return;
}
lf_hash_search_unpin(pins);
}
*enabled= false;
+ *history= false;
return;
}
+int update_setup_actors_derived_flags()
+{
+ PFS_thread *thread= PFS_thread::get_current_thread();
+ if (unlikely(thread == NULL))
+ return HA_ERR_OUT_OF_MEM;
+
+ update_accounts_derived_flags(thread);
+ return 0;
+}
+
/** @} */
diff --git a/storage/perfschema/pfs_setup_actor.h b/storage/perfschema/pfs_setup_actor.h
index 613d5454a9c..3d00c52aa32 100644
--- a/storage/perfschema/pfs_setup_actor.h
+++ b/storage/perfschema/pfs_setup_actor.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2016, 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, version 2.0,
@@ -33,6 +33,7 @@
#include "lf.h"
struct PFS_global_param;
+class PFS_opaque_container_page;
/* WL#988 Roles Not implemented yet */
#define ROLENAME_LENGTH 64
@@ -74,30 +75,35 @@ struct PFS_ALIGNED PFS_setup_actor
const char *m_rolename;
/** Length of @c m_rolename. */
uint m_rolename_length;
+ /** ENABLED flag. */
+ bool m_enabled;
+ /** HISTORY flag. */
+ bool m_history;
+ /** Container page. */
+ PFS_opaque_container_page *m_page;
};
int init_setup_actor(const PFS_global_param *param);
void cleanup_setup_actor(void);
-int init_setup_actor_hash(void);
+int init_setup_actor_hash(const PFS_global_param *param);
void cleanup_setup_actor_hash(void);
-int insert_setup_actor(const String *user, const String *host, const String *role);
-int delete_setup_actor(const String *user, const String *host, const String *role);
+int insert_setup_actor(const String *user, const String *host,
+ const String *role, bool enabled, bool history);
+int delete_setup_actor(const String *user, const String *host,
+ const String *role);
int reset_setup_actor(void);
long setup_actor_count(void);
void lookup_setup_actor(PFS_thread *thread,
const char *user, uint user_length,
const char *host, uint host_length,
- bool *enabled);
+ bool *enabled, bool *history);
-/* For iterators and show status. */
+/** Update derived flags for all setup_actors. */
+int update_setup_actors_derived_flags();
-extern ulong setup_actor_max;
-
-/* Exposing the data directly, for iterators. */
-
-extern PFS_setup_actor *setup_actor_array;
+/* For show status. */
extern LF_HASH setup_actor_hash;
diff --git a/storage/perfschema/pfs_setup_object.cc b/storage/perfschema/pfs_setup_object.cc
index f33030e927f..9325b84997f 100644
--- a/storage/perfschema/pfs_setup_object.cc
+++ b/storage/perfschema/pfs_setup_object.cc
@@ -34,6 +34,7 @@
#include "pfs_instr.h"
#include "pfs_setup_object.h"
#include "pfs_global.h"
+#include "pfs_buffer_container.h"
/**
@addtogroup Performance_schema_buffers
@@ -42,10 +43,6 @@
uint setup_objects_version= 0;
-ulong setup_object_max;
-
-PFS_setup_object *setup_object_array= NULL;
-
LF_HASH setup_object_hash;
static bool setup_object_hash_inited= false;
@@ -56,27 +53,13 @@ static bool setup_object_hash_inited= false;
*/
int init_setup_object(const PFS_global_param *param)
{
- setup_object_max= param->m_setup_object_sizing;
-
- setup_object_array= NULL;
-
- if (setup_object_max > 0)
- {
- setup_object_array= PFS_MALLOC_ARRAY(setup_object_max, sizeof(PFS_setup_object),
- PFS_setup_object, MYF(MY_ZEROFILL));
- if (unlikely(setup_object_array == NULL))
- return 1;
- }
-
- return 0;
+ return global_setup_object_container.init(param->m_setup_object_sizing);
}
/** Cleanup all the setup object buffers. */
void cleanup_setup_object(void)
{
- pfs_free(setup_object_array);
- setup_object_array= NULL;
- setup_object_max= 0;
+ global_setup_object_container.cleanup();
}
C_MODE_START
@@ -100,13 +83,12 @@ C_MODE_END
Initialize the setup objects hash.
@return 0 on success
*/
-int init_setup_object_hash(void)
+int init_setup_object_hash(const PFS_global_param *param)
{
- if ((! setup_object_hash_inited) && (setup_object_max > 0))
+ if ((! setup_object_hash_inited) && (param->m_setup_object_sizing != 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;
@@ -158,9 +140,6 @@ static void set_setup_object_key(PFS_setup_object_key *key,
int insert_setup_object(enum_object_type object_type, const String *schema,
const String *object, bool enabled, bool timed)
{
- if (setup_object_max == 0)
- return HA_ERR_RECORD_FILE_FULL;
-
PFS_thread *thread= PFS_thread::get_current_thread();
if (unlikely(thread == NULL))
return HA_ERR_OUT_OF_MEM;
@@ -169,47 +148,37 @@ int insert_setup_object(enum_object_type object_type, const String *schema,
if (unlikely(pins == NULL))
return HA_ERR_OUT_OF_MEM;
- static uint PFS_ALIGNED setup_object_monotonic_index= 0;
- uint index;
- uint attempts= 0;
PFS_setup_object *pfs;
+ pfs_dirty_state dirty_state;
- while (++attempts <= setup_object_max)
+ pfs= global_setup_object_container.allocate(& dirty_state);
+ if (pfs != NULL)
{
- /* See create_mutex() */
- index= PFS_atomic::add_u32(& setup_object_monotonic_index, 1) % setup_object_max;
- pfs= setup_object_array + index;
-
- if (pfs->m_lock.is_free())
+ set_setup_object_key(&pfs->m_key, object_type,
+ schema->ptr(), schema->length(),
+ object->ptr(), object->length());
+ pfs->m_schema_name= &pfs->m_key.m_hash_key[1];
+ pfs->m_schema_name_length= schema->length();
+ pfs->m_object_name= pfs->m_schema_name + pfs->m_schema_name_length + 1;
+ pfs->m_object_name_length= object->length();
+ pfs->m_enabled= enabled;
+ pfs->m_timed= timed;
+
+ int res;
+ pfs->m_lock.dirty_to_allocated(& dirty_state);
+ res= lf_hash_insert(&setup_object_hash, pins, &pfs);
+ if (likely(res == 0))
{
- if (pfs->m_lock.free_to_dirty())
- {
- set_setup_object_key(&pfs->m_key, object_type,
- schema->ptr(), schema->length(),
- object->ptr(), object->length());
- pfs->m_schema_name= &pfs->m_key.m_hash_key[1];
- pfs->m_schema_name_length= schema->length();
- pfs->m_object_name= pfs->m_schema_name + pfs->m_schema_name_length + 1;
- pfs->m_object_name_length= object->length();
- pfs->m_enabled= enabled;
- pfs->m_timed= timed;
-
- int res;
- res= lf_hash_insert(&setup_object_hash, pins, &pfs);
- if (likely(res == 0))
- {
- pfs->m_lock.dirty_to_allocated();
- setup_objects_version++;
- return 0;
- }
-
- pfs->m_lock.dirty_to_free();
- if (res > 0)
- return HA_ERR_FOUND_DUPP_KEY;
- /* OOM in lf_hash_insert */
- return HA_ERR_OUT_OF_MEM;
- }
+ setup_objects_version++;
+ return 0;
}
+
+ global_setup_object_container.deallocate(pfs);
+
+ if (res > 0)
+ return HA_ERR_FOUND_DUPP_KEY;
+ /* OOM in lf_hash_insert */
+ return HA_ERR_OUT_OF_MEM;
}
return HA_ERR_RECORD_FILE_FULL;
@@ -239,7 +208,7 @@ int delete_setup_object(enum_object_type object_type, const String *schema,
{
PFS_setup_object *pfs= *entry;
lf_hash_delete(&setup_object_hash, pins, key.m_hash_key, key.m_key_length);
- pfs->m_lock.allocated_to_free();
+ global_setup_object_container.deallocate(pfs);
}
lf_hash_search_unpin(pins);
@@ -248,6 +217,26 @@ int delete_setup_object(enum_object_type object_type, const String *schema,
return 0;
}
+class Proc_reset_setup_object
+ : public PFS_buffer_processor<PFS_setup_object>
+{
+public:
+ Proc_reset_setup_object(LF_PINS* pins)
+ : m_pins(pins)
+ {}
+
+ virtual void operator()(PFS_setup_object *pfs)
+ {
+ lf_hash_delete(&setup_object_hash, m_pins,
+ pfs->m_key.m_hash_key, pfs->m_key.m_key_length);
+
+ global_setup_object_container.deallocate(pfs);
+ }
+
+private:
+ LF_PINS* m_pins;
+};
+
int reset_setup_object()
{
PFS_thread *thread= PFS_thread::get_current_thread();
@@ -258,18 +247,9 @@ int reset_setup_object()
if (unlikely(pins == NULL))
return HA_ERR_OUT_OF_MEM;
- PFS_setup_object *pfs= setup_object_array;
- PFS_setup_object *pfs_last= setup_object_array + setup_object_max;
-
- for ( ; pfs < pfs_last; pfs++)
- {
- if (pfs->m_lock.is_populated())
- {
- lf_hash_delete(&setup_object_hash, pins,
- pfs->m_key.m_hash_key, pfs->m_key.m_key_length);
- pfs->m_lock.allocated_to_free();
- }
- }
+ Proc_reset_setup_object proc(pins);
+ // FIXME: delete helper instead
+ global_setup_object_container.apply(proc);
setup_objects_version++;
return 0;
diff --git a/storage/perfschema/pfs_setup_object.h b/storage/perfschema/pfs_setup_object.h
index ee40742941c..d49be341bbe 100644
--- a/storage/perfschema/pfs_setup_object.h
+++ b/storage/perfschema/pfs_setup_object.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2016, 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, version 2.0,
@@ -33,6 +33,7 @@
class String;
struct PFS_global_param;
+class PFS_opaque_container_page;
/**
@addtogroup Performance_schema_buffers
@@ -75,11 +76,13 @@ struct PFS_ALIGNED PFS_setup_object
bool m_enabled;
/** TIMED flag. */
bool m_timed;
+ /** Container page. */
+ PFS_opaque_container_page *m_page;
};
int init_setup_object(const PFS_global_param *param);
void cleanup_setup_object(void);
-int init_setup_object_hash(void);
+int init_setup_object_hash(const PFS_global_param *param);
void cleanup_setup_object_hash(void);
int insert_setup_object(enum_object_type object_type, const String *schema,
@@ -95,13 +98,7 @@ void lookup_setup_object(PFS_thread *thread,
const char *object_name, int object_name_length,
bool *enabled, bool *timed);
-/* For iterators and show status. */
-
-extern ulong setup_object_max;
-
-/* Exposing the data directly, for iterators. */
-
-extern PFS_setup_object *setup_object_array;
+/* For show status. */
extern LF_HASH setup_object_hash;
diff --git a/storage/perfschema/pfs_stat.h b/storage/perfschema/pfs_stat.h
index 8a049e3013b..8667a5f691c 100644
--- a/storage/perfschema/pfs_stat.h
+++ b/storage/perfschema/pfs_stat.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -23,6 +23,7 @@
#ifndef PFS_STAT_H
#define PFS_STAT_H
+#include <algorithm>
#include "sql_const.h"
/* memcpy */
#include "string.h"
@@ -53,7 +54,7 @@ struct PFS_single_stat
{
m_count= 0;
m_sum= 0;
- m_min= ULONGLONG_MAX;
+ m_min= ULLONG_MAX;
m_max= 0;
}
@@ -61,7 +62,7 @@ struct PFS_single_stat
{
m_count= 0;
m_sum= 0;
- m_min= ULONGLONG_MAX;
+ m_min= ULLONG_MAX;
m_max= 0;
}
@@ -72,6 +73,19 @@ struct PFS_single_stat
inline void aggregate(const PFS_single_stat *stat)
{
+ if (stat->m_count != 0)
+ {
+ m_count+= stat->m_count;
+ m_sum+= stat->m_sum;
+ if (unlikely(m_min > stat->m_min))
+ m_min= stat->m_min;
+ if (unlikely(m_max < stat->m_max))
+ m_max= stat->m_max;
+ }
+ }
+
+ inline void aggregate_no_check(const PFS_single_stat *stat)
+ {
m_count+= stat->m_count;
m_sum+= stat->m_sum;
if (unlikely(m_min > stat->m_min))
@@ -99,6 +113,16 @@ struct PFS_single_stat
if (unlikely(m_max < value))
m_max= value;
}
+
+ inline void aggregate_many_value(ulonglong value, ulonglong count)
+ {
+ m_count+= count;
+ m_sum+= value;
+ if (unlikely(m_min > value))
+ m_min= value;
+ if (unlikely(m_max < value))
+ m_max= value;
+ }
};
/** Combined statistic. */
@@ -107,39 +131,49 @@ struct PFS_byte_stat : public PFS_single_stat
/** Byte count statistics */
ulonglong m_bytes;
- /* Aggregate wait stats, event count and byte count */
+ /** Aggregate wait stats, event count and byte count */
inline void aggregate(const PFS_byte_stat *stat)
{
- PFS_single_stat::aggregate(stat);
+ if (stat->m_count != 0)
+ {
+ PFS_single_stat::aggregate_no_check(stat);
+ m_bytes+= stat->m_bytes;
+ }
+ }
+
+ /** Aggregate wait stats, event count and byte count */
+ inline void aggregate_no_check(const PFS_byte_stat *stat)
+ {
+ PFS_single_stat::aggregate_no_check(stat);
m_bytes+= stat->m_bytes;
}
- /* Aggregate individual wait time, event count and byte count */
+ /** Aggregate individual wait time, event count and byte count */
inline void aggregate(ulonglong wait, ulonglong bytes)
{
aggregate_value(wait);
m_bytes+= bytes;
}
- /* Aggregate wait stats and event count */
+ /** Aggregate wait stats and event count */
inline void aggregate_waits(const PFS_byte_stat *stat)
{
PFS_single_stat::aggregate(stat);
}
- /* Aggregate event count and byte count */
+ /** Aggregate event count and byte count */
inline void aggregate_counted()
{
PFS_single_stat::aggregate_counted();
}
- /* Aggregate event count and byte count */
+ /** Aggregate event count and byte count */
inline void aggregate_counted(ulonglong bytes)
{
PFS_single_stat::aggregate_counted();
m_bytes+= bytes;
}
-
+
PFS_byte_stat()
{
reset();
@@ -157,22 +191,28 @@ struct PFS_mutex_stat
{
/** Wait statistics. */
PFS_single_stat m_wait_stat;
+#ifdef PFS_LATER
/**
Lock statistics.
This statistic is not exposed in user visible tables yet.
*/
PFS_single_stat m_lock_stat;
+#endif
inline void aggregate(const PFS_mutex_stat *stat)
{
m_wait_stat.aggregate(&stat->m_wait_stat);
+#ifdef PFS_LATER
m_lock_stat.aggregate(&stat->m_lock_stat);
+#endif
}
inline void reset(void)
{
m_wait_stat.reset();
+#ifdef PFS_LATER
m_lock_stat.reset();
+#endif
}
};
@@ -181,6 +221,7 @@ struct PFS_rwlock_stat
{
/** Wait statistics. */
PFS_single_stat m_wait_stat;
+#ifdef PFS_LATER
/**
RWLock read lock usage statistics.
This statistic is not exposed in user visible tables yet.
@@ -191,19 +232,24 @@ struct PFS_rwlock_stat
This statistic is not exposed in user visible tables yet.
*/
PFS_single_stat m_write_lock_stat;
+#endif
inline void aggregate(const PFS_rwlock_stat *stat)
{
m_wait_stat.aggregate(&stat->m_wait_stat);
+#ifdef PFS_LATER
m_read_lock_stat.aggregate(&stat->m_read_lock_stat);
m_write_lock_stat.aggregate(&stat->m_write_lock_stat);
+#endif
}
inline void reset(void)
{
m_wait_stat.reset();
+#ifdef PFS_LATER
m_read_lock_stat.reset();
m_write_lock_stat.reset();
+#endif
}
};
@@ -212,6 +258,7 @@ struct PFS_cond_stat
{
/** Wait statistics. */
PFS_single_stat m_wait_stat;
+#ifdef PFS_LATER
/**
Number of times a condition was signalled.
This statistic is not exposed in user visible tables yet.
@@ -222,19 +269,24 @@ struct PFS_cond_stat
This statistic is not exposed in user visible tables yet.
*/
ulonglong m_broadcast_count;
+#endif
inline void aggregate(const PFS_cond_stat *stat)
{
m_wait_stat.aggregate(&stat->m_wait_stat);
+#ifdef PFS_LATER
m_signal_count+= stat->m_signal_count;
m_broadcast_count+= stat->m_broadcast_count;
+#endif
}
inline void reset(void)
{
m_wait_stat.reset();
+#ifdef PFS_LATER
m_signal_count= 0;
m_broadcast_count= 0;
+#endif
}
};
@@ -245,7 +297,7 @@ struct PFS_file_io_stat
PFS_byte_stat m_read;
/** WRITE statistics */
PFS_byte_stat m_write;
- /** Miscelleanous statistics */
+ /** Miscellaneous statistics */
PFS_byte_stat m_misc;
inline void reset(void)
@@ -313,11 +365,51 @@ struct PFS_stage_stat
inline void aggregate_value(ulonglong value)
{ m_timer1_stat.aggregate_value(value); }
+ inline void aggregate(const PFS_stage_stat *stat)
+ { m_timer1_stat.aggregate(& stat->m_timer1_stat); }
+};
+
+/** Statistics for stored program usage. */
+struct PFS_sp_stat
+{
+ PFS_single_stat m_timer1_stat;
+
+ inline void reset(void)
+ { m_timer1_stat.reset(); }
+
+ inline void aggregate_counted()
+ { m_timer1_stat.aggregate_counted(); }
+
+ inline void aggregate_value(ulonglong value)
+ { m_timer1_stat.aggregate_value(value); }
+
+ inline void aggregate(const PFS_stage_stat *stat)
+ { m_timer1_stat.aggregate(& stat->m_timer1_stat); }
+};
+
+/** Statistics for prepared statement usage. */
+struct PFS_prepared_stmt_stat
+{
+ PFS_single_stat m_timer1_stat;
+
+ inline void reset(void)
+ { m_timer1_stat.reset(); }
+
+ inline void aggregate_counted()
+ { m_timer1_stat.aggregate_counted(); }
+
+ inline void aggregate_value(ulonglong value)
+ { m_timer1_stat.aggregate_value(value); }
+
inline void aggregate(PFS_stage_stat *stat)
{ m_timer1_stat.aggregate(& stat->m_timer1_stat); }
};
-/** Statistics for statement usage. */
+/**
+ Statistics for statement usage.
+ This structure uses lazy initialization,
+ controlled by member @c m_timer1_stat.m_count.
+*/
struct PFS_statement_stat
{
PFS_single_stat m_timer1_stat;
@@ -343,80 +435,128 @@ struct PFS_statement_stat
PFS_statement_stat()
{
- m_error_count= 0;
- m_warning_count= 0;
- m_rows_affected= 0;
- m_lock_time= 0;
- m_rows_sent= 0;
- m_rows_examined= 0;
- m_created_tmp_disk_tables= 0;
- m_created_tmp_tables= 0;
- m_select_full_join= 0;
- m_select_full_range_join= 0;
- m_select_range= 0;
- m_select_range_check= 0;
- m_select_scan= 0;
- m_sort_merge_passes= 0;
- m_sort_range= 0;
- m_sort_rows= 0;
- m_sort_scan= 0;
- m_no_index_used= 0;
- m_no_good_index_used= 0;
+ reset();
}
- inline void reset(void)
+ inline void reset()
{
- m_timer1_stat.reset();
- m_error_count= 0;
- m_warning_count= 0;
- m_rows_affected= 0;
- m_lock_time= 0;
- m_rows_sent= 0;
- m_rows_examined= 0;
- m_created_tmp_disk_tables= 0;
- m_created_tmp_tables= 0;
- m_select_full_join= 0;
- m_select_full_range_join= 0;
- m_select_range= 0;
- m_select_range_check= 0;
- m_select_scan= 0;
- m_sort_merge_passes= 0;
- m_sort_range= 0;
- m_sort_rows= 0;
- m_sort_scan= 0;
- m_no_index_used= 0;
- m_no_good_index_used= 0;
+ m_timer1_stat.m_count= 0;
}
+ inline void mark_used()
+ {
+ delayed_reset();
+ }
+
+private:
+ inline void delayed_reset(void)
+ {
+ if (m_timer1_stat.m_count == 0)
+ {
+ m_timer1_stat.reset();
+ m_error_count= 0;
+ m_warning_count= 0;
+ m_rows_affected= 0;
+ m_lock_time= 0;
+ m_rows_sent= 0;
+ m_rows_examined= 0;
+ m_created_tmp_disk_tables= 0;
+ m_created_tmp_tables= 0;
+ m_select_full_join= 0;
+ m_select_full_range_join= 0;
+ m_select_range= 0;
+ m_select_range_check= 0;
+ m_select_scan= 0;
+ m_sort_merge_passes= 0;
+ m_sort_range= 0;
+ m_sort_rows= 0;
+ m_sort_scan= 0;
+ m_no_index_used= 0;
+ m_no_good_index_used= 0;
+ }
+ }
+
+public:
inline void aggregate_counted()
- { m_timer1_stat.aggregate_counted(); }
+ {
+ delayed_reset();
+ m_timer1_stat.aggregate_counted();
+ }
inline void aggregate_value(ulonglong value)
- { m_timer1_stat.aggregate_value(value); }
+ {
+ delayed_reset();
+ m_timer1_stat.aggregate_value(value);
+ }
+
+ inline void aggregate(const PFS_statement_stat *stat)
+ {
+ if (stat->m_timer1_stat.m_count != 0)
+ {
+ delayed_reset();
+ m_timer1_stat.aggregate_no_check(& stat->m_timer1_stat);
+
+ m_error_count+= stat->m_error_count;
+ m_warning_count+= stat->m_warning_count;
+ m_rows_affected+= stat->m_rows_affected;
+ m_lock_time+= stat->m_lock_time;
+ m_rows_sent+= stat->m_rows_sent;
+ m_rows_examined+= stat->m_rows_examined;
+ m_created_tmp_disk_tables+= stat->m_created_tmp_disk_tables;
+ m_created_tmp_tables+= stat->m_created_tmp_tables;
+ m_select_full_join+= stat->m_select_full_join;
+ m_select_full_range_join+= stat->m_select_full_range_join;
+ m_select_range+= stat->m_select_range;
+ m_select_range_check+= stat->m_select_range_check;
+ m_select_scan+= stat->m_select_scan;
+ m_sort_merge_passes+= stat->m_sort_merge_passes;
+ m_sort_range+= stat->m_sort_range;
+ m_sort_rows+= stat->m_sort_rows;
+ m_sort_scan+= stat->m_sort_scan;
+ m_no_index_used+= stat->m_no_index_used;
+ m_no_good_index_used+= stat->m_no_good_index_used;
+ }
+ }
+};
+
+/** Statistics for transaction usage. */
+struct PFS_transaction_stat
+{
+ PFS_single_stat m_read_write_stat;
+ PFS_single_stat m_read_only_stat;
+
+ ulonglong m_savepoint_count;
+ ulonglong m_rollback_to_savepoint_count;
+ ulonglong m_release_savepoint_count;
+
+ PFS_transaction_stat()
+ {
+ m_savepoint_count= 0;
+ m_rollback_to_savepoint_count= 0;
+ m_release_savepoint_count= 0;
+ }
+
+ ulonglong count(void)
+ {
+ return (m_read_write_stat.m_count + m_read_only_stat.m_count);
+ }
+
+ inline void reset(void)
+ {
+ m_read_write_stat.reset();
+ m_read_only_stat.reset();
+ m_savepoint_count= 0;
+ m_rollback_to_savepoint_count= 0;
+ m_release_savepoint_count= 0;
+ }
- inline void aggregate(PFS_statement_stat *stat)
- {
- m_timer1_stat.aggregate(& stat->m_timer1_stat);
-
- m_error_count+= stat->m_error_count;
- m_warning_count+= stat->m_warning_count;
- m_rows_affected+= stat->m_rows_affected;
- m_lock_time+= stat->m_lock_time;
- m_rows_sent+= stat->m_rows_sent;
- m_rows_examined+= stat->m_rows_examined;
- m_created_tmp_disk_tables+= stat->m_created_tmp_disk_tables;
- m_created_tmp_tables+= stat->m_created_tmp_tables;
- m_select_full_join+= stat->m_select_full_join;
- m_select_full_range_join+= stat->m_select_full_range_join;
- m_select_range+= stat->m_select_range;
- m_select_range_check+= stat->m_select_range_check;
- m_select_scan+= stat->m_select_scan;
- m_sort_merge_passes+= stat->m_sort_merge_passes;
- m_sort_range+= stat->m_sort_range;
- m_sort_rows+= stat->m_sort_rows;
- m_sort_scan+= stat->m_sort_scan;
- m_no_index_used+= stat->m_no_index_used;
- m_no_good_index_used+= stat->m_no_good_index_used;
+ inline void aggregate(const PFS_transaction_stat *stat)
+ {
+ m_read_write_stat.aggregate(&stat->m_read_write_stat);
+ m_read_only_stat.aggregate(&stat->m_read_only_stat);
+ m_savepoint_count+= stat->m_savepoint_count;
+ m_rollback_to_savepoint_count+= stat->m_rollback_to_savepoint_count;
+ m_release_savepoint_count+= stat->m_release_savepoint_count;
}
};
@@ -480,16 +620,17 @@ enum PFS_TL_LOCK_TYPE
PFS_TL_READ_NO_INSERT= 3,
PFS_TL_WRITE_ALLOW_WRITE= 4,
PFS_TL_WRITE_CONCURRENT_INSERT= 5,
- PFS_TL_WRITE_DELAYED= 6,
- PFS_TL_WRITE_LOW_PRIORITY= 7,
- PFS_TL_WRITE= 8,
+ PFS_TL_WRITE_LOW_PRIORITY= 6,
+ PFS_TL_WRITE= 7,
/* Locks for handler::ha_external_lock() */
- PFS_TL_READ_EXTERNAL= 9,
- PFS_TL_WRITE_EXTERNAL= 10
+ PFS_TL_READ_EXTERNAL= 8,
+ PFS_TL_WRITE_EXTERNAL= 9,
+
+ PFS_TL_NONE= 99
};
-#define COUNT_PFS_TL_LOCK_TYPE 11
+#define COUNT_PFS_TL_LOCK_TYPE 10
/** Statistics for table locks. */
struct PFS_table_lock_stat
@@ -644,7 +785,7 @@ struct PFS_socket_io_stat
PFS_byte_stat m_read;
/** WRITE statistics */
PFS_byte_stat m_write;
- /** Miscelleanous statistics */
+ /** Miscellaneous statistics */
PFS_byte_stat m_misc;
inline void reset(void)
@@ -691,6 +832,478 @@ struct PFS_socket_stat
}
};
+struct PFS_memory_stat_delta
+{
+ size_t m_alloc_count_delta;
+ size_t m_free_count_delta;
+ size_t m_alloc_size_delta;
+ size_t m_free_size_delta;
+
+ void reset()
+ {
+ m_alloc_count_delta= 0;
+ m_free_count_delta= 0;
+ m_alloc_size_delta= 0;
+ m_free_size_delta= 0;
+ }
+};
+
+/**
+ Memory statistics.
+ Conceptually, the following statistics are maintained:
+ - CURRENT_COUNT_USED,
+ - LOW_COUNT_USED,
+ - HIGH_COUNT_USED
+ - CURRENT_SIZE_USED,
+ - LOW_SIZE_USED,
+ - HIGH_SIZE_USED
+ Now, the implementation keeps different counters,
+ which are easier (less overhead) to maintain while
+ collecting statistics.
+ Invariants are as follows:
+ CURRENT_COUNT_USED = @c m_alloc_count - @c m_free_count
+ LOW_COUNT_USED + @c m_free_count_capacity = CURRENT_COUNT_USED
+ CURRENT_COUNT_USED + @c m_alloc_count_capacity = HIGH_COUNT_USED
+ CURRENT_SIZE_USED = @c m_alloc_size - @c m_free_size
+ LOW_SIZE_USED + @c m_free_size_capacity = CURRENT_SIZE_USED
+ CURRENT_SIZE_USED + @c m_alloc_size_capacity = HIGH_SIZE_USED
+
+*/
+struct PFS_memory_stat
+{
+ bool m_used;
+ size_t m_alloc_count;
+ size_t m_free_count;
+ size_t m_alloc_size;
+ size_t m_free_size;
+
+ size_t m_alloc_count_capacity;
+ size_t m_free_count_capacity;
+ size_t m_alloc_size_capacity;
+ size_t m_free_size_capacity;
+
+ inline void reset(void)
+ {
+ m_used= false;
+ m_alloc_count= 0;
+ m_free_count= 0;
+ m_alloc_size= 0;
+ m_free_size= 0;
+
+ m_alloc_count_capacity= 0;
+ m_free_count_capacity= 0;
+ m_alloc_size_capacity= 0;
+ m_free_size_capacity= 0;
+ }
+
+ inline void rebase(void)
+ {
+ if (! m_used)
+ return;
+
+ size_t base;
+
+ base= std::min<size_t>(m_alloc_count, m_free_count);
+ m_alloc_count-= base;
+ m_free_count-= base;
+
+ base= std::min<size_t>(m_alloc_size, m_free_size);
+ m_alloc_size-= base;
+ m_free_size-= base;
+
+ m_alloc_count_capacity= 0;
+ m_free_count_capacity= 0;
+ m_alloc_size_capacity= 0;
+ m_free_size_capacity= 0;
+ }
+
+ inline void partial_aggregate_to(PFS_memory_stat *stat)
+ {
+ if (! m_used)
+ return;
+
+ size_t base;
+
+ stat->m_used= true;
+
+ base= std::min<size_t>(m_alloc_count, m_free_count);
+ if (base != 0)
+ {
+ stat->m_alloc_count+= base;
+ stat->m_free_count+= base;
+ m_alloc_count-= base;
+ m_free_count-= base;
+ }
+
+ base= std::min<size_t>(m_alloc_size, m_free_size);
+ if (base != 0)
+ {
+ stat->m_alloc_size+= base;
+ stat->m_free_size+= base;
+ m_alloc_size-= base;
+ m_free_size-= base;
+ }
+
+ stat->m_alloc_count_capacity+= m_alloc_count_capacity;
+ stat->m_free_count_capacity+= m_free_count_capacity;
+ stat->m_alloc_size_capacity+= m_alloc_size_capacity;
+ stat->m_free_size_capacity+= m_free_size_capacity;
+
+ m_alloc_count_capacity= 0;
+ m_free_count_capacity= 0;
+ m_alloc_size_capacity= 0;
+ m_free_size_capacity= 0;
+ }
+
+ inline void full_aggregate_to(PFS_memory_stat *stat) const
+ {
+ if (! m_used)
+ return;
+
+ stat->m_used= true;
+
+ stat->m_alloc_count+= m_alloc_count;
+ stat->m_free_count+= m_free_count;
+ stat->m_alloc_size+= m_alloc_size;
+ stat->m_free_size+= m_free_size;
+
+ stat->m_alloc_count_capacity+= m_alloc_count_capacity;
+ stat->m_free_count_capacity+= m_free_count_capacity;
+ stat->m_alloc_size_capacity+= m_alloc_size_capacity;
+ stat->m_free_size_capacity+= m_free_size_capacity;
+ }
+
+ inline void partial_aggregate_to(PFS_memory_stat *stat1, PFS_memory_stat *stat2)
+ {
+ if (! m_used)
+ return;
+
+ size_t base;
+
+ stat1->m_used= true;
+ stat2->m_used= true;
+
+ base= std::min<size_t>(m_alloc_count, m_free_count);
+ if (base != 0)
+ {
+ stat1->m_alloc_count+= base;
+ stat2->m_alloc_count+= base;
+ stat1->m_free_count+= base;
+ stat2->m_free_count+= base;
+ m_alloc_count-= base;
+ m_free_count-= base;
+ }
+
+ base= std::min<size_t>(m_alloc_size, m_free_size);
+ if (base != 0)
+ {
+ stat1->m_alloc_size+= base;
+ stat2->m_alloc_size+= base;
+ stat1->m_free_size+= base;
+ stat2->m_free_size+= base;
+ m_alloc_size-= base;
+ m_free_size-= base;
+ }
+
+ stat1->m_alloc_count_capacity+= m_alloc_count_capacity;
+ stat2->m_alloc_count_capacity+= m_alloc_count_capacity;
+ stat1->m_free_count_capacity+= m_free_count_capacity;
+ stat2->m_free_count_capacity+= m_free_count_capacity;
+ stat1->m_alloc_size_capacity+= m_alloc_size_capacity;
+ stat2->m_alloc_size_capacity+= m_alloc_size_capacity;
+ stat1->m_free_size_capacity+= m_free_size_capacity;
+ stat2->m_free_size_capacity+= m_free_size_capacity;
+
+ m_alloc_count_capacity= 0;
+ m_free_count_capacity= 0;
+ m_alloc_size_capacity= 0;
+ m_free_size_capacity= 0;
+ }
+
+ inline void full_aggregate_to(PFS_memory_stat *stat1, PFS_memory_stat *stat2) const
+ {
+ if (! m_used)
+ return;
+
+ stat1->m_used= true;
+ stat2->m_used= true;
+
+ stat1->m_alloc_count+= m_alloc_count;
+ stat2->m_alloc_count+= m_alloc_count;
+ stat1->m_free_count+= m_free_count;
+ stat2->m_free_count+= m_free_count;
+ stat1->m_alloc_size+= m_alloc_size;
+ stat2->m_alloc_size+= m_alloc_size;
+ stat1->m_free_size+= m_free_size;
+ stat2->m_free_size+= m_free_size;
+
+ stat1->m_alloc_count_capacity+= m_alloc_count_capacity;
+ stat2->m_alloc_count_capacity+= m_alloc_count_capacity;
+ stat1->m_free_count_capacity+= m_free_count_capacity;
+ stat2->m_free_count_capacity+= m_free_count_capacity;
+ stat1->m_alloc_size_capacity+= m_alloc_size_capacity;
+ stat2->m_alloc_size_capacity+= m_alloc_size_capacity;
+ stat1->m_free_size_capacity+= m_free_size_capacity;
+ stat2->m_free_size_capacity+= m_free_size_capacity;
+ }
+
+ void count_builtin_alloc(size_t size)
+ {
+ m_used= true;
+
+ m_alloc_count++;
+ m_free_count_capacity++;
+ m_alloc_size+= size;
+ m_free_size_capacity+= size;
+
+ if (m_alloc_count_capacity >= 1)
+ {
+ m_alloc_count_capacity--;
+ }
+
+ if (m_alloc_size_capacity >= size)
+ {
+ m_alloc_size_capacity-= size;
+ }
+
+ return;
+ }
+
+ void count_builtin_free(size_t size)
+ {
+ m_used= true;
+
+ m_free_count++;
+ m_alloc_count_capacity++;
+ m_free_size+= size;
+ m_alloc_size_capacity+= size;
+
+ if (m_free_count_capacity >= 1)
+ {
+ m_free_count_capacity--;
+ }
+
+ if (m_free_size_capacity >= size)
+ {
+ m_free_size_capacity-= size;
+ }
+
+ return;
+ }
+
+ inline PFS_memory_stat_delta *count_alloc(size_t size,
+ PFS_memory_stat_delta *delta)
+ {
+ m_used= true;
+
+ m_alloc_count++;
+ m_free_count_capacity++;
+ m_alloc_size+= size;
+ m_free_size_capacity+= size;
+
+ if ((m_alloc_count_capacity >= 1) &&
+ (m_alloc_size_capacity >= size))
+ {
+ m_alloc_count_capacity--;
+ m_alloc_size_capacity-= size;
+ return NULL;
+ }
+
+ delta->reset();
+
+ if (m_alloc_count_capacity >= 1)
+ {
+ m_alloc_count_capacity--;
+ }
+ else
+ {
+ delta->m_alloc_count_delta= 1;
+ }
+
+ if (m_alloc_size_capacity >= size)
+ {
+ m_alloc_size_capacity-= size;
+ }
+ else
+ {
+ delta->m_alloc_size_delta= size - m_alloc_size_capacity;
+ m_alloc_size_capacity= 0;
+ }
+
+ return delta;
+ }
+
+ inline PFS_memory_stat_delta *count_realloc(size_t old_size, size_t new_size,
+ PFS_memory_stat_delta *delta)
+ {
+ m_used= true;
+
+ size_t size_delta= new_size - old_size;
+ m_alloc_count++;
+ m_alloc_size+= new_size;
+ m_free_count++;
+ m_free_size+= old_size;
+
+ if (new_size == old_size)
+ {
+ return NULL;
+ }
+
+ if (new_size > old_size)
+ {
+ /* Growing */
+ size_delta= new_size - old_size;
+ m_free_size_capacity+= size_delta;
+
+ if (m_alloc_size_capacity >= size_delta)
+ {
+ m_alloc_size_capacity-= size_delta;
+ return NULL;
+ }
+
+ delta->reset();
+ delta->m_alloc_size_delta= size_delta - m_alloc_size_capacity;
+ m_alloc_size_capacity= 0;
+ }
+ else
+ {
+ /* Shrinking */
+ size_delta= old_size - new_size;
+ m_alloc_size_capacity+= size_delta;
+
+ if (m_free_size_capacity >= size_delta)
+ {
+ m_free_size_capacity-= size_delta;
+ return NULL;
+ }
+
+ delta->reset();
+ delta->m_free_size_delta= size_delta - m_free_size_capacity;
+ m_free_size_capacity= 0;
+ }
+
+ return delta;
+ }
+
+ inline PFS_memory_stat_delta *count_free(size_t size, PFS_memory_stat_delta *delta)
+ {
+ m_used= true;
+
+ m_free_count++;
+ m_alloc_count_capacity++;
+ m_free_size+= size;
+ m_alloc_size_capacity+= size;
+
+ if ((m_free_count_capacity >= 1) &&
+ (m_free_size_capacity >= size))
+ {
+ m_free_count_capacity--;
+ m_free_size_capacity-= size;
+ return NULL;
+ }
+
+ delta->reset();
+
+ if (m_free_count_capacity >= 1)
+ {
+ m_free_count_capacity--;
+ }
+ else
+ {
+ delta->m_free_count_delta= 1;
+ }
+
+ if (m_free_size_capacity >= size)
+ {
+ m_free_size_capacity-= size;
+ }
+ else
+ {
+ delta->m_free_size_delta= size - m_free_size_capacity;
+ m_free_size_capacity= 0;
+ }
+
+ return delta;
+ }
+
+ inline PFS_memory_stat_delta *apply_delta(const PFS_memory_stat_delta *delta,
+ PFS_memory_stat_delta *delta_buffer)
+ {
+ size_t val;
+ size_t remaining_alloc_count;
+ size_t remaining_alloc_size;
+ size_t remaining_free_count;
+ size_t remaining_free_size;
+ bool has_remaining= false;
+
+ m_used= true;
+
+ val= delta->m_alloc_count_delta;
+ if (val <= m_alloc_count_capacity)
+ {
+ m_alloc_count_capacity-= val;
+ remaining_alloc_count= 0;
+ }
+ else
+ {
+ remaining_alloc_count= val - m_alloc_count_capacity;
+ m_alloc_count_capacity= 0;
+ has_remaining= true;
+ }
+
+ val= delta->m_alloc_size_delta;
+ if (val <= m_alloc_size_capacity)
+ {
+ m_alloc_size_capacity-= val;
+ remaining_alloc_size= 0;
+ }
+ else
+ {
+ remaining_alloc_size= val - m_alloc_size_capacity;
+ m_alloc_size_capacity= 0;
+ has_remaining= true;
+ }
+
+ val= delta->m_free_count_delta;
+ if (val <= m_free_count_capacity)
+ {
+ m_free_count_capacity-= val;
+ remaining_free_count= 0;
+ }
+ else
+ {
+ remaining_free_count= val - m_free_count_capacity;
+ m_free_count_capacity= 0;
+ has_remaining= true;
+ }
+
+ val= delta->m_free_size_delta;
+ if (val <= m_free_size_capacity)
+ {
+ m_free_size_capacity-= val;
+ remaining_free_size= 0;
+ }
+ else
+ {
+ remaining_free_size= val - m_free_size_capacity;
+ m_free_size_capacity= 0;
+ has_remaining= true;
+ }
+
+ if (! has_remaining)
+ return NULL;
+
+ delta_buffer->m_alloc_count_delta= remaining_alloc_count;
+ delta_buffer->m_alloc_size_delta= remaining_alloc_size;
+ delta_buffer->m_free_count_delta= remaining_free_count;
+ delta_buffer->m_free_size_delta= remaining_free_size;
+ return delta_buffer;
+ }
+};
+
+#define PFS_MEMORY_STAT_INITIALIZER { false, 0, 0, 0, 0, 0, 0, 0, 0}
+
+/** Connections statistics. */
struct PFS_connection_stat
{
PFS_connection_stat()
diff --git a/storage/perfschema/pfs_status.cc b/storage/perfschema/pfs_status.cc
new file mode 100644
index 00000000000..61afcbfccd9
--- /dev/null
+++ b/storage/perfschema/pfs_status.cc
@@ -0,0 +1,166 @@
+/* Copyright (c) 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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_status.cc
+ Status variables statistics (implementation).
+*/
+
+#include "my_global.h"
+#include "my_sys.h"
+#include "pfs_global.h"
+#include "pfs_instr_class.h"
+#include "pfs_instr.h"
+#include "pfs_account.h"
+#include "pfs_host.h"
+#include "pfs_user.h"
+#include "pfs_status.h"
+#include "pfs_atomic.h"
+#include "pfs_buffer_container.h"
+
+#include "sql_show.h" /* reset_status_vars */
+
+PFS_status_stats::PFS_status_stats()
+{
+ reset();
+}
+
+void PFS_status_stats::reset()
+{
+ m_has_stats= false;
+ memset(&m_stats, 0, sizeof(m_stats));
+}
+
+void PFS_status_stats::aggregate(const PFS_status_stats *from)
+{
+ if (from->m_has_stats)
+ {
+ m_has_stats= true;
+ for (int i= 0; i < COUNT_GLOBAL_STATUS_VARS; i++)
+ {
+ m_stats[i] += from->m_stats[i];
+ }
+ }
+}
+
+void PFS_status_stats::aggregate_from(const STATUS_VAR *from)
+{
+ ulonglong *from_var= (ulonglong*) from;
+
+ m_has_stats= true;
+ for (int i= 0;
+ i < COUNT_GLOBAL_STATUS_VARS;
+ i++, from_var++)
+ {
+ m_stats[i] += *from_var;
+ }
+}
+
+void PFS_status_stats::aggregate_to(STATUS_VAR *to)
+{
+ if (m_has_stats)
+ {
+ ulonglong *to_var= (ulonglong*) to;
+
+ for (int i= 0;
+ i < COUNT_GLOBAL_STATUS_VARS;
+ i++, to_var++)
+ {
+ *to_var += m_stats[i];
+ }
+ }
+}
+
+static void fct_reset_status_by_thread(PFS_thread *thread)
+{
+ PFS_account *account;
+ PFS_user *user;
+ PFS_host *host;
+
+ if (thread->m_lock.is_populated())
+ {
+ account= sanitize_account(thread->m_account);
+ user= sanitize_user(thread->m_user);
+ host= sanitize_host(thread->m_host);
+ aggregate_thread_status(thread, account, user, host);
+ }
+}
+
+/** Reset table STATUS_BY_THREAD data. */
+void reset_status_by_thread()
+{
+ global_thread_container.apply_all(fct_reset_status_by_thread);
+}
+
+static void fct_reset_status_by_account(PFS_account *account)
+{
+ PFS_user *user;
+ PFS_host *host;
+
+ if (account->m_lock.is_populated())
+ {
+ user= sanitize_user(account->m_user);
+ host= sanitize_host(account->m_host);
+ account->aggregate_status(user, host);
+ }
+}
+
+/** Reset table STATUS_BY_ACCOUNT data. */
+void reset_status_by_account()
+{
+ global_account_container.apply_all(fct_reset_status_by_account);
+}
+
+static void fct_reset_status_by_user(PFS_user *user)
+{
+ if (user->m_lock.is_populated())
+ user->aggregate_status();
+}
+
+/** Reset table STATUS_BY_USER data. */
+void reset_status_by_user()
+{
+ global_user_container.apply_all(fct_reset_status_by_user);
+}
+
+static void fct_reset_status_by_host(PFS_host *host)
+{
+ if (host->m_lock.is_populated())
+ host->aggregate_status();
+}
+
+/** Reset table STATUS_BY_HOST data. */
+void reset_status_by_host()
+{
+ global_host_container.apply_all(fct_reset_status_by_host);
+}
+
+/** Reset table GLOBAL_STATUS data. */
+void reset_global_status()
+{
+ /*
+ Do not memset global_status_var,
+ NO_FLUSH counters need to be preserved
+ */
+ reset_status_vars();
+}
+
diff --git a/storage/perfschema/pfs_status.h b/storage/perfschema/pfs_status.h
new file mode 100644
index 00000000000..0417976e9f2
--- /dev/null
+++ b/storage/perfschema/pfs_status.h
@@ -0,0 +1,51 @@
+/* Copyright (c) 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#ifndef PFS_STATUS_H
+#define PFS_STATUS_H
+
+/**
+ @file storage/perfschema/pfs_status.h
+ Status variables statistics (declarations).
+*/
+
+struct PFS_status_stats
+{
+ PFS_status_stats();
+
+ void reset();
+ void aggregate(const PFS_status_stats *from);
+ void aggregate_from(const STATUS_VAR *from);
+ void aggregate_to(STATUS_VAR *to);
+
+ bool m_has_stats;
+ ulonglong m_stats[COUNT_GLOBAL_STATUS_VARS];
+};
+
+void reset_status_by_thread();
+void reset_status_by_account();
+void reset_status_by_user();
+void reset_status_by_host();
+void reset_global_status();
+
+#endif
+
diff --git a/storage/perfschema/pfs_timer.cc b/storage/perfschema/pfs_timer.cc
index 8533dffcb27..ceec4ed9359 100644
--- a/storage/perfschema/pfs_timer.cc
+++ b/storage/perfschema/pfs_timer.cc
@@ -33,6 +33,7 @@ enum_timer_name idle_timer= TIMER_NAME_MICROSEC;
enum_timer_name wait_timer= TIMER_NAME_CYCLE;
enum_timer_name stage_timer= TIMER_NAME_NANOSEC;
enum_timer_name statement_timer= TIMER_NAME_NANOSEC;
+enum_timer_name transaction_timer= TIMER_NAME_NANOSEC;
static ulonglong cycle_v0;
static ulonglong nanosec_v0;
@@ -174,30 +175,35 @@ void init_timers(void)
/* Normal case. */
stage_timer= TIMER_NAME_NANOSEC;
statement_timer= TIMER_NAME_NANOSEC;
+ transaction_timer= TIMER_NAME_NANOSEC;
}
else if (microsec_to_pico != 0)
{
/* Windows. */
stage_timer= TIMER_NAME_MICROSEC;
statement_timer= TIMER_NAME_MICROSEC;
+ transaction_timer= TIMER_NAME_MICROSEC;
}
else if (millisec_to_pico != 0)
{
/* Robustness, no known cases. */
stage_timer= TIMER_NAME_MILLISEC;
statement_timer= TIMER_NAME_MILLISEC;
+ transaction_timer= TIMER_NAME_MILLISEC;
}
else if (tick_to_pico != 0)
{
/* Robustness, no known cases. */
stage_timer= TIMER_NAME_TICK;
statement_timer= TIMER_NAME_TICK;
+ transaction_timer= TIMER_NAME_TICK;
}
else
{
/* Robustness, no known cases. */
stage_timer= TIMER_NAME_CYCLE;
statement_timer= TIMER_NAME_CYCLE;
+ transaction_timer= TIMER_NAME_CYCLE;
}
/*
diff --git a/storage/perfschema/pfs_timer.h b/storage/perfschema/pfs_timer.h
index 222a7f00fae..f2bedc878e7 100644
--- a/storage/perfschema/pfs_timer.h
+++ b/storage/perfschema/pfs_timer.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -106,6 +106,11 @@ extern enum_timer_name stage_timer;
*/
extern enum_timer_name statement_timer;
/**
+ Transaction timer.
+ The timer used to measure all transaction events.
+*/
+extern enum_timer_name transaction_timer;
+/**
Timer information data.
Characteristics about each supported timer.
*/
diff --git a/storage/perfschema/pfs_user.cc b/storage/perfschema/pfs_user.cc
index 14b86e1478e..feb99f41147 100644
--- a/storage/perfschema/pfs_user.cc
+++ b/storage/perfschema/pfs_user.cc
@@ -34,21 +34,13 @@
#include "pfs_user.h"
#include "pfs_global.h"
#include "pfs_instr_class.h"
+#include "pfs_buffer_container.h"
/**
@addtogroup Performance_schema_buffers
@{
*/
-ulong user_max;
-ulong user_lost;
-
-PFS_user *user_array= NULL;
-
-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;
-
LF_HASH user_hash;
static bool user_hash_inited= false;
@@ -59,59 +51,8 @@ static bool user_hash_inited= false;
*/
int init_user(const PFS_global_param *param)
{
- uint index;
-
- user_max= param->m_user_sizing;
-
- user_array= NULL;
- user_instr_class_waits_array= NULL;
- user_instr_class_stages_array= NULL;
- user_instr_class_statements_array= NULL;
- uint waits_sizing= user_max * wait_class_max;
- uint stages_sizing= user_max * stage_class_max;
- uint statements_sizing= user_max * statement_class_max;
-
- if (user_max > 0)
- {
- user_array= PFS_MALLOC_ARRAY(user_max, sizeof(PFS_user), PFS_user,
- MYF(MY_ZEROFILL));
- if (unlikely(user_array == NULL))
- return 1;
- }
-
- if (waits_sizing > 0)
- {
- user_instr_class_waits_array=
- PFS_connection_slice::alloc_waits_slice(waits_sizing);
- if (unlikely(user_instr_class_waits_array == NULL))
- return 1;
- }
-
- if (stages_sizing > 0)
- {
- user_instr_class_stages_array=
- PFS_connection_slice::alloc_stages_slice(stages_sizing);
- if (unlikely(user_instr_class_stages_array == NULL))
- return 1;
- }
-
- if (statements_sizing > 0)
- {
- user_instr_class_statements_array=
- PFS_connection_slice::alloc_statements_slice(statements_sizing);
- if (unlikely(user_instr_class_statements_array == NULL))
- return 1;
- }
-
- for (index= 0; index < user_max; index++)
- {
- user_array[index].m_instr_class_waits_stats=
- &user_instr_class_waits_array[index * wait_class_max];
- user_array[index].m_instr_class_stages_stats=
- &user_instr_class_stages_array[index * stage_class_max];
- user_array[index].m_instr_class_statements_stats=
- &user_instr_class_statements_array[index * statement_class_max];
- }
+ if (global_user_container.init(param->m_user_sizing))
+ return 1;
return 0;
}
@@ -119,15 +60,7 @@ int init_user(const PFS_global_param *param)
/** Cleanup all the user buffers. */
void cleanup_user(void)
{
- pfs_free(user_array);
- user_array= NULL;
- pfs_free(user_instr_class_waits_array);
- user_instr_class_waits_array= NULL;
- pfs_free(user_instr_class_stages_array);
- user_instr_class_stages_array= NULL;
- pfs_free(user_instr_class_statements_array);
- user_instr_class_statements_array= NULL;
- user_max= 0;
+ global_user_container.cleanup();
}
C_MODE_START
@@ -151,13 +84,12 @@ C_MODE_END
Initialize the user hash.
@return 0 on success
*/
-int init_user_hash(void)
+int init_user_hash(const PFS_global_param *param)
{
- if ((! user_hash_inited) && (user_max > 0))
+ if ((! user_hash_inited) && (param->m_user_sizing != 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;
@@ -204,16 +136,10 @@ PFS_user *
find_or_create_user(PFS_thread *thread,
const char *username, uint username_length)
{
- if (user_max == 0)
- {
- user_lost++;
- return NULL;
- }
-
LF_PINS *pins= get_user_hash_pins(thread);
if (unlikely(pins == NULL))
{
- user_lost++;
+ global_user_container.m_lost++;
return NULL;
}
@@ -221,8 +147,10 @@ find_or_create_user(PFS_thread *thread,
set_user_key(&key, username, username_length);
PFS_user **entry;
+ PFS_user *pfs;
uint retry_count= 0;
const uint retry_max= 3;
+ pfs_dirty_state dirty_state;
search:
entry= reinterpret_cast<PFS_user**>
@@ -230,7 +158,6 @@ search:
key.m_hash_key, key.m_key_length));
if (entry && (entry != MY_ERRPTR))
{
- PFS_user *pfs;
pfs= *entry;
pfs->inc_refcount();
lf_hash_search_unpin(pins);
@@ -239,68 +166,55 @@ search:
lf_hash_search_unpin(pins);
- PFS_scan scan;
- uint random= randomized_index(username, user_max);
-
- for (scan.init(random, user_max);
- scan.has_pass();
- scan.next_pass())
+ pfs= global_user_container.allocate(& dirty_state);
+ if (pfs != NULL)
{
- PFS_user *pfs= user_array + scan.first();
- PFS_user *pfs_last= user_array + scan.last();
- for ( ; pfs < pfs_last; pfs++)
+ pfs->m_key= key;
+ if (username_length > 0)
+ pfs->m_username= &pfs->m_key.m_hash_key[0];
+ else
+ pfs->m_username= NULL;
+ pfs->m_username_length= username_length;
+
+ pfs->init_refcount();
+ pfs->reset_stats();
+ pfs->m_disconnected_count= 0;
+
+ int res;
+ pfs->m_lock.dirty_to_allocated(& dirty_state);
+ res= lf_hash_insert(&user_hash, pins, &pfs);
+ if (likely(res == 0))
{
- if (pfs->m_lock.is_free())
+ return pfs;
+ }
+
+ global_user_container.deallocate(pfs);
+
+ if (res > 0)
+ {
+ if (++retry_count > retry_max)
{
- if (pfs->m_lock.free_to_dirty())
- {
- pfs->m_key= key;
- if (username_length > 0)
- pfs->m_username= &pfs->m_key.m_hash_key[0];
- else
- pfs->m_username= NULL;
- pfs->m_username_length= username_length;
-
- pfs->init_refcount();
- pfs->reset_stats();
- pfs->m_disconnected_count= 0;
-
- int res;
- res= lf_hash_insert(&user_hash, pins, &pfs);
- if (likely(res == 0))
- {
- pfs->m_lock.dirty_to_allocated();
- return pfs;
- }
-
- pfs->m_lock.dirty_to_free();
-
- if (res > 0)
- {
- if (++retry_count > retry_max)
- {
- user_lost++;
- return NULL;
- }
- goto search;
- }
-
- user_lost++;
- return NULL;
- }
+ global_user_container.m_lost++;
+ return NULL;
}
+ goto search;
}
+
+ global_user_container.m_lost++;
+ return NULL;
}
- user_lost++;
return NULL;
}
-void PFS_user::aggregate()
+void PFS_user::aggregate(bool alive)
{
aggregate_waits();
aggregate_stages();
aggregate_statements();
+ aggregate_transactions();
+ aggregate_memory(alive);
+ aggregate_status();
aggregate_stats();
}
@@ -322,6 +236,24 @@ void PFS_user::aggregate_statements()
reset_statements_stats();
}
+void PFS_user::aggregate_transactions()
+{
+ /* No parent to aggregate to, clean the stats */
+ reset_transactions_stats();
+}
+
+void PFS_user::aggregate_memory(bool alive)
+{
+ /* No parent to aggregate to, clean the stats */
+ rebase_memory_stats();
+}
+
+void PFS_user::aggregate_status()
+{
+ /* No parent to aggregate to, clean the stats */
+ reset_status_stats();
+}
+
void PFS_user::aggregate_stats()
{
/* No parent to aggregate to, clean the stats */
@@ -333,12 +265,20 @@ void PFS_user::release()
dec_refcount();
}
+void PFS_user::carry_memory_stat_delta(PFS_memory_stat_delta *delta, uint index)
+{
+ PFS_memory_stat *event_name_array;
+ PFS_memory_stat *stat;
+ PFS_memory_stat_delta delta_buffer;
+
+ event_name_array= write_instr_class_memory_stats();
+ stat= & event_name_array[index];
+ (void) stat->apply_delta(delta, &delta_buffer);
+}
+
PFS_user *sanitize_user(PFS_user *unsafe)
{
- if ((&user_array[0] <= unsafe) &&
- (unsafe < &user_array[user_max]))
- return unsafe;
- return NULL;
+ return global_user_container.sanitize(unsafe);
}
void purge_user(PFS_thread *thread, PFS_user *user)
@@ -358,13 +298,33 @@ void purge_user(PFS_thread *thread, PFS_user *user)
{
lf_hash_delete(&user_hash, pins,
user->m_key.m_hash_key, user->m_key.m_key_length);
- user->m_lock.allocated_to_free();
+ user->aggregate(false);
+ global_user_container.deallocate(user);
}
}
lf_hash_search_unpin(pins);
}
+class Proc_purge_user
+ : public PFS_buffer_processor<PFS_user>
+{
+public:
+ Proc_purge_user(PFS_thread *thread)
+ : m_thread(thread)
+ {}
+
+ virtual void operator()(PFS_user *pfs)
+ {
+ pfs->aggregate(true);
+ if (pfs->get_refcount() == 0)
+ purge_user(m_thread, pfs);
+ }
+
+private:
+ PFS_thread *m_thread;
+};
+
/** Purge non connected users, reset stats of connected users. */
void purge_all_user(void)
{
@@ -372,18 +332,8 @@ void purge_all_user(void)
if (unlikely(thread == NULL))
return;
- PFS_user *pfs= user_array;
- PFS_user *pfs_last= user_array + user_max;
-
- for ( ; pfs < pfs_last; pfs++)
- {
- if (pfs->m_lock.is_populated())
- {
- pfs->aggregate();
- if (pfs->get_refcount() == 0)
- purge_user(thread, pfs);
- }
- }
+ Proc_purge_user proc(thread);
+ global_user_container.apply(proc);
}
/** @} */
diff --git a/storage/perfschema/pfs_user.h b/storage/perfschema/pfs_user.h
index 3d0457eae59..9553ff8cae7 100644
--- a/storage/perfschema/pfs_user.h
+++ b/storage/perfschema/pfs_user.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -40,6 +40,7 @@ struct PFS_thread;
@{
*/
+/** Hash key for a user. */
struct PFS_user_key
{
/**
@@ -51,6 +52,7 @@ struct PFS_user_key
uint m_key_length;
};
+/** Per user statistics. */
struct PFS_ALIGNED PFS_user : public PFS_connection_slice
{
public:
@@ -74,13 +76,18 @@ public:
PFS_atomic::add_32(& m_refcount, -1);
}
- void aggregate(void);
+ void aggregate(bool alive);
void aggregate_waits(void);
void aggregate_stages(void);
void aggregate_statements(void);
+ void aggregate_transactions(void);
+ void aggregate_memory(bool alive);
+ void aggregate_status(void);
void aggregate_stats(void);
void release(void);
+ void carry_memory_stat_delta(PFS_memory_stat_delta *delta, uint index);
+
/** Internal lock. */
pfs_lock m_lock;
PFS_user_key m_key;
@@ -95,7 +102,7 @@ private:
int init_user(const PFS_global_param *param);
void cleanup_user(void);
-int init_user_hash(void);
+int init_user_hash(const PFS_global_param *param);
void cleanup_user_hash(void);
PFS_user *
@@ -106,14 +113,7 @@ PFS_user *sanitize_user(PFS_user *unsafe);
void purge_all_user(void);
-/* For iterators and show status. */
-
-extern ulong user_max;
-extern ulong user_lost;
-
-/* Exposing the data directly, for iterators. */
-
-extern PFS_user *user_array;
+/* For show status. */
extern LF_HASH user_hash;
diff --git a/storage/perfschema/pfs_variable.cc b/storage/perfschema/pfs_variable.cc
new file mode 100644
index 00000000000..933d6ad6ce6
--- /dev/null
+++ b/storage/perfschema/pfs_variable.cc
@@ -0,0 +1,1348 @@
+/* Copyright (c) 2015, 2018, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
+
+/**
+ @file storage/perfschema/pfs_variable.cc
+ Performance schema system variable and status variable (implementation).
+*/
+#include "sql_plugin.h"
+#include "pfs_variable.h"
+#include "my_sys.h"
+#include "debug_sync.h"
+#include "pfs.h"
+#include "pfs_global.h"
+#include "pfs_visitor.h"
+#include "sql_audit.h" // audit_global_variable_get
+
+static inline SHOW_SCOPE show_scope_from_type(enum enum_mysql_show_type type)
+{
+ switch(type) {
+ case SHOW_BOOL:
+ case SHOW_CHAR:
+ case SHOW_CHAR_PTR:
+ case SHOW_DOUBLE:
+ case SHOW_HAVE:
+ case SHOW_HA_ROWS:
+ case SHOW_KEY_CACHE_LONG:
+ case SHOW_LEX_STRING:
+ case SHOW_LONG_NOFLUSH:
+ case SHOW_MY_BOOL:
+ case SHOW_SINT:
+ case SHOW_SLONG:
+ case SHOW_SLONGLONG:
+ case SHOW_SYS:
+ case SHOW_UINT:
+ case SHOW_ULONG:
+ case SHOW_ULONGLONG:
+ return SHOW_SCOPE_GLOBAL;
+
+ case SHOW_DOUBLE_STATUS:
+ case SHOW_LONGLONG_STATUS:
+ case SHOW_LONG_STATUS:
+ return SHOW_SCOPE_ALL;
+
+ case SHOW_ARRAY:
+ case SHOW_FUNC:
+ case SHOW_SIMPLE_FUNC:
+ case SHOW_UNDEF:
+ default:
+ return SHOW_SCOPE_UNDEF;
+ }
+ return SHOW_SCOPE_UNDEF;
+}
+
+
+/**
+ CLASS PFS_system_variable_cache
+*/
+
+/**
+ Build a sorted list of all system variables from the system variable hash.
+ Filter by scope. Must be called inside of LOCK_plugin_delete.
+*/
+bool PFS_system_variable_cache::init_show_var_array(enum_var_type scope, bool strict)
+{
+ DBUG_ASSERT(!m_initialized);
+ m_query_scope= scope;
+
+ mysql_rwlock_rdlock(&LOCK_system_variables_hash);
+ DEBUG_SYNC(m_current_thd, "acquired_LOCK_system_variables_hash");
+
+ /* Record the system variable hash version to detect subsequent changes. */
+ m_version= get_system_variable_hash_version();
+
+ /* Build the SHOW_VAR array from the system variable hash. */
+ SHOW_VAR *vars= enumerate_sys_vars(m_current_thd, true, m_query_scope/*, strict */);
+ m_show_var_array.reserve(get_system_variable_hash_records());
+ for (int i=0; vars[i].name; i++)
+ m_show_var_array.set(i, vars[i]);
+
+ mysql_rwlock_unlock(&LOCK_system_variables_hash);
+
+ /* Increase cache size if necessary. */
+ m_cache.reserve(m_show_var_array.elements());
+
+ m_initialized= true;
+ return true;
+}
+
+/**
+ Build an array of SHOW_VARs from the system variable hash.
+ Filter for SESSION scope.
+*/
+bool PFS_system_variable_cache::do_initialize_session(void)
+{
+ /* Block plugins from unloading. */
+ mysql_mutex_lock(&LOCK_plugin_delete);
+
+ /* Build the array. */
+ bool ret= init_show_var_array(OPT_SESSION, true);
+
+ mysql_mutex_unlock(&LOCK_plugin_delete);
+ return ret;
+}
+
+/**
+ Match system variable scope to desired scope.
+*/
+bool PFS_system_variable_cache::match_scope(int scope)
+{
+ switch (scope)
+ {
+ case sys_var::GLOBAL:
+ return m_query_scope == OPT_GLOBAL;
+ break;
+
+ case sys_var::SESSION:
+ return (m_query_scope == OPT_GLOBAL || m_query_scope == OPT_SESSION);
+ break;
+
+ case sys_var::ONLY_SESSION:
+ return m_query_scope == OPT_SESSION;
+ break;
+
+ default:
+ return false;
+ break;
+ }
+ return false;
+}
+
+/**
+ Build a GLOBAL system variable cache.
+*/
+int PFS_system_variable_cache::do_materialize_global(void)
+{
+ /* Block plugins from unloading. */
+ mysql_mutex_lock(&LOCK_plugin_delete);
+
+ m_materialized= false;
+
+ /*
+ Build array of SHOW_VARs from system variable hash. Do this within
+ LOCK_plugin_delete to ensure that the hash table remains unchanged
+ during materialization.
+ */
+ if (!m_external_init)
+ init_show_var_array(OPT_GLOBAL, true);
+
+ /* Resolve the value for each SHOW_VAR in the array, add to cache. */
+ for (SHOW_VAR *show_var= m_show_var_array.front();
+ show_var->value && (show_var != m_show_var_array.end()); show_var++)
+ {
+ const char* name= show_var->name;
+ sys_var *value= (sys_var *)show_var->value;
+ DBUG_ASSERT(value);
+
+ if ((m_query_scope == OPT_GLOBAL) &&
+ (!my_strcasecmp(system_charset_info, name, "sql_log_bin")))
+ {
+ /*
+ PLEASE READ:
+ http://dev.mysql.com/doc/relnotes/mysql/5.7/en/news-5-7-6.html
+
+ SQL_LOG_BIN is:
+ - declared in sys_vars.cc as both GLOBAL and SESSION in 5.7
+ - impossible to SET with SET GLOBAL (raises an error)
+ - and yet can be read with @@global.sql_log_bin
+
+ When show_compatibility_56 = ON,
+ - SHOW GLOBAL VARIABLES does expose a row for SQL_LOG_BIN
+ - INFORMATION_SCHEMA.GLOBAL_VARIABLES also does expose a row,
+ both are for backward compatibility of existing applications,
+ so that no application logic change is required.
+
+ Now, with show_compatibility_56 = OFF (aka, in this code)
+ - SHOW GLOBAL VARIABLES does -- not -- expose a row for SQL_LOG_BIN
+ - PERFORMANCE_SCHEMA.GLOBAL_VARIABLES also does -- not -- expose a row
+ so that a clean interface is exposed to (upgraded and modified) applications.
+
+ The assert below will fail once SQL_LOG_BIN really is defined
+ as SESSION_ONLY (in 5.8), so that this special case can be removed.
+ */
+ DBUG_ASSERT(value->scope() == sys_var::SESSION);
+ continue;
+ }
+
+ /* Match the system variable scope to the target scope. */
+ if (match_scope(value->scope()))
+ {
+ /* Resolve value, convert to text, add to cache. */
+ System_variable system_var(m_current_thd, show_var, m_query_scope, false);
+ m_cache.push(system_var);
+ }
+ }
+
+ m_materialized= true;
+ mysql_mutex_unlock(&LOCK_plugin_delete);
+ return 0;
+}
+
+/**
+ Build a GLOBAL and SESSION system variable cache.
+*/
+int PFS_system_variable_cache::do_materialize_all(THD *unsafe_thd)
+{
+ int ret= 1;
+
+ m_unsafe_thd= unsafe_thd;
+ m_safe_thd= NULL;
+ m_materialized= false;
+ m_cache.clear();
+
+ /* Block plugins from unloading. */
+ mysql_mutex_lock(&LOCK_plugin_delete);
+
+ /*
+ Build array of SHOW_VARs from system variable hash. Do this within
+ LOCK_plugin_delete to ensure that the hash table remains unchanged
+ while this thread is materialized.
+ */
+ if (!m_external_init)
+ init_show_var_array(OPT_SESSION, false);
+
+ /* Get and lock a validated THD from the thread manager. */
+ if ((m_safe_thd= get_THD(unsafe_thd)) != NULL)
+ {
+ DEBUG_SYNC(m_current_thd, "materialize_session_variable_array_THD_locked");
+ for (SHOW_VAR *show_var= m_show_var_array.front();
+ show_var->value && (show_var != m_show_var_array.end()); show_var++)
+ {
+ const char* name= show_var->name;
+ sys_var *value= (sys_var *)show_var->value;
+ DBUG_ASSERT(value);
+ bool ignore= false;
+
+ if (value->scope() == sys_var::SESSION &&
+ (!my_strcasecmp(system_charset_info, name, "gtid_executed")))
+ {
+ /*
+ GTID_EXECUTED is:
+ - declared in sys_vars.cc as both GLOBAL and SESSION in 5.7
+ - can be read with @@session.gtid_executed
+
+ When show_compatibility_56 = ON,
+ - SHOW SESSION VARIABLES does expose a row for GTID_EXECUTED
+ - INFORMATION_SCHEMA.SESSION_VARIABLES also does expose a row,
+ both are for backward compatibility of existing applications,
+ so that no application logic change is required.
+
+ Now, with show_compatibility_56 = OFF (aka, in this code)
+ - SHOW SESSION VARIABLES does -- not -- expose a row for GTID_EXECUTED
+ - PERFORMANCE_SCHEMA.SESSION_VARIABLES also does -- not -- expose a row
+ so that a clean interface is exposed to (upgraded and modified)
+ applications.
+
+ This special case needs be removed once @@SESSION.GTID_EXECUTED is
+ deprecated.
+ */
+ ignore= true;
+ }
+ /* Resolve value, convert to text, add to cache. */
+ System_variable system_var(m_safe_thd, show_var, m_query_scope, ignore);
+ m_cache.push(system_var);
+ }
+
+ /* Release lock taken in get_THD(). */
+ mysql_mutex_unlock(&m_safe_thd->LOCK_thd_data);
+
+ m_materialized= true;
+ ret= 0;
+ }
+
+ mysql_mutex_unlock(&LOCK_plugin_delete);
+ return ret;
+}
+
+/**
+ Allocate and assign mem_root for system variable materialization.
+*/
+void PFS_system_variable_cache::set_mem_root(void)
+{
+ if (m_mem_sysvar_ptr == NULL)
+ {
+ init_sql_alloc(PSI_INSTRUMENT_ME, &m_mem_sysvar, SYSVAR_MEMROOT_BLOCK_SIZE, 0, 0);
+ m_mem_sysvar_ptr= &m_mem_sysvar;
+ }
+ m_mem_thd= my_thread_get_THR_MALLOC(); /* pointer to current THD mem_root */
+ m_mem_thd_save= *m_mem_thd; /* restore later */
+ *m_mem_thd= &m_mem_sysvar; /* use temporary mem_root */
+}
+
+/**
+ Mark memory blocks in the temporary mem_root as free.
+ Restore THD::mem_root.
+*/
+void PFS_system_variable_cache::clear_mem_root(void)
+{
+ if (m_mem_sysvar_ptr)
+ {
+ free_root(&m_mem_sysvar, MYF(MY_MARK_BLOCKS_FREE));
+ *m_mem_thd= m_mem_thd_save; /* restore original mem_root */
+ m_mem_thd= NULL;
+ m_mem_thd_save= NULL;
+ }
+}
+
+/**
+ Free the temporary mem_root.
+ Restore THD::mem_root if necessary.
+*/
+void PFS_system_variable_cache::free_mem_root(void)
+{
+ if (m_mem_sysvar_ptr)
+ {
+ free_root(&m_mem_sysvar, MYF(0));
+ m_mem_sysvar_ptr= NULL;
+ if (m_mem_thd && m_mem_thd_save)
+ {
+ *m_mem_thd= m_mem_thd_save; /* restore original mem_root */
+ m_mem_thd= NULL;
+ m_mem_thd_save= NULL;
+ }
+ }
+}
+
+/**
+ Build a SESSION system variable cache for a pfs_thread.
+ Requires that init_show_var_array() has already been called.
+ Return 0 for success.
+*/
+int PFS_system_variable_cache::do_materialize_session(PFS_thread *pfs_thread)
+{
+ int ret= 1;
+
+ m_pfs_thread= pfs_thread;
+ m_materialized= false;
+ m_cache.clear();
+
+ /* Block plugins from unloading. */
+ mysql_mutex_lock(&LOCK_plugin_delete);
+
+ /* The SHOW_VAR array must be initialized externally. */
+ DBUG_ASSERT(m_initialized);
+
+ /* Use a temporary mem_root to avoid depleting THD mem_root. */
+ if (m_use_mem_root)
+ set_mem_root();
+
+ /* Get and lock a validated THD from the thread manager. */
+ if ((m_safe_thd= get_THD(pfs_thread)) != NULL)
+ {
+ for (SHOW_VAR *show_var= m_show_var_array.front();
+ show_var->value && (show_var != m_show_var_array.end()); show_var++)
+ {
+ sys_var *value= (sys_var *)show_var->value;
+
+ /* Match the system variable scope to the target scope. */
+ if (match_scope(value->scope()))
+ {
+ const char* name= show_var->name;
+ bool ignore= false;
+
+ if (value->scope() == sys_var::SESSION &&
+ (!my_strcasecmp(system_charset_info, name, "gtid_executed")))
+ {
+ /* Deprecated. See PFS_system_variable_cache::do_materialize_all. */
+#warning no @@gtid_executed in MariaDB
+ ignore= true;
+ }
+ /* Resolve value, convert to text, add to cache. */
+ System_variable system_var(m_safe_thd, show_var, m_query_scope, ignore);
+ m_cache.push(system_var);
+ }
+ }
+
+ /* Release lock taken in get_THD(). */
+ mysql_mutex_unlock(&m_safe_thd->LOCK_thd_data);
+
+ m_materialized= true;
+ ret= 0;
+ }
+
+ /* Mark mem_root blocks as free. */
+ if (m_use_mem_root)
+ clear_mem_root();
+
+ mysql_mutex_unlock(&LOCK_plugin_delete);
+ return ret;
+}
+
+/**
+ Materialize a single system variable for a pfs_thread.
+ Requires that init_show_var_array() has already been called.
+ Return 0 for success.
+*/
+int PFS_system_variable_cache::do_materialize_session(PFS_thread *pfs_thread, uint index)
+{
+ int ret= 1;
+
+ m_pfs_thread= pfs_thread;
+ m_materialized= false;
+ m_cache.clear();
+
+ /* Block plugins from unloading. */
+ mysql_mutex_lock(&LOCK_plugin_delete);
+
+ /* The SHOW_VAR array must be initialized externally. */
+ DBUG_ASSERT(m_initialized);
+
+ /* Get and lock a validated THD from the thread manager. */
+ if ((m_safe_thd= get_THD(pfs_thread)) != NULL)
+ {
+ SHOW_VAR *show_var= &m_show_var_array.at(index);
+
+ if (show_var && show_var->value &&
+ (show_var != m_show_var_array.end()))
+ {
+ sys_var *value= (sys_var *)show_var->value;
+
+ /* Match the system variable scope to the target scope. */
+ if (match_scope(value->scope()))
+ {
+ const char* name= show_var->name;
+ bool ignore= false;
+
+ if (value->scope() == sys_var::SESSION &&
+ (!my_strcasecmp(system_charset_info, name, "gtid_executed")))
+ {
+ /* Deprecated. See PFS_system_variable_cache::do_materialize_all. */
+ ignore= true;
+ }
+ /* Resolve value, convert to text, add to cache. */
+ System_variable system_var(m_safe_thd, show_var, m_query_scope, ignore);
+ m_cache.push_back(system_var);
+ }
+ }
+
+ /* Release lock taken in get_THD(). */
+ mysql_mutex_unlock(&m_safe_thd->LOCK_thd_data);
+
+ m_materialized= true;
+ ret= 0;
+ }
+
+ mysql_mutex_unlock(&LOCK_plugin_delete);
+ return ret;
+}
+
+/**
+ Build a SESSION system variable cache for a THD.
+*/
+int PFS_system_variable_cache::do_materialize_session(THD *unsafe_thd)
+{
+ int ret= 1;
+
+ m_unsafe_thd= unsafe_thd;
+ m_safe_thd= NULL;
+ m_materialized= false;
+ m_cache.clear();
+
+ /* Block plugins from unloading. */
+ mysql_mutex_lock(&LOCK_plugin_delete);
+
+ /*
+ Build array of SHOW_VARs from system variable hash. Do this within
+ LOCK_plugin_delete to ensure that the hash table remains unchanged
+ while this thread is materialized.
+ */
+ if (!m_external_init)
+ init_show_var_array(OPT_SESSION, true);
+
+ /* Get and lock a validated THD from the thread manager. */
+ if ((m_safe_thd= get_THD(unsafe_thd)) != NULL)
+ {
+ for (SHOW_VAR *show_var= m_show_var_array.front();
+ show_var->value && (show_var != m_show_var_array.end()); show_var++)
+ {
+ sys_var *value = (sys_var *)show_var->value;
+
+ /* Match the system variable scope to the target scope. */
+ if (match_scope(value->scope()))
+ {
+ const char* name= show_var->name;
+ bool ignore= false;
+
+ if (value->scope() == sys_var::SESSION &&
+ (!my_strcasecmp(system_charset_info, name, "gtid_executed")))
+ {
+ /* Deprecated. See PFS_system_variable_cache::do_materialize_all. */
+ ignore= true;
+ }
+ /* Resolve value, convert to text, add to cache. */
+ System_variable system_var(m_safe_thd, show_var, m_query_scope, ignore);
+ m_cache.push(system_var);
+ }
+ }
+
+ /* Release lock taken in get_THD(). */
+ mysql_mutex_unlock(&m_safe_thd->LOCK_thd_data);
+
+ m_materialized= true;
+ ret= 0;
+ }
+
+ mysql_mutex_unlock(&LOCK_plugin_delete);
+ return ret;
+}
+
+
+/**
+ CLASS System_variable
+*/
+
+/**
+ Empty placeholder.
+*/
+System_variable::System_variable()
+ : m_name(NULL), m_name_length(0), m_value_length(0), m_type(SHOW_UNDEF), m_scope(0),
+ m_ignore(false), m_charset(NULL), m_initialized(false)
+{
+ m_value_str[0]= '\0';
+}
+
+/**
+ GLOBAL or SESSION system variable.
+*/
+System_variable::System_variable(THD *target_thd, const SHOW_VAR *show_var,
+ enum_var_type query_scope, bool ignore)
+ : m_name(NULL), m_name_length(0), m_value_length(0), m_type(SHOW_UNDEF), m_scope(0),
+ m_ignore(ignore), m_charset(NULL), m_initialized(false)
+{
+ init(target_thd, show_var, query_scope);
+}
+
+/**
+ Get sys_var value from global or local source then convert to string.
+*/
+void System_variable::init(THD *target_thd, const SHOW_VAR *show_var,
+ enum_var_type query_scope)
+{
+ if (show_var == NULL || show_var->name == NULL)
+ return;
+
+ enum_mysql_show_type show_var_type= show_var->type;
+ DBUG_ASSERT(show_var_type == SHOW_SYS);
+
+ m_name= show_var->name;
+ m_name_length= strlen(m_name);
+
+ /* Deprecated variables are ignored but must still be accounted for. */
+ if (m_ignore)
+ {
+ m_value_str[0]= '\0';
+ m_value_length= 0;
+ m_initialized= true;
+ return;
+ }
+
+ THD *current_thread= current_thd;
+
+ /* Block remote target thread from updating this system variable. */
+ if (target_thd != current_thread)
+ /*XXX mysql_mutex_lock(&target_thd->LOCK_thd_sysvar)*/;
+ /* Block system variable additions or deletions. */
+ mysql_mutex_lock(&LOCK_global_system_variables);
+
+ sys_var *system_var= (sys_var *)show_var->value;
+ DBUG_ASSERT(system_var != NULL);
+ m_charset= system_var->charset(target_thd);
+ m_type= system_var->show_type();
+ m_scope= system_var->scope();
+
+ /* Get the value of the system variable. */
+ String buf(m_value_str, sizeof(m_value_str) - 1, system_charset_info);
+ system_var->val_str_nolock(&buf, target_thd,
+ system_var->value_ptr(target_thd, query_scope, &null_lex_str));
+
+ m_value_length= MY_MIN(buf.length(), SHOW_VAR_FUNC_BUFF_SIZE);
+
+ /* Returned value may reference a string other than m_value_str. */
+ if (buf.ptr() != m_value_str)
+ memcpy(m_value_str, buf.ptr(), m_value_length);
+ m_value_str[m_value_length]= 0;
+
+ mysql_mutex_unlock(&LOCK_global_system_variables);
+ if (target_thd != current_thread)
+ /*XXX mysql_mutex_unlock(&target_thd->LOCK_thd_sysvar)*/;
+
+ m_initialized= true;
+}
+
+
+/**
+ CLASS PFS_status_variable_cache
+*/
+
+PFS_status_variable_cache::
+PFS_status_variable_cache(bool external_init) :
+ PFS_variable_cache<Status_variable>(external_init),
+ m_show_command(false), m_sum_client_status(NULL)
+{
+ /* Determine if the originating query is a SHOW command. */
+ m_show_command= (m_current_thd->lex->sql_command == SQLCOM_SHOW_STATUS);
+}
+
+/**
+ Build cache of SESSION status variables for a user.
+*/
+int PFS_status_variable_cache::materialize_user(PFS_user *pfs_user)
+{
+ if (!pfs_user)
+ return 1;
+
+ if (is_materialized(pfs_user))
+ return 0;
+
+ if (!pfs_user->m_lock.is_populated())
+ return 1;
+
+ /* Set callback function. */
+ m_sum_client_status= sum_user_status;
+ return do_materialize_client((PFS_client *)pfs_user);
+}
+
+/**
+ Build cache of SESSION status variables for a host.
+*/
+int PFS_status_variable_cache::materialize_host(PFS_host *pfs_host)
+{
+ if (!pfs_host)
+ return 1;
+
+ if (is_materialized(pfs_host))
+ return 0;
+
+ if (!pfs_host->m_lock.is_populated())
+ return 1;
+
+ /* Set callback function. */
+ m_sum_client_status= sum_host_status;
+ return do_materialize_client((PFS_client *)pfs_host);
+}
+
+/**
+ Build cache of SESSION status variables for an account.
+*/
+int PFS_status_variable_cache::materialize_account(PFS_account *pfs_account)
+{
+ if (!pfs_account)
+ return 1;
+
+ if (is_materialized(pfs_account))
+ return 0;
+
+ if (!pfs_account->m_lock.is_populated())
+ return 1;
+
+ /* Set callback function. */
+ m_sum_client_status= sum_account_status;
+ return do_materialize_client((PFS_client *)pfs_account);
+}
+/**
+ Compare status variable scope to desired scope.
+ @param variable_scope Scope of current status variable
+ @return TRUE if variable matches the query scope
+*/
+bool PFS_status_variable_cache::match_scope(SHOW_SCOPE variable_scope, bool strict)
+{
+ switch (variable_scope)
+ {
+ case SHOW_SCOPE_GLOBAL:
+ return (m_query_scope == OPT_GLOBAL) || (! strict && (m_query_scope == OPT_SESSION));
+ break;
+ case SHOW_SCOPE_SESSION:
+ /* Ignore session-only vars if aggregating by user, host or account. */
+ if (m_aggregate)
+ return false;
+ else
+ return (m_query_scope == OPT_SESSION);
+ break;
+ case SHOW_SCOPE_ALL:
+ return (m_query_scope == OPT_GLOBAL || m_query_scope == OPT_SESSION);
+ break;
+ case SHOW_SCOPE_UNDEF:
+ default:
+ return false;
+ break;
+ }
+ return false;
+}
+
+/*
+ Exclude specific status variables from the query by name or prefix.
+ Return TRUE if variable should be filtered.
+*/
+bool PFS_status_variable_cache::filter_by_name(const SHOW_VAR *show_var)
+{
+ DBUG_ASSERT(show_var);
+ DBUG_ASSERT(show_var->name);
+
+ if (show_var->type == SHOW_ARRAY)
+ {
+ /* The SHOW_ARRAY name is the prefix for the variables in the subarray. */
+ const char *prefix= show_var->name;
+ /* Exclude COM counters if not a SHOW STATUS command. */
+ if (!my_strcasecmp(system_charset_info, prefix, "Com") && !m_show_command)
+ return true;
+ }
+ else
+ {
+ /*
+ Slave status resides in Performance Schema replication tables. Exclude
+ these slave status variables from the SHOW STATUS command and from the
+ status tables.
+ Assume null prefix to ensure that only server-defined slave status
+ variables are filtered.
+ */
+ const char *name= show_var->name;
+ if (!my_strcasecmp(system_charset_info, name, "Slave_running") ||
+ !my_strcasecmp(system_charset_info, name, "Slave_retried_transactions") ||
+ !my_strcasecmp(system_charset_info, name, "Slave_last_heartbeat") ||
+ !my_strcasecmp(system_charset_info, name, "Slave_received_heartbeats") ||
+ !my_strcasecmp(system_charset_info, name, "Slave_heartbeat_period"))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/**
+ Check that the variable type is aggregatable.
+
+ @param variable_type Status variable type
+ @return TRUE if variable type can be aggregated
+*/
+bool PFS_status_variable_cache::can_aggregate(enum_mysql_show_type variable_type)
+{
+ switch(variable_type)
+ {
+ /*
+ All server status counters that are totaled across threads are defined in
+ system_status_var as either SHOW_LONGLONG_STATUS or SHOW_LONG_STATUS.
+ These data types are not available to plugins.
+ */
+ case SHOW_LONGLONG_STATUS:
+ case SHOW_LONG_STATUS:
+ return true;
+ break;
+
+ /* Server and plugin */
+ case SHOW_UNDEF:
+ case SHOW_BOOL:
+ case SHOW_CHAR:
+ case SHOW_CHAR_PTR:
+ case SHOW_ARRAY:
+ case SHOW_FUNC:
+ case SHOW_INT:
+ case SHOW_LONG:
+ case SHOW_LONGLONG:
+ case SHOW_DOUBLE:
+ /* Server only */
+ case SHOW_HAVE:
+ case SHOW_MY_BOOL:
+ case SHOW_SYS:
+ case SHOW_LEX_STRING:
+ case SHOW_KEY_CACHE_LONG:
+ case SHOW_DOUBLE_STATUS:
+ case SHOW_HA_ROWS:
+ case SHOW_LONG_NOFLUSH:
+ case SHOW_SLONG:
+ default:
+ return false;
+ break;
+ }
+}
+
+/**
+ Check if a status variable should be excluded from the query.
+ Return TRUE if the variable should be excluded.
+*/
+bool PFS_status_variable_cache::filter_show_var(const SHOW_VAR *show_var, bool strict)
+{
+ /* Match the variable scope with the query scope. */
+ if (!match_scope(show_scope_from_type(show_var->type), strict))
+ return true;
+
+ /* Exclude specific status variables by name or prefix. */
+ if (filter_by_name(show_var))
+ return true;
+
+ /* For user, host or account, ignore variables having non-aggregatable types. */
+ if (m_aggregate && !can_aggregate(show_var->type))
+ return true;
+
+ return false;
+}
+
+
+/**
+ Build an array of SHOW_VARs from the global status array. Expand nested
+ subarrays, filter unwanted variables.
+ NOTE: Must be done inside of LOCK_status to guard against plugin load/unload.
+*/
+bool PFS_status_variable_cache::init_show_var_array(enum_var_type scope, bool strict)
+{
+ DBUG_ASSERT(!m_initialized);
+
+ /* Resize if necessary. */
+ m_show_var_array.reserve(all_status_vars.elements + 1);
+
+ m_query_scope= scope;
+
+ for (SHOW_VAR *show_var_iter= dynamic_element(&all_status_vars, 0, SHOW_VAR *);
+ show_var_iter != dynamic_element(&all_status_vars, all_status_vars.elements, SHOW_VAR *);
+ show_var_iter++)
+ {
+ SHOW_VAR show_var= *show_var_iter;
+
+ /* Check if this status var should be excluded from the query. */
+ if (filter_show_var(&show_var, strict))
+ continue;
+
+ if (show_var.type == SHOW_ARRAY)
+ {
+ /* Expand nested subarray. The name is used as a prefix. */
+ expand_show_var_array((SHOW_VAR *)show_var.value, show_var.name, strict);
+ }
+ else
+ {
+ show_var.name= make_show_var_name(NULL, show_var.name);
+ m_show_var_array.push(show_var);
+ }
+ }
+
+ /* Last element is NULL. */
+ st_mysql_show_var empty= {0,0,SHOW_UNDEF};
+ m_show_var_array.push(empty);
+
+ /* Get the latest version of all_status_vars. */
+ m_version= get_status_vars_version();
+
+ /* Increase cache size if necessary. */
+ m_cache.reserve(m_show_var_array.elements());
+
+ m_initialized= true;
+ return true;
+}
+
+/**
+ Expand a nested subarray of status variables, indicated by a type of SHOW_ARRAY.
+*/
+void PFS_status_variable_cache::expand_show_var_array(const SHOW_VAR *show_var_array, const char *prefix, bool strict)
+{
+ for (const SHOW_VAR *show_var_ptr= show_var_array;
+ show_var_ptr && show_var_ptr->name;
+ show_var_ptr++)
+ {
+ SHOW_VAR show_var= *show_var_ptr;
+
+ if (filter_show_var(&show_var, strict))
+ continue;
+
+ if (show_var.type == SHOW_ARRAY)
+ {
+ char name_buf[SHOW_VAR_MAX_NAME_LEN];
+ show_var.name= make_show_var_name(prefix, show_var.name, name_buf, sizeof(name_buf));
+ /* Expand nested subarray. The name is used as a prefix. */
+ expand_show_var_array((SHOW_VAR *)show_var.value, show_var.name, strict);
+ }
+ else
+ {
+ /* Add the SHOW_VAR element. Make a local copy of the name string. */
+ show_var.name= make_show_var_name(prefix, show_var.name);
+ m_show_var_array.push(show_var);
+ }
+ }
+}
+
+/**
+ Build the complete status variable name, with prefix. Return in buffer provided.
+*/
+char * PFS_status_variable_cache::make_show_var_name(const char* prefix, const char* name,
+ char *name_buf, size_t buf_len)
+{
+ DBUG_ASSERT(name_buf != NULL);
+ char *prefix_end= name_buf;
+
+ if (prefix && *prefix)
+ {
+ /* Drop the prefix into the front of the name buffer. */
+ prefix_end= my_stpnmov(name_buf, prefix, buf_len-1);
+ *prefix_end++= '_';
+ }
+
+ /* Restrict name length to remaining buffer size. */
+ size_t max_name_len= name_buf + buf_len - prefix_end;
+
+ /* Load the name into the buffer after the prefix. */
+ my_stpnmov(prefix_end, name, max_name_len);
+ name_buf[buf_len-1]= 0;
+
+ return (name_buf);
+}
+
+/**
+ Make a copy of the name string prefixed with the subarray name if necessary.
+*/
+char * PFS_status_variable_cache::make_show_var_name(const char* prefix, const char* name)
+{
+ char name_buf[SHOW_VAR_MAX_NAME_LEN];
+ size_t buf_len= sizeof(name_buf);
+ make_show_var_name(prefix, name, name_buf, buf_len);
+ return m_current_thd->strdup(name_buf); /* freed at statement end */
+}
+
+/**
+ Build an internal SHOW_VAR array from the external status variable array.
+*/
+bool PFS_status_variable_cache::do_initialize_session(void)
+{
+ /* Acquire LOCK_status to guard against plugin load/unload. */
+ //if (m_current_thd->fill_status_recursion_level++ == 0)
+ mysql_mutex_lock(&LOCK_status);
+
+ bool ret= init_show_var_array(OPT_SESSION, true);
+
+ //if (m_current_thd->fill_status_recursion_level-- == 1)
+ mysql_mutex_unlock(&LOCK_status);
+
+ return ret;
+}
+
+/**
+ For the current THD, use initial_status_vars taken from before the query start.
+*/
+STATUS_VAR *PFS_status_variable_cache::set_status_vars(void)
+{
+ STATUS_VAR *status_vars;
+ if (m_safe_thd == m_current_thd && m_current_thd->initial_status_var != NULL)
+ status_vars= m_current_thd->initial_status_var;
+ else
+ status_vars= &m_safe_thd->status_var;
+
+ return status_vars;
+}
+
+/**
+ Build cache for GLOBAL status variables using values totaled from all threads.
+*/
+int PFS_status_variable_cache::do_materialize_global(void)
+{
+ STATUS_VAR status_totals;
+
+ m_materialized= false;
+ DEBUG_SYNC(m_current_thd, "before_materialize_global_status_array");
+
+ /* Acquire LOCK_status to guard against plugin load/unload. */
+ //if (m_current_thd->fill_status_recursion_level++ == 0)
+ mysql_mutex_lock(&LOCK_status);
+
+ /*
+ Build array of SHOW_VARs from global status array. Do this within
+ LOCK_status to ensure that the array remains unchanged during
+ materialization.
+ */
+ if (!m_external_init)
+ init_show_var_array(OPT_GLOBAL, true);
+
+ /*
+ Collect totals for all active threads. Start with global status vars as a
+ baseline.
+ */
+ PFS_connection_status_visitor visitor(&status_totals);
+ PFS_connection_iterator::visit_global(false, /* hosts */
+ false, /* users */
+ false, /* accounts */
+ false, /* threads */
+ true, /* THDs */
+ &visitor);
+ /*
+ Build the status variable cache using the SHOW_VAR array as a reference.
+ Use the status totals collected from all threads.
+ */
+ manifest(m_current_thd, m_show_var_array.front(), &status_totals, "", false, true);
+
+ //if (m_current_thd->fill_status_recursion_level-- == 1)
+ mysql_mutex_unlock(&LOCK_status);
+
+ m_materialized= true;
+ DEBUG_SYNC(m_current_thd, "after_materialize_global_status_array");
+
+ return 0;
+}
+
+/**
+ Build GLOBAL and SESSION status variable cache using values for a non-instrumented thread.
+*/
+int PFS_status_variable_cache::do_materialize_all(THD* unsafe_thd)
+{
+ int ret= 1;
+ DBUG_ASSERT(unsafe_thd != NULL);
+
+ m_unsafe_thd= unsafe_thd;
+ m_materialized= false;
+ m_cache.clear();
+
+ /* Avoid recursive acquisition of LOCK_status. */
+ //if (m_current_thd->fill_status_recursion_level++ == 0)
+ mysql_mutex_lock(&LOCK_status);
+
+ /*
+ Build array of SHOW_VARs from global status array. Do this within
+ LOCK_status to ensure that the array remains unchanged while this
+ thread is materialized.
+ */
+ if (!m_external_init)
+ init_show_var_array(OPT_SESSION, false);
+
+ /* Get and lock a validated THD from the thread manager. */
+ if ((m_safe_thd= get_THD(unsafe_thd)) != NULL)
+ {
+ /*
+ Build the status variable cache using the SHOW_VAR array as a reference.
+ Use the status values from the THD protected by the thread manager lock.
+ */
+ STATUS_VAR *status_vars= set_status_vars();
+ manifest(m_safe_thd, m_show_var_array.front(), status_vars, "", false, false);
+
+ /* Release lock taken in get_THD(). */
+ mysql_mutex_unlock(&m_safe_thd->LOCK_thd_data);
+
+ m_materialized= true;
+ ret= 0;
+ }
+
+ //if (m_current_thd->fill_status_recursion_level-- == 1)
+ mysql_mutex_unlock(&LOCK_status);
+ return ret;
+}
+
+/**
+ Build SESSION status variable cache using values for a non-instrumented thread.
+*/
+int PFS_status_variable_cache::do_materialize_session(THD* unsafe_thd)
+{
+ int ret= 1;
+ DBUG_ASSERT(unsafe_thd != NULL);
+
+ m_unsafe_thd= unsafe_thd;
+ m_materialized= false;
+ m_cache.clear();
+
+ /* Avoid recursive acquisition of LOCK_status. */
+ //if (m_current_thd->fill_status_recursion_level++ == 0)
+ mysql_mutex_lock(&LOCK_status);
+
+ /*
+ Build array of SHOW_VARs from global status array. Do this within
+ LOCK_status to ensure that the array remains unchanged while this
+ thread is materialized.
+ */
+ if (!m_external_init)
+ init_show_var_array(OPT_SESSION, true);
+
+ /* Get and lock a validated THD from the thread manager. */
+ if ((m_safe_thd= get_THD(unsafe_thd)) != NULL)
+ {
+ /*
+ Build the status variable cache using the SHOW_VAR array as a reference.
+ Use the status values from the THD protected by the thread manager lock.
+ */
+ STATUS_VAR *status_vars= set_status_vars();
+ manifest(m_safe_thd, m_show_var_array.front(), status_vars, "", false, true);
+
+ /* Release lock taken in get_THD(). */
+ mysql_mutex_unlock(&m_safe_thd->LOCK_thd_data);
+
+ m_materialized= true;
+ ret= 0;
+ }
+
+ //if (m_current_thd->fill_status_recursion_level-- == 1)
+ mysql_mutex_unlock(&LOCK_status);
+ return ret;
+}
+
+/**
+ Build SESSION status variable cache using values for a PFS_thread.
+ NOTE: Requires that init_show_var_array() has already been called.
+*/
+int PFS_status_variable_cache::do_materialize_session(PFS_thread *pfs_thread)
+{
+ int ret= 1;
+ DBUG_ASSERT(pfs_thread != NULL);
+
+ m_pfs_thread= pfs_thread;
+ m_materialized= false;
+ m_cache.clear();
+
+ /* Acquire LOCK_status to guard against plugin load/unload. */
+ //if (m_current_thd->fill_status_recursion_level++ == 0)
+ mysql_mutex_lock(&LOCK_status);
+
+ /* The SHOW_VAR array must be initialized externally. */
+ DBUG_ASSERT(m_initialized);
+
+ /* Get and lock a validated THD from the thread manager. */
+ if ((m_safe_thd= get_THD(pfs_thread)) != NULL)
+ {
+ /*
+ Build the status variable cache using the SHOW_VAR array as a reference.
+ Use the status values from the THD protected by the thread manager lock.
+ */
+ STATUS_VAR *status_vars= set_status_vars();
+ manifest(m_safe_thd, m_show_var_array.front(), status_vars, "", false, true);
+
+ /* Release lock taken in get_THD(). */
+ mysql_mutex_unlock(&m_safe_thd->LOCK_thd_data);
+
+ m_materialized= true;
+ ret= 0;
+ }
+
+ //if (m_current_thd->fill_status_recursion_level-- == 1)
+ mysql_mutex_unlock(&LOCK_status);
+ return ret;
+}
+
+/**
+ Build cache of SESSION status variables using the status values provided.
+ The cache is associated with a user, host or account, but not with any
+ particular thread.
+ NOTE: Requires that init_show_var_array() has already been called.
+*/
+int PFS_status_variable_cache::do_materialize_client(PFS_client *pfs_client)
+{
+ DBUG_ASSERT(pfs_client != NULL);
+ STATUS_VAR status_totals;
+
+ m_pfs_client= pfs_client;
+ m_materialized= false;
+ m_cache.clear();
+
+ /* Acquire LOCK_status to guard against plugin load/unload. */
+ //if (m_current_thd->fill_status_recursion_level++ == 0)
+ mysql_mutex_lock(&LOCK_status);
+
+ /* The SHOW_VAR array must be initialized externally. */
+ DBUG_ASSERT(m_initialized);
+
+ /*
+ Generate status totals from active threads and from totals aggregated
+ from disconnected threads.
+ */
+ m_sum_client_status(pfs_client, &status_totals);
+
+ /*
+ Build the status variable cache using the SHOW_VAR array as a reference and
+ the status totals collected from threads associated with this client.
+ */
+ manifest(m_current_thd, m_show_var_array.front(), &status_totals, "", false, true);
+
+ //if (m_current_thd->fill_status_recursion_level-- == 1)
+ mysql_mutex_unlock(&LOCK_status);
+
+ m_materialized= true;
+ return 0;
+}
+
+/*
+ Build the status variable cache from the expanded and sorted SHOW_VAR array.
+ Resolve status values using the STATUS_VAR struct provided.
+*/
+void PFS_status_variable_cache::manifest(THD *thd, const SHOW_VAR *show_var_array,
+ STATUS_VAR *status_vars, const char *prefix,
+ bool nested_array, bool strict)
+{
+ for (const SHOW_VAR *show_var_iter= show_var_array;
+ show_var_iter && show_var_iter->name;
+ show_var_iter++)
+ {
+ // work buffer, must be aligned to handle long/longlong values
+ my_aligned_storage<SHOW_VAR_FUNC_BUFF_SIZE+1, MY_ALIGNOF(longlong)>
+ value_buf;
+ SHOW_VAR show_var_tmp;
+ const SHOW_VAR *show_var_ptr= show_var_iter; /* preserve array pointer */
+
+ /*
+ If the value is a function reference, then execute the function and
+ reevaluate the new SHOW_TYPE and value. Handle nested case where
+ SHOW_FUNC resolves to another SHOW_FUNC.
+ */
+ if (show_var_ptr->type == SHOW_FUNC)
+ {
+ show_var_tmp= *show_var_ptr;
+ /*
+ Execute the function reference in show_var_tmp->value, which returns
+ show_var_tmp with a new type and new value.
+ */
+ for (const SHOW_VAR *var= show_var_ptr; var->type == SHOW_FUNC; var= &show_var_tmp)
+ {
+ ((mysql_show_var_func)(var->value))(thd, &show_var_tmp, value_buf.data, NULL, m_query_scope);
+ }
+ show_var_ptr= &show_var_tmp;
+ }
+
+ /*
+ If we are expanding a SHOW_ARRAY, filter variables that were not prefiltered by
+ init_show_var_array().
+ */
+ if (nested_array && filter_show_var(show_var_ptr, strict))
+ continue;
+
+ if (show_var_ptr->type == SHOW_ARRAY)
+ {
+ /*
+ Status variables of type SHOW_ARRAY were expanded and filtered by
+ init_show_var_array(), except where a SHOW_FUNC resolves into a
+ SHOW_ARRAY, such as with InnoDB. Recurse to expand the subarray.
+ */
+ manifest(thd, (SHOW_VAR *)show_var_ptr->value, status_vars, show_var_ptr->name, true, strict);
+ }
+ else
+ {
+ /* Add the materialized status variable to the cache. */
+ SHOW_VAR show_var= *show_var_ptr;
+ /*
+ For nested array expansions, make a copy of the variable name, just as
+ done in init_show_var_array().
+ */
+ if (nested_array)
+ show_var.name= make_show_var_name(prefix, show_var_ptr->name);
+
+ /* Convert status value to string format. Add to the cache. */
+ Status_variable status_var(&show_var, status_vars, m_query_scope);
+ m_cache.push(status_var);
+ }
+ }
+}
+
+/**
+ CLASS Status_variable
+*/
+Status_variable::Status_variable(const SHOW_VAR *show_var, STATUS_VAR *status_vars, enum_var_type query_scope)
+ : m_name_length(0), m_value_length(0), m_type(SHOW_UNDEF),
+ m_charset(NULL), m_initialized(false)
+{
+ init(show_var, status_vars, query_scope);
+}
+
+/**
+ Resolve status value, convert to string.
+ show_var->value is an offset into status_vars.
+ NOTE: Assumes LOCK_status is held.
+*/
+void Status_variable::init(const SHOW_VAR *show_var, STATUS_VAR *status_vars, enum_var_type query_scope)
+{
+ if (show_var == NULL || show_var->name == NULL)
+ return;
+ m_name= show_var->name;
+ m_name_length= strlen(m_name);
+ m_type= show_var->type;
+
+ /* Get the value of the status variable. */
+ char *value= m_value_str;
+ m_value_length= get_one_variable(status_vars, m_type, show_var->value, &value);
+ m_value_length= MY_MIN(m_value_length, SHOW_VAR_FUNC_BUFF_SIZE);
+
+ /* Returned value may reference a string other than m_value_str. */
+ if (value != m_value_str)
+ memcpy(m_value_str, value, m_value_length);
+ m_value_str[m_value_length]= 0;
+
+ m_initialized= true;
+}
+
+/*
+ Get status totals for this user from active THDs and related accounts.
+*/
+void sum_user_status(PFS_client *pfs_user, STATUS_VAR *status_totals)
+{
+ PFS_connection_status_visitor visitor(status_totals);
+ PFS_connection_iterator::visit_user((PFS_user *)pfs_user,
+ true, /* accounts */
+ false, /* threads */
+ true, /* THDs */
+ &visitor);
+}
+
+/*
+ Get status totals for this host from active THDs and related accounts.
+*/
+void sum_host_status(PFS_client *pfs_host, STATUS_VAR *status_totals)
+{
+ PFS_connection_status_visitor visitor(status_totals);
+ PFS_connection_iterator::visit_host((PFS_host *)pfs_host,
+ true, /* accounts */
+ false, /* threads */
+ true, /* THDs */
+ &visitor);
+}
+
+/*
+ Get status totals for this account from active THDs and from totals aggregated
+ from disconnectd threads.
+*/
+void sum_account_status(PFS_client *pfs_account, STATUS_VAR *status_totals)
+{
+ PFS_connection_status_visitor visitor(status_totals);
+ PFS_connection_iterator::visit_account((PFS_account *)pfs_account,
+ false, /* threads */
+ true, /* THDs */
+ &visitor);
+}
+
+/**
+ Reset aggregated status counter stats for account, user and host.
+ NOTE: Assumes LOCK_status is held.
+*/
+void reset_pfs_status_stats()
+{
+ reset_status_by_account();
+ reset_status_by_user();
+ reset_status_by_host();
+}
+
+/** @} */
diff --git a/storage/perfschema/pfs_variable.h b/storage/perfschema/pfs_variable.h
new file mode 100644
index 00000000000..eefca5612ea
--- /dev/null
+++ b/storage/perfschema/pfs_variable.h
@@ -0,0 +1,718 @@
+/* Copyright (c) 2015, 2018, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
+
+#ifndef PFS_VARIABLE_H
+#define PFS_VARIABLE_H
+
+/**
+ @file storage/perfschema/pfs_variable.h
+ Performance schema system and status variables (declarations).
+*/
+
+/**
+ OVERVIEW
+ --------
+ Status and system variables are implemented differently in the server, but the
+ steps to process them in the Performance Schema are essentially the same:
+
+ 1. INITIALIZE - Build or acquire a sorted list of variables to use for input.
+ Use the SHOW_VAR struct as an intermediate format common to system, status
+ and user vars:
+
+ SHOW_VAR
+ Name - Text string
+ Value - Pointer to memory location, function, subarray structure
+ Type - Scalar, function, or subarray
+ Scope - SESSION, GLOBAL, BOTH
+
+ Steps:
+ - Register the server's internal buffer with the class. Acquire locks
+ if necessary, then scan the contents of the input buffer.
+ - For system variables, convert each element to SHOW_VAR format, store in
+ a temporary array.
+ - For status variables, copy existing global status array into a local
+ array that can be used without locks. Expand nested subarrays, indicated
+ by a type of SHOW_ARRAY.
+
+ 2. MATERIALIZE - Convert the list of SHOW_VAR variables to string format,
+ store in a local cache:
+ - Resolve each variable according to the type.
+ - Recursively process unexpanded nested arrays and callback functions.
+ - Aggregate values across threads for global status.
+ - Convert numeric values to a string.
+ - Prefix variable name with the plugin name.
+
+ 3. OUTPUT - Iterate the cache for the SHOW command or table query.
+
+ CLASS OVERVIEW
+ --------------
+ 1. System_variable - A materialized system variable
+ 2. Status_variable - A materialized status variable
+ 3. PFS_variable_cache - Base class that defines the interface for the operations above.
+ public
+ init_show_var_array() - Build SHOW_VAR list of variables for processing
+ materialize_global() - Materialize global variables, aggregate across sessions
+ materialize_session() - Materialize variables for a given PFS_thread or THD
+ materialize_user() - Materialize variables for a user, aggregate across related threads.
+ materialize_host() - Materialize variables for a host, aggregate across related threads.
+ materialize_account() - Materialize variables for a account, aggregate across related threads.
+ private
+ m_show_var_array - Prealloc_array of SHOW_VARs for input to Materialize
+ m_cache - Prealloc_array of materialized variables for output
+ do_materialize_global() - Implementation of materialize_global()
+ do_materialize_session() - Implementation of materialize_session()
+ do_materialize_client() - Implementation of materialize_user/host/account()
+
+ 4. PFS_system_variable_cache - System variable implementation of PFS_variable_cache
+ 5. PFS_status_variable_cache - Status variable implementation of PFS_variable_cache
+ 6. Find_THD_variable - Used by the thread manager to find and lock a THD.
+
+ GLOSSARY
+ --------
+ Status variable - Server or plugin status counter. Not dynamic.
+ System variable - Server or plugin configuration variable. Usually dynamic.
+ GLOBAL scope - Associated with the server, no context at thread level.
+ SESSION scope - Associated with a connection or thread, but no global context.
+ BOTH scope - Globally defined but applies at the session level.
+ Initialize - Build list of variables in SHOW_VAR format.
+ Materialize - Convert variables in SHOW_VAR list to string, cache for output.
+ Manifest - Substep of Materialize. Resolve variable values according to
+ type. This includes SHOW_FUNC types which are resolved by
+ executing a callback function (possibly recursively), and
+ SHOW_ARRAY types that expand into nested subarrays.
+ LOCK PRIORITIES
+ ---------------
+ System Variables
+ LOCK_plugin_delete (block plugin delete)
+ LOCK_system_variables_hash
+ LOCK_thd_data (block THD delete)
+ LOCK_thd_sysvar (block system variable updates, alloc_and_copy_thd_dynamic_variables)
+ LOCK_global_system_variables (very briefly held)
+
+ Status Variables
+ LOCK_status
+ LOCK_thd_data (block THD delete)
+*/
+
+/* Iteration on THD from the sql layer. */
+//#include "mysqld_thd_manager.h"
+#define PFS_VAR
+/* Class sys_var */
+#include "set_var.h"
+/* convert_value_to_string */
+#include "sql_show.h"
+/* PFS_thread */
+#include "pfs_instr.h"
+#include "pfs_user.h"
+#include "pfs_host.h"
+#include "pfs_account.h"
+#include "my_thread.h"
+
+/* Global array of all server and plugin-defined status variables. */
+extern DYNAMIC_ARRAY all_status_vars;
+extern bool status_vars_inited;
+static const uint SYSVAR_MEMROOT_BLOCK_SIZE = 4096;
+
+extern mysql_mutex_t LOCK_plugin_delete;
+
+class Find_THD_Impl;
+class Find_THD_variable;
+typedef PFS_connection_slice PFS_client;
+
+/**
+ CLASS System_variable - System variable derived from sys_var object.
+*/
+class System_variable
+{
+public:
+ System_variable();
+ System_variable(THD *target_thd, const SHOW_VAR *show_var,
+ enum_var_type query_scope, bool ignore);
+ ~System_variable() {}
+
+ bool is_null() const { return !m_initialized; }
+ bool is_ignored() const { return m_ignore; }
+
+public:
+ const char *m_name;
+ size_t m_name_length;
+ char m_value_str[SHOW_VAR_FUNC_BUFF_SIZE+1];
+ size_t m_value_length;
+ enum_mysql_show_type m_type;
+ int m_scope;
+ bool m_ignore;
+ const CHARSET_INFO *m_charset;
+
+private:
+ bool m_initialized;
+ void init(THD *thd, const SHOW_VAR *show_var, enum_var_type query_scope);
+};
+
+
+/**
+ CLASS Status_variable - Status variable derived from SHOW_VAR.
+*/
+class Status_variable
+{
+public:
+ Status_variable() : m_name(NULL), m_name_length(0), m_value_length(0),
+ m_type(SHOW_UNDEF),
+ m_charset(NULL), m_initialized(false) {}
+
+ Status_variable(const SHOW_VAR *show_var, STATUS_VAR *status_array, enum_var_type query_scope);
+
+ ~Status_variable() {}
+
+ bool is_null() const {return !m_initialized;};
+
+public:
+ const char *m_name;
+ size_t m_name_length;
+ char m_value_str[SHOW_VAR_FUNC_BUFF_SIZE+1];
+ size_t m_value_length;
+ SHOW_TYPE m_type;
+ const CHARSET_INFO *m_charset;
+private:
+ bool m_initialized;
+ void init(const SHOW_VAR *show_var, STATUS_VAR *status_array, enum_var_type query_scope);
+};
+
+
+/**
+ CLASS Find_THD_variable - Get and lock a validated THD from the thread manager.
+*/
+class Find_THD_variable //: public Find_THD_Impl
+{
+public:
+ Find_THD_variable() : m_unsafe_thd(NULL) {}
+ Find_THD_variable(THD *unsafe_thd) : m_unsafe_thd(unsafe_thd) {}
+
+ virtual bool operator()(THD *thd)
+ {
+ //TODO: filter bg threads?
+ if (thd != m_unsafe_thd)
+ return false;
+
+ /* Hold this lock to keep THD during materialization. */
+ mysql_mutex_lock(&thd->LOCK_thd_data);
+ return true;
+ }
+ void set_unsafe_thd(THD *unsafe_thd) { m_unsafe_thd= unsafe_thd; }
+private:
+ THD *m_unsafe_thd;
+};
+
+/**
+ CLASS PFS_variable_cache - Base class for a system or status variable cache.
+*/
+template <class Var_type>
+class PFS_variable_cache
+{
+public:
+ typedef Dynamic_array<Var_type> Variable_array;
+
+ PFS_variable_cache(bool external_init)
+ : m_safe_thd(NULL),
+ m_unsafe_thd(NULL),
+ m_current_thd(current_thd),
+ m_pfs_thread(NULL),
+ m_pfs_client(NULL),
+ //m_thd_finder(),
+ m_cache(PSI_INSTRUMENT_MEM, 200, 50),
+ m_initialized(false),
+ m_external_init(external_init),
+ m_materialized(false),
+ m_show_var_array(PSI_INSTRUMENT_MEM, 200, 50),
+ m_version(0),
+ m_query_scope(OPT_DEFAULT),
+ m_use_mem_root(false),
+ m_aggregate(false)
+ { }
+
+ virtual ~PFS_variable_cache()= 0;
+
+ /**
+ Build array of SHOW_VARs from the external variable source.
+ Filter using session scope.
+ */
+ bool initialize_session(void);
+
+ /**
+ Build array of SHOW_VARs suitable for aggregation by user, host or account.
+ Filter using session scope.
+ */
+ bool initialize_client_session(void);
+
+ /**
+ Build cache of GLOBAL system or status variables.
+ Aggregate across threads if applicable.
+ */
+ int materialize_global();
+
+ /**
+ Build cache of GLOBAL and SESSION variables for a non-instrumented thread.
+ */
+ int materialize_all(THD *thd);
+
+ /**
+ Build cache of SESSION variables for a non-instrumented thread.
+ */
+ int materialize_session(THD *thd);
+
+ /**
+ Build cache of SESSION variables for an instrumented thread.
+ */
+ int materialize_session(PFS_thread *pfs_thread, bool use_mem_root= false);
+
+ /**
+ Cache a single SESSION variable for an instrumented thread.
+ */
+ int materialize_session(PFS_thread *pfs_thread, uint index);
+
+ /**
+ Build cache of SESSION status variables for a user.
+ */
+ int materialize_user(PFS_user *pfs_user);
+
+ /**
+ Build cache of SESSION status variables for a host.
+ */
+ int materialize_host(PFS_host *pfs_host);
+
+ /**
+ Build cache of SESSION status variables for an account.
+ */
+ int materialize_account(PFS_account *pfs_account);
+
+ /**
+ True if variables have been materialized.
+ */
+ bool is_materialized(void)
+ {
+ return m_materialized;
+ }
+
+ /**
+ True if variables have been materialized for given THD.
+ */
+ bool is_materialized(THD *unsafe_thd)
+ {
+ return (unsafe_thd == m_unsafe_thd && m_materialized);
+ }
+
+ /**
+ True if variables have been materialized for given PFS_thread.
+ */
+ bool is_materialized(PFS_thread *pfs_thread)
+ {
+ return (pfs_thread == m_pfs_thread && m_materialized);
+ }
+
+ /**
+ True if variables have been materialized for given PFS_user.
+ */
+ bool is_materialized(PFS_user *pfs_user)
+ {
+ return (static_cast<PFS_client *>(pfs_user) == m_pfs_client && m_materialized);
+ }
+
+ /**
+ True if variables have been materialized for given PFS_host.
+ */
+ bool is_materialized(PFS_host *pfs_host)
+ {
+ return (static_cast<PFS_client *>(pfs_host) == m_pfs_client && m_materialized);
+ }
+
+ /**
+ True if variables have been materialized for given PFS_account.
+ */
+ bool is_materialized(PFS_account *pfs_account)
+ {
+ return (static_cast<PFS_client *>(pfs_account) == m_pfs_client && m_materialized);
+ }
+
+ /**
+ True if variables have been materialized for given PFS_user/host/account.
+ */
+ bool is_materialized(PFS_client *pfs_client)
+ {
+ return (static_cast<PFS_client *>(pfs_client) == m_pfs_client && m_materialized);
+ }
+
+ /**
+ Get a validated THD from the thread manager. Execute callback function while
+ inside of the thread manager locks.
+ */
+ THD *get_THD(THD *thd);
+ THD *get_THD(PFS_thread *pfs_thread);
+
+ /**
+ Get a single variable from the cache.
+ Get the first element in the cache by default.
+ */
+ const Var_type *get(uint index= 0) const
+ {
+ if (index >= m_cache.elements())
+ return NULL;
+
+ const Var_type *p= &m_cache.at(index);
+ return p;
+ }
+
+ /**
+ Number of elements in the cache.
+ */
+ uint size()
+ {
+ return (uint)m_cache.elements();
+ }
+
+private:
+ virtual bool do_initialize_global(void) { return true; }
+ virtual bool do_initialize_session(void) { return true; }
+ virtual int do_materialize_global(void) { return 1; }
+ virtual int do_materialize_all(THD *thd) { return 1; }
+ virtual int do_materialize_session(THD *thd) { return 1; }
+ virtual int do_materialize_session(PFS_thread *) { return 1; }
+ virtual int do_materialize_session(PFS_thread *, uint index) { return 1; }
+
+protected:
+ /* Validated THD */
+ THD *m_safe_thd;
+
+ /* Unvalidated THD */
+ THD *m_unsafe_thd;
+
+ /* Current THD */
+ THD *m_current_thd;
+
+ /* Current PFS_thread. */
+ PFS_thread *m_pfs_thread;
+
+ /* Current PFS_user, host or account. */
+ PFS_client *m_pfs_client;
+
+ /* Callback for thread iterator. */
+ //Find_THD_variable m_thd_finder;
+
+ /* Cache of materialized variables. */
+ Variable_array m_cache;
+
+ /* True when list of SHOW_VAR is complete. */
+ bool m_initialized;
+
+ /*
+ True if the SHOW_VAR array must be initialized externally from the
+ materialization step, such as with aggregations and queries by thread.
+ */
+ bool m_external_init;
+
+ /* True when cache is complete. */
+ bool m_materialized;
+
+ /* Array of variables to be materialized. Last element must be null. */
+ Dynamic_array<SHOW_VAR> m_show_var_array;
+
+ /* Version of global hash/array. Changes when vars added/removed. */
+ ulonglong m_version;
+
+ /* Query scope: GLOBAL or SESSION. */
+ enum_var_type m_query_scope;
+
+ /* True if temporary mem_root should be used for materialization. */
+ bool m_use_mem_root;
+
+ /* True if summarizing across users, hosts or accounts. */
+ bool m_aggregate;
+
+};
+
+#if 0
+/**
+ Required implementation for pure virtual destructor of a template class.
+*/
+template <class Var_type>
+PFS_variable_cache<Var_type>::~PFS_variable_cache()
+{
+}
+
+/**
+ Get a validated THD from the thread manager. Execute callback function while
+ while inside the thread manager lock.
+*/
+template <class Var_type>
+THD *PFS_variable_cache<Var_type>::get_THD(THD *unsafe_thd)
+{
+ if (unsafe_thd == NULL)
+ {
+ /*
+ May happen, precisely because the pointer is unsafe
+ (THD just disconnected for example).
+ No need to walk Global_THD_manager for that.
+ */
+ return NULL;
+ }
+
+ m_thd_finder.set_unsafe_thd(unsafe_thd);
+ THD* safe_thd= Global_THD_manager::get_instance()->find_thd(&m_thd_finder);
+ return safe_thd;
+}
+
+template <class Var_type>
+THD *PFS_variable_cache<Var_type>::get_THD(PFS_thread *pfs_thread)
+{
+ DBUG_ASSERT(pfs_thread != NULL);
+ return get_THD(pfs_thread->m_thd);
+}
+
+/**
+ Build array of SHOW_VARs from external source of system or status variables.
+ Filter using session scope.
+*/
+template <class Var_type>
+bool PFS_variable_cache<Var_type>::initialize_session(void)
+{
+ if (m_initialized)
+ return 0;
+
+ return do_initialize_session();
+}
+
+/**
+ Build array of SHOW_VARs suitable for aggregation by user, host or account.
+ Filter using session scope.
+*/
+template <class Var_type>
+bool PFS_variable_cache<Var_type>::initialize_client_session(void)
+{
+ if (m_initialized)
+ return 0;
+
+ /* Requires aggregation by user, host or account. */
+ m_aggregate= true;
+
+ return do_initialize_session();
+}
+
+/**
+ Build cache of all GLOBAL variables.
+*/
+template <class Var_type>
+int PFS_variable_cache<Var_type>::materialize_global()
+{
+ if (is_materialized())
+ return 0;
+
+ return do_materialize_global();
+}
+
+/**
+ Build cache of GLOBAL and SESSION variables for a non-instrumented thread.
+*/
+template <class Var_type>
+int PFS_variable_cache<Var_type>::materialize_all(THD *unsafe_thd)
+{
+ if (!unsafe_thd)
+ return 1;
+
+ if (is_materialized(unsafe_thd))
+ return 0;
+
+ return do_materialize_all(unsafe_thd);
+}
+
+/**
+ Build cache of SESSION variables for a non-instrumented thread.
+*/
+template <class Var_type>
+int PFS_variable_cache<Var_type>::materialize_session(THD *unsafe_thd)
+{
+ if (!unsafe_thd)
+ return 1;
+
+ if (is_materialized(unsafe_thd))
+ return 0;
+
+ return do_materialize_session(unsafe_thd);
+}
+
+/**
+ Build cache of SESSION variables for a thread.
+*/
+template <class Var_type>
+int PFS_variable_cache<Var_type>::materialize_session(PFS_thread *pfs_thread, bool use_mem_root)
+{
+ if (!pfs_thread)
+ return 1;
+
+ if (is_materialized(pfs_thread))
+ return 0;
+
+ if (!pfs_thread->m_lock.is_populated() || pfs_thread->m_thd == NULL)
+ return 1;
+
+ m_use_mem_root= use_mem_root;
+
+ return do_materialize_session(pfs_thread);
+}
+
+/**
+ Materialize a single variable for a thread.
+*/
+template <class Var_type>
+int PFS_variable_cache<Var_type>::materialize_session(PFS_thread *pfs_thread, uint index)
+{
+ /* No check for is_materialized(). */
+
+ if (!pfs_thread)
+ return 1;
+
+ if (!pfs_thread->m_lock.is_populated() || pfs_thread->m_thd == NULL)
+ return 1;
+
+ return do_materialize_session(pfs_thread, index);
+}
+#endif
+
+/**
+ CLASS PFS_system_variable_cache - System variable cache.
+*/
+class PFS_system_variable_cache : public PFS_variable_cache<System_variable>
+{
+public:
+ PFS_system_variable_cache(bool external_init) :
+ PFS_variable_cache<System_variable>(external_init),
+ m_mem_thd(NULL), m_mem_thd_save(NULL),
+ m_mem_sysvar_ptr(NULL) { }
+ bool match_scope(int scope);
+ ulonglong get_sysvar_hash_version(void) { return m_version; }
+ ~PFS_system_variable_cache() { free_mem_root(); }
+
+private:
+ /* Build SHOW_var array. */
+ bool init_show_var_array(enum_var_type scope, bool strict);
+ bool do_initialize_session(void);
+
+ /* Global */
+ int do_materialize_global(void);
+ /* Global and Session - THD */
+ int do_materialize_all(THD* thd);
+ /* Session - THD */
+ int do_materialize_session(THD* thd);
+ /* Session - PFS_thread */
+ int do_materialize_session(PFS_thread *thread);
+ /* Single variable - PFS_thread */
+ int do_materialize_session(PFS_thread *pfs_thread, uint index);
+
+ /* Temporary mem_root to use for materialization. */
+ MEM_ROOT m_mem_sysvar;
+ /* Pointer to THD::mem_root. */
+ MEM_ROOT **m_mem_thd;
+ /* Save THD::mem_root. */
+ MEM_ROOT *m_mem_thd_save;
+ /* Pointer to temporary mem_root. */
+ MEM_ROOT *m_mem_sysvar_ptr;
+ /* Allocate and/or assign temporary mem_root. */
+ void set_mem_root(void);
+ /* Mark all memory blocks as free in temporary mem_root. */
+ void clear_mem_root(void);
+ /* Free mem_root memory. */
+ void free_mem_root(void);
+};
+
+
+/**
+ CLASS PFS_status_variable_cache - Status variable cache
+*/
+class PFS_status_variable_cache : public PFS_variable_cache<Status_variable>
+{
+public:
+ PFS_status_variable_cache(bool external_init);
+
+ int materialize_user(PFS_user *pfs_user);
+ int materialize_host(PFS_host *pfs_host);
+ int materialize_account(PFS_account *pfs_account);
+
+ ulonglong get_status_array_version(void) { return m_version; }
+
+protected:
+ /* Get PFS_user, account or host associated with a PFS_thread. Implemented by table class. */
+ virtual PFS_client *get_pfs(PFS_thread *pfs_thread) { return NULL; }
+
+ /* True if query is a SHOW command. */
+ bool m_show_command;
+
+private:
+ bool do_initialize_session(void);
+
+ int do_materialize_global(void);
+ /* Global and Session - THD */
+ int do_materialize_all(THD* thd);
+ int do_materialize_session(THD *thd);
+ int do_materialize_session(PFS_thread *thread);
+ int do_materialize_session(PFS_thread *thread, uint index) { return 0; }
+ int do_materialize_client(PFS_client *pfs_client);
+
+ /* Callback to sum user, host or account status variables. */
+ void (*m_sum_client_status)(PFS_client *pfs_client, STATUS_VAR *status_totals);
+
+ /* Build SHOW_VAR array from external source. */
+ bool init_show_var_array(enum_var_type scope, bool strict);
+
+ /* Recursively expand nested SHOW_VAR arrays. */
+ void expand_show_var_array(const SHOW_VAR *show_var_array, const char *prefix, bool strict);
+
+ /* Exclude unwanted variables from the query. */
+ bool filter_show_var(const SHOW_VAR *show_var, bool strict);
+
+ /* Check the variable scope against the query scope. */
+ bool match_scope(SHOW_SCOPE variable_scope, bool strict);
+
+ /* Exclude specific status variables by name or prefix. */
+ bool filter_by_name(const SHOW_VAR *show_var);
+
+ /* Check if a variable has an aggregatable type. */
+ bool can_aggregate(enum_mysql_show_type variable_type);
+
+ /* Build status variable name with prefix. Return in the buffer provided. */
+ char *make_show_var_name(const char* prefix, const char* name, char *name_buf, size_t buf_len);
+
+ /* Build status variable name with prefix. Return copy of the string. */
+ char *make_show_var_name(const char* prefix, const char* name);
+
+ /* For the current THD, use initial_status_vars taken from before the query start. */
+ STATUS_VAR *set_status_vars(void);
+
+ /* Build the list of status variables from SHOW_VAR array. */
+ void manifest(THD *thd, const SHOW_VAR *show_var_array,
+ STATUS_VAR *status_var_array, const char *prefix, bool nested_array, bool strict);
+};
+
+/* Callback functions to sum status variables for a given user, host or account. */
+void sum_user_status(PFS_client *pfs_user, STATUS_VAR *status_totals);
+void sum_host_status(PFS_client *pfs_host, STATUS_VAR *status_totals);
+void sum_account_status(PFS_client *pfs_account, STATUS_VAR *status_totals);
+
+
+/** @} */
+#endif
diff --git a/storage/perfschema/pfs_visitor.cc b/storage/perfschema/pfs_visitor.cc
index 097965fde17..713139ef935 100644
--- a/storage/perfschema/pfs_visitor.cc
+++ b/storage/perfschema/pfs_visitor.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -28,6 +28,7 @@
#include "pfs_user.h"
#include "pfs_host.h"
#include "pfs_account.h"
+#include "pfs_buffer_container.h"
/**
@file storage/perfschema/pfs_visitor.cc
@@ -39,182 +40,330 @@
@{
*/
+class All_THD_visitor_adapter : public Do_THD_Impl
+{
+public:
+ All_THD_visitor_adapter(PFS_connection_visitor *visitor)
+ : m_visitor(visitor)
+ {}
+
+ virtual void operator()(THD *thd)
+ {
+ m_visitor->visit_THD(thd);
+ }
+
+private:
+ PFS_connection_visitor *m_visitor;
+};
+
/** Connection iterator */
void PFS_connection_iterator::visit_global(bool with_hosts, bool with_users,
bool with_accounts, bool with_threads,
+ bool with_THDs,
PFS_connection_visitor *visitor)
{
DBUG_ASSERT(visitor != NULL);
+ DBUG_ASSERT(! with_threads || ! with_THDs);
visitor->visit_global();
if (with_hosts)
{
- PFS_host *pfs= host_array;
- PFS_host *pfs_last= pfs + host_max;
- for ( ; pfs < pfs_last; pfs++)
+ PFS_host_iterator it= global_host_container.iterate();
+ PFS_host *pfs= it.scan_next();
+
+ while (pfs != NULL)
{
- if (pfs->m_lock.is_populated())
- visitor->visit_host(pfs);
+ visitor->visit_host(pfs);
+ pfs= it.scan_next();
}
}
if (with_users)
{
- PFS_user *pfs= user_array;
- PFS_user *pfs_last= pfs + user_max;
- for ( ; pfs < pfs_last; pfs++)
+ PFS_user_iterator it= global_user_container.iterate();
+ PFS_user *pfs= it.scan_next();
+
+ while (pfs != NULL)
{
- if (pfs->m_lock.is_populated())
- visitor->visit_user(pfs);
+ visitor->visit_user(pfs);
+ pfs= it.scan_next();
}
}
if (with_accounts)
{
- PFS_account *pfs= account_array;
- PFS_account *pfs_last= pfs + account_max;
- for ( ; pfs < pfs_last; pfs++)
+ PFS_account_iterator it= global_account_container.iterate();
+ PFS_account *pfs= it.scan_next();
+
+ while (pfs != NULL)
{
- if (pfs->m_lock.is_populated())
- visitor->visit_account(pfs);
+ visitor->visit_account(pfs);
+ pfs= it.scan_next();
}
}
+
if (with_threads)
{
- PFS_thread *pfs= thread_array;
- PFS_thread *pfs_last= pfs + thread_max;
- for ( ; pfs < pfs_last; pfs++)
+ PFS_thread_iterator it= global_thread_container.iterate();
+ PFS_thread *pfs= it.scan_next();
+
+ while (pfs != NULL)
{
- if (pfs->m_lock.is_populated())
- visitor->visit_thread(pfs);
+ visitor->visit_thread(pfs);
+ pfs= it.scan_next();
}
}
+
+ if (with_THDs)
+ {
+ All_THD_visitor_adapter adapter(visitor);
+ Global_THD_manager::get_instance()->do_for_all_thd(& adapter);
+ }
}
+class All_host_THD_visitor_adapter : public Do_THD_Impl
+{
+public:
+ All_host_THD_visitor_adapter(PFS_connection_visitor *visitor, PFS_host *host)
+ : m_visitor(visitor), m_host(host)
+ {}
+
+ virtual void operator()(THD *thd)
+ {
+ PSI_thread *psi= thd->get_psi();
+ PFS_thread *pfs= reinterpret_cast<PFS_thread*>(psi);
+ pfs= sanitize_thread(pfs);
+ if (pfs != NULL)
+ {
+ PFS_account *account= sanitize_account(pfs->m_account);
+ if (account != NULL)
+ {
+ if (account->m_host == m_host)
+ {
+ m_visitor->visit_THD(thd);
+ }
+ }
+ else if (pfs->m_host == m_host)
+ {
+ m_visitor->visit_THD(thd);
+ }
+ }
+ }
+
+private:
+ PFS_connection_visitor *m_visitor;
+ PFS_host *m_host;
+};
+
void PFS_connection_iterator::visit_host(PFS_host *host,
bool with_accounts, bool with_threads,
+ bool with_THDs,
PFS_connection_visitor *visitor)
{
DBUG_ASSERT(visitor != NULL);
+ DBUG_ASSERT(! with_threads || ! with_THDs);
visitor->visit_host(host);
if (with_accounts)
{
- PFS_account *pfs= account_array;
- PFS_account *pfs_last= pfs + account_max;
- for ( ; pfs < pfs_last; pfs++)
+ PFS_account_iterator it= global_account_container.iterate();
+ PFS_account *pfs= it.scan_next();
+
+ while (pfs != NULL)
{
- if ((pfs->m_host == host) && pfs->m_lock.is_populated())
+ if (pfs->m_host == host)
{
visitor->visit_account(pfs);
}
+ pfs= it.scan_next();
}
}
if (with_threads)
{
- PFS_thread *pfs= thread_array;
- PFS_thread *pfs_last= pfs + thread_max;
- for ( ; pfs < pfs_last; pfs++)
+ PFS_thread_iterator it= global_thread_container.iterate();
+ PFS_thread *pfs= it.scan_next();
+
+ while (pfs != NULL)
{
- if (pfs->m_lock.is_populated())
+ PFS_account *safe_account= sanitize_account(pfs->m_account);
+ if (((safe_account != NULL) && (safe_account->m_host == host)) /* 1 */
+ || (pfs->m_host == host)) /* 2 */
{
- PFS_account *safe_account= sanitize_account(pfs->m_account);
- if ((safe_account != NULL) && (safe_account->m_host == host))
- {
- /*
- If the thread belongs to a known user@host that belongs to this host,
- process it.
- */
- visitor->visit_thread(pfs);
- }
- else if (pfs->m_host == host)
+ /*
+ If the thread belongs to:
+ - (1) a known user@host that belongs to this host,
+ - (2) a 'lost' user@host that belongs to this host
+ process it.
+ */
+ visitor->visit_thread(pfs);
+ }
+ pfs= it.scan_next();
+ }
+ }
+
+ if (with_THDs)
+ {
+ All_host_THD_visitor_adapter adapter(visitor, host);
+ Global_THD_manager::get_instance()->do_for_all_thd(& adapter);
+ }
+}
+
+class All_user_THD_visitor_adapter : public Do_THD_Impl
+{
+public:
+ All_user_THD_visitor_adapter(PFS_connection_visitor *visitor, PFS_user *user)
+ : m_visitor(visitor), m_user(user)
+ {}
+
+ virtual void operator()(THD *thd)
+ {
+ PSI_thread *psi= thd->get_psi();
+ PFS_thread *pfs= reinterpret_cast<PFS_thread*>(psi);
+ pfs= sanitize_thread(pfs);
+ if (pfs != NULL)
+ {
+ PFS_account *account= sanitize_account(pfs->m_account);
+ if (account != NULL)
+ {
+ if (account->m_user == m_user)
{
- /*
- If the thread belongs to a 'lost' user@host that belong to this host,
- process it.
- */
- visitor->visit_thread(pfs);
+ m_visitor->visit_THD(thd);
}
}
+ else if (pfs->m_user == m_user)
+ {
+ m_visitor->visit_THD(thd);
+ }
}
}
-}
+
+private:
+ PFS_connection_visitor *m_visitor;
+ PFS_user *m_user;
+};
void PFS_connection_iterator::visit_user(PFS_user *user,
bool with_accounts, bool with_threads,
+ bool with_THDs,
PFS_connection_visitor *visitor)
{
DBUG_ASSERT(visitor != NULL);
+ DBUG_ASSERT(! with_threads || ! with_THDs);
visitor->visit_user(user);
if (with_accounts)
{
- PFS_account *pfs= account_array;
- PFS_account *pfs_last= pfs + account_max;
- for ( ; pfs < pfs_last; pfs++)
+ PFS_account_iterator it= global_account_container.iterate();
+ PFS_account *pfs= it.scan_next();
+
+ while (pfs != NULL)
{
- if ((pfs->m_user == user) && pfs->m_lock.is_populated())
+ if (pfs->m_user == user)
{
visitor->visit_account(pfs);
}
+ pfs= it.scan_next();
}
}
if (with_threads)
{
- PFS_thread *pfs= thread_array;
- PFS_thread *pfs_last= pfs + thread_max;
- for ( ; pfs < pfs_last; pfs++)
+ PFS_thread_iterator it= global_thread_container.iterate();
+ PFS_thread *pfs= it.scan_next();
+
+ while (pfs != NULL)
{
- if (pfs->m_lock.is_populated())
+ PFS_account *safe_account= sanitize_account(pfs->m_account);
+ if (((safe_account != NULL) && (safe_account->m_user == user)) /* 1 */
+ || (pfs->m_user == user)) /* 2 */
{
- PFS_account *safe_account= sanitize_account(pfs->m_account);
- if ((safe_account != NULL) && (safe_account->m_user == user))
- {
- /*
- If the thread belongs to a known user@host that belongs to this user,
- process it.
- */
- visitor->visit_thread(pfs);
- }
- else if (pfs->m_user == user)
- {
- /*
- If the thread belongs to a 'lost' user@host that belong to this user,
- process it.
- */
- visitor->visit_thread(pfs);
- }
+ /*
+ If the thread belongs to:
+ - (1) a known user@host that belongs to this user,
+ - (2) a 'lost' user@host that belongs to this user
+ process it.
+ */
+ visitor->visit_thread(pfs);
}
+ pfs= it.scan_next();
}
}
+
+ if (with_THDs)
+ {
+ All_user_THD_visitor_adapter adapter(visitor, user);
+ Global_THD_manager::get_instance()->do_for_all_thd(& adapter);
+ }
}
+class All_account_THD_visitor_adapter : public Do_THD_Impl
+{
+public:
+ All_account_THD_visitor_adapter(PFS_connection_visitor *visitor, PFS_account *account)
+ : m_visitor(visitor), m_account(account)
+ {}
+
+ virtual void operator()(THD *thd)
+ {
+ PSI_thread *psi= thd->get_psi();
+ PFS_thread *pfs= reinterpret_cast<PFS_thread*>(psi);
+ pfs= sanitize_thread(pfs);
+ if (pfs != NULL)
+ {
+ if (pfs->m_account == m_account)
+ {
+ m_visitor->visit_THD(thd);
+ }
+ }
+ }
+
+private:
+ PFS_connection_visitor *m_visitor;
+ PFS_account *m_account;
+};
+
void PFS_connection_iterator::visit_account(PFS_account *account,
- bool with_threads,
- PFS_connection_visitor *visitor)
+ bool with_threads,
+ bool with_THDs,
+ PFS_connection_visitor *visitor)
{
DBUG_ASSERT(visitor != NULL);
+ DBUG_ASSERT(! with_threads || ! with_THDs);
visitor->visit_account(account);
if (with_threads)
{
- PFS_thread *pfs= thread_array;
- PFS_thread *pfs_last= pfs + thread_max;
- for ( ; pfs < pfs_last; pfs++)
+ PFS_thread_iterator it= global_thread_container.iterate();
+ PFS_thread *pfs= it.scan_next();
+
+ while (pfs != NULL)
{
- if ((pfs->m_account == account) && pfs->m_lock.is_populated())
+ if (pfs->m_account == account)
{
visitor->visit_thread(pfs);
}
+ pfs= it.scan_next();
}
}
+
+ if (with_THDs)
+ {
+ All_account_THD_visitor_adapter adapter(visitor, account);
+ Global_THD_manager::get_instance()->do_for_all_thd(& adapter);
+ }
+}
+
+void PFS_connection_iterator::visit_THD(THD *thd,
+ PFS_connection_visitor *visitor)
+{
+ DBUG_ASSERT(visitor != NULL);
+ visitor->visit_THD(thd);
}
void PFS_instance_iterator::visit_all(PFS_instance_visitor *visitor)
@@ -246,14 +395,13 @@ void PFS_instance_iterator::visit_all_mutex_classes(PFS_instance_visitor *visito
void PFS_instance_iterator::visit_all_mutex_instances(PFS_instance_visitor *visitor)
{
- PFS_mutex *pfs= mutex_array;
- PFS_mutex *pfs_last= pfs + mutex_max;
- for ( ; pfs < pfs_last; pfs++)
+ PFS_mutex_iterator it= global_mutex_container.iterate();
+ PFS_mutex *pfs= it.scan_next();
+
+ while (pfs != NULL)
{
- if (pfs->m_lock.is_populated())
- {
- visitor->visit_mutex(pfs);
- }
+ visitor->visit_mutex(pfs);
+ pfs= it.scan_next();
}
}
@@ -278,14 +426,13 @@ void PFS_instance_iterator::visit_all_rwlock_classes(PFS_instance_visitor *visit
void PFS_instance_iterator::visit_all_rwlock_instances(PFS_instance_visitor *visitor)
{
- PFS_rwlock *pfs= rwlock_array;
- PFS_rwlock *pfs_last= pfs + rwlock_max;
- for ( ; pfs < pfs_last; pfs++)
+ PFS_rwlock_iterator it= global_rwlock_container.iterate();
+ PFS_rwlock *pfs= it.scan_next();
+
+ while (pfs != NULL)
{
- if (pfs->m_lock.is_populated())
- {
- visitor->visit_rwlock(pfs);
- }
+ visitor->visit_rwlock(pfs);
+ pfs= it.scan_next();
}
}
@@ -310,14 +457,13 @@ void PFS_instance_iterator::visit_all_cond_classes(PFS_instance_visitor *visitor
void PFS_instance_iterator::visit_all_cond_instances(PFS_instance_visitor *visitor)
{
- PFS_cond *pfs= cond_array;
- PFS_cond *pfs_last= pfs + cond_max;
- for ( ; pfs < pfs_last; pfs++)
+ PFS_cond_iterator it= global_cond_container.iterate();
+ PFS_cond *pfs= it.scan_next();
+
+ while (pfs != NULL)
{
- if (pfs->m_lock.is_populated())
- {
- visitor->visit_cond(pfs);
- }
+ visitor->visit_cond(pfs);
+ pfs= it.scan_next();
}
}
@@ -342,14 +488,13 @@ void PFS_instance_iterator::visit_all_file_classes(PFS_instance_visitor *visitor
void PFS_instance_iterator::visit_all_file_instances(PFS_instance_visitor *visitor)
{
- PFS_file *pfs= file_array;
- PFS_file *pfs_last= pfs + file_max;
- for ( ; pfs < pfs_last; pfs++)
+ PFS_file_iterator it= global_file_container.iterate();
+ PFS_file *pfs= it.scan_next();
+
+ while (pfs != NULL)
{
- if (pfs->m_lock.is_populated())
- {
- visitor->visit_file(pfs);
- }
+ visitor->visit_file(pfs);
+ pfs= it.scan_next();
}
}
@@ -375,14 +520,16 @@ void PFS_instance_iterator::visit_mutex_instances(PFS_mutex_class *klass,
}
else
{
- PFS_mutex *pfs= mutex_array;
- PFS_mutex *pfs_last= pfs + mutex_max;
- for ( ; pfs < pfs_last; pfs++)
+ PFS_mutex_iterator it= global_mutex_container.iterate();
+ PFS_mutex *pfs= it.scan_next();
+
+ while (pfs != NULL)
{
- if ((pfs->m_class == klass) && pfs->m_lock.is_populated())
+ if (pfs->m_class == klass)
{
visitor->visit_mutex(pfs);
}
+ pfs= it.scan_next();
}
}
}
@@ -407,14 +554,16 @@ void PFS_instance_iterator::visit_rwlock_instances(PFS_rwlock_class *klass,
}
else
{
- PFS_rwlock *pfs= rwlock_array;
- PFS_rwlock *pfs_last= pfs + rwlock_max;
- for ( ; pfs < pfs_last; pfs++)
+ PFS_rwlock_iterator it= global_rwlock_container.iterate();
+ PFS_rwlock *pfs= it.scan_next();
+
+ while (pfs != NULL)
{
- if ((pfs->m_class == klass) && pfs->m_lock.is_populated())
+ if (pfs->m_class == klass)
{
visitor->visit_rwlock(pfs);
}
+ pfs= it.scan_next();
}
}
}
@@ -439,14 +588,16 @@ void PFS_instance_iterator::visit_cond_instances(PFS_cond_class *klass,
}
else
{
- PFS_cond *pfs= cond_array;
- PFS_cond *pfs_last= pfs + cond_max;
- for ( ; pfs < pfs_last; pfs++)
+ PFS_cond_iterator it= global_cond_container.iterate();
+ PFS_cond *pfs= it.scan_next();
+
+ while (pfs != NULL)
{
- if ((pfs->m_class == klass) && pfs->m_lock.is_populated())
+ if (pfs->m_class == klass)
{
visitor->visit_cond(pfs);
}
+ pfs= it.scan_next();
}
}
}
@@ -471,14 +622,16 @@ void PFS_instance_iterator::visit_file_instances(PFS_file_class *klass,
}
else
{
- PFS_file *pfs= file_array;
- PFS_file *pfs_last= pfs + file_max;
- for ( ; pfs < pfs_last; pfs++)
+ PFS_file_iterator it= global_file_container.iterate();
+ PFS_file *pfs= it.scan_next();
+
+ while (pfs != NULL)
{
- if ((pfs->m_class == klass) && pfs->m_lock.is_populated())
+ if (pfs->m_class == klass)
{
visitor->visit_file(pfs);
}
+ pfs= it.scan_next();
}
}
}
@@ -505,14 +658,16 @@ void PFS_instance_iterator::visit_socket_instances(PFS_socket_class *klass,
}
else
{
- PFS_socket *pfs= socket_array;
- PFS_socket *pfs_last= pfs + socket_max;
- for ( ; pfs < pfs_last; pfs++)
+ PFS_socket_iterator it= global_socket_container.iterate();
+ PFS_socket *pfs= it.scan_next();
+
+ while (pfs != NULL)
{
- if ((pfs->m_class == klass) && pfs->m_lock.is_populated())
+ if (pfs->m_class == klass)
{
visitor->visit_socket(pfs);
}
+ pfs= it.scan_next();
}
}
}
@@ -542,16 +697,17 @@ void PFS_instance_iterator::visit_socket_instances(PFS_socket_class *klass,
else
{
/* Get current socket stats from each socket instance owned by this thread */
- PFS_socket *pfs= socket_array;
- PFS_socket *pfs_last= pfs + socket_max;
+ PFS_socket_iterator it= global_socket_container.iterate();
+ PFS_socket *pfs= it.scan_next();
- for ( ; pfs < pfs_last; pfs++)
+ while (pfs != NULL)
{
if (unlikely((pfs->m_class == klass) &&
(pfs->m_thread_owner == thread)))
{
visitor->visit_socket(pfs);
}
+ pfs= it.scan_next();
}
}
}
@@ -586,53 +742,127 @@ void PFS_object_iterator::visit_all(PFS_object_visitor *visitor)
visit_all_tables(visitor);
}
-void PFS_object_iterator::visit_all_tables(PFS_object_visitor *visitor)
+class Proc_all_table_shares
+ : public PFS_buffer_processor<PFS_table_share>
{
- DBUG_ASSERT(visitor != NULL);
+public:
+ Proc_all_table_shares(PFS_object_visitor *visitor)
+ : m_visitor(visitor)
+ {}
- visitor->visit_global();
+ virtual void operator()(PFS_table_share *pfs)
+ {
+ if (pfs->m_enabled)
+ {
+ m_visitor->visit_table_share(pfs);
+ }
+ }
- /* For all the table shares ... */
- PFS_table_share *share= table_share_array;
- PFS_table_share *share_last= table_share_array + table_share_max;
- for ( ; share < share_last; share++)
+private:
+ PFS_object_visitor* m_visitor;
+};
+
+class Proc_all_table_handles
+ : public PFS_buffer_processor<PFS_table>
+{
+public:
+ Proc_all_table_handles(PFS_object_visitor *visitor)
+ : m_visitor(visitor)
+ {}
+
+ virtual void operator()(PFS_table *pfs)
{
- if (share->m_lock.is_populated())
+ PFS_table_share *safe_share= sanitize_table_share(pfs->m_share);
+ if (safe_share != NULL)
{
- visitor->visit_table_share(share);
+ if (safe_share->m_enabled)
+ {
+ m_visitor->visit_table(pfs);
+ }
}
}
+private:
+ PFS_object_visitor* m_visitor;
+};
+
+void PFS_object_iterator::visit_all_tables(PFS_object_visitor *visitor)
+{
+ DBUG_ASSERT(visitor != NULL);
+
+ visitor->visit_global();
+
+ /* For all the table shares ... */
+ Proc_all_table_shares proc_shares(visitor);
+ global_table_share_container.apply(proc_shares);
+
/* For all the table handles ... */
- PFS_table *table= table_array;
- PFS_table *table_last= table_array + table_max;
- for ( ; table < table_last; table++)
+ Proc_all_table_handles proc_handles(visitor);
+ global_table_container.apply(proc_handles);
+}
+
+class Proc_one_table_share_handles
+ : public PFS_buffer_processor<PFS_table>
+{
+public:
+ Proc_one_table_share_handles(PFS_object_visitor *visitor, PFS_table_share *share)
+ : m_visitor(visitor), m_share(share)
+ {}
+
+ virtual void operator()(PFS_table *pfs)
{
- if (table->m_lock.is_populated())
+ if (pfs->m_share == m_share)
{
- visitor->visit_table(table);
+ m_visitor->visit_table(pfs);
}
}
-}
+
+private:
+ PFS_object_visitor* m_visitor;
+ PFS_table_share* m_share;
+};
void PFS_object_iterator::visit_tables(PFS_table_share *share,
PFS_object_visitor *visitor)
{
DBUG_ASSERT(visitor != NULL);
+ if (!share->m_enabled)
+ return;
+
visitor->visit_table_share(share);
+#ifdef LATER
+ if (share->get_refcount() == 0)
+ return;
+#endif
+
/* For all the table handles ... */
- PFS_table *table= table_array;
- PFS_table *table_last= table_array + table_max;
- for ( ; table < table_last; table++)
+ Proc_one_table_share_handles proc(visitor, share);
+ global_table_container.apply(proc);
+}
+
+class Proc_one_table_share_indexes
+ : public PFS_buffer_processor<PFS_table>
+{
+public:
+ Proc_one_table_share_indexes(PFS_object_visitor *visitor, PFS_table_share *share, uint index)
+ : m_visitor(visitor), m_share(share), m_index(index)
+ {}
+
+ virtual void operator()(PFS_table *pfs)
{
- if ((table->m_share == share) && table->m_lock.is_populated())
+ if (pfs->m_share == m_share)
{
- visitor->visit_table(table);
+ m_visitor->visit_table_index(pfs, m_index);
}
}
-}
+
+private:
+ PFS_object_visitor* m_visitor;
+ PFS_table_share* m_share;
+ uint m_index;
+};
void PFS_object_iterator::visit_table_indexes(PFS_table_share *share,
uint index,
@@ -640,18 +870,19 @@ void PFS_object_iterator::visit_table_indexes(PFS_table_share *share,
{
DBUG_ASSERT(visitor != NULL);
+ if (!share->m_enabled)
+ return;
+
visitor->visit_table_share_index(share, index);
+#ifdef LATER
+ if (share->get_refcount() == 0)
+ return;
+#endif
+
/* For all the table handles ... */
- PFS_table *table= table_array;
- PFS_table *table_last= table_array + table_max;
- for ( ; table < table_last; table++)
- {
- if ((table->m_share == share) && table->m_lock.is_populated())
- {
- visitor->visit_table_index(table, index);
- }
- }
+ Proc_one_table_share_indexes proc(visitor, share, index);
+ global_table_container.apply(proc);
}
/** Connection wait visitor */
@@ -668,32 +899,62 @@ PFS_connection_wait_visitor::~PFS_connection_wait_visitor()
void PFS_connection_wait_visitor::visit_global()
{
/*
- This visitor is used only for idle instruments.
+ This visitor is used only for global instruments
+ that do not have instances.
For waits, do not sum by connection but by instances,
it is more efficient.
*/
- DBUG_ASSERT(m_index == global_idle_class.m_event_name_index);
- m_stat.aggregate(& global_idle_stat);
+ DBUG_ASSERT( (m_index == global_idle_class.m_event_name_index)
+ || (m_index == global_metadata_class.m_event_name_index));
+
+ if (m_index == global_idle_class.m_event_name_index)
+ {
+ m_stat.aggregate(& global_idle_stat);
+ }
+ else
+ {
+ m_stat.aggregate(& global_metadata_stat);
+ }
}
void PFS_connection_wait_visitor::visit_host(PFS_host *pfs)
{
- m_stat.aggregate(& pfs->m_instr_class_waits_stats[m_index]);
+ const PFS_single_stat *event_name_array;
+ event_name_array= pfs->read_instr_class_waits_stats();
+ if (event_name_array != NULL)
+ {
+ m_stat.aggregate(& event_name_array[m_index]);
+ }
}
void PFS_connection_wait_visitor::visit_user(PFS_user *pfs)
{
- m_stat.aggregate(& pfs->m_instr_class_waits_stats[m_index]);
+ const PFS_single_stat *event_name_array;
+ event_name_array= pfs->read_instr_class_waits_stats();
+ if (event_name_array != NULL)
+ {
+ m_stat.aggregate(& event_name_array[m_index]);
+ }
}
void PFS_connection_wait_visitor::visit_account(PFS_account *pfs)
{
- m_stat.aggregate(& pfs->m_instr_class_waits_stats[m_index]);
+ const PFS_single_stat *event_name_array;
+ event_name_array= pfs->read_instr_class_waits_stats();
+ if (event_name_array != NULL)
+ {
+ m_stat.aggregate(& event_name_array[m_index]);
+ }
}
void PFS_connection_wait_visitor::visit_thread(PFS_thread *pfs)
{
- m_stat.aggregate(& pfs->m_instr_class_waits_stats[m_index]);
+ const PFS_single_stat *event_name_array;
+ event_name_array= pfs->read_instr_class_waits_stats();
+ if (event_name_array != NULL)
+ {
+ m_stat.aggregate(& event_name_array[m_index]);
+ }
}
PFS_connection_all_wait_visitor
@@ -711,11 +972,14 @@ void PFS_connection_all_wait_visitor::visit_global()
void PFS_connection_all_wait_visitor::visit_connection_slice(PFS_connection_slice *pfs)
{
- PFS_single_stat *stat= pfs->m_instr_class_waits_stats;
- PFS_single_stat *stat_last= stat + wait_class_max;
- for ( ; stat < stat_last; stat++)
+ const PFS_single_stat *stat= pfs->read_instr_class_waits_stats();
+ if (stat != NULL)
{
- m_stat.aggregate(stat);
+ const PFS_single_stat *stat_last= stat + wait_class_max;
+ for ( ; stat < stat_last; stat++)
+ {
+ m_stat.aggregate(stat);
+ }
}
}
@@ -754,22 +1018,42 @@ void PFS_connection_stage_visitor::visit_global()
void PFS_connection_stage_visitor::visit_host(PFS_host *pfs)
{
- m_stat.aggregate(& pfs->m_instr_class_stages_stats[m_index]);
+ const PFS_stage_stat *event_name_array;
+ event_name_array= pfs->read_instr_class_stages_stats();
+ if (event_name_array != NULL)
+ {
+ m_stat.aggregate(& event_name_array[m_index]);
+ }
}
void PFS_connection_stage_visitor::visit_user(PFS_user *pfs)
{
- m_stat.aggregate(& pfs->m_instr_class_stages_stats[m_index]);
+ const PFS_stage_stat *event_name_array;
+ event_name_array= pfs->read_instr_class_stages_stats();
+ if (event_name_array != NULL)
+ {
+ m_stat.aggregate(& event_name_array[m_index]);
+ }
}
void PFS_connection_stage_visitor::visit_account(PFS_account *pfs)
{
- m_stat.aggregate(& pfs->m_instr_class_stages_stats[m_index]);
+ const PFS_stage_stat *event_name_array;
+ event_name_array= pfs->read_instr_class_stages_stats();
+ if (event_name_array != NULL)
+ {
+ m_stat.aggregate(& event_name_array[m_index]);
+ }
}
void PFS_connection_stage_visitor::visit_thread(PFS_thread *pfs)
{
- m_stat.aggregate(& pfs->m_instr_class_stages_stats[m_index]);
+ const PFS_stage_stat *event_name_array;
+ event_name_array= pfs->read_instr_class_stages_stats();
+ if (event_name_array != NULL)
+ {
+ m_stat.aggregate(& event_name_array[m_index]);
+ }
}
PFS_connection_statement_visitor
@@ -788,22 +1072,42 @@ void PFS_connection_statement_visitor::visit_global()
void PFS_connection_statement_visitor::visit_host(PFS_host *pfs)
{
- m_stat.aggregate(& pfs->m_instr_class_statements_stats[m_index]);
+ const PFS_statement_stat *event_name_array;
+ event_name_array= pfs->read_instr_class_statements_stats();
+ if (event_name_array != NULL)
+ {
+ m_stat.aggregate(& event_name_array[m_index]);
+ }
}
void PFS_connection_statement_visitor::visit_user(PFS_user *pfs)
{
- m_stat.aggregate(& pfs->m_instr_class_statements_stats[m_index]);
+ const PFS_statement_stat *event_name_array;
+ event_name_array= pfs->read_instr_class_statements_stats();
+ if (event_name_array != NULL)
+ {
+ m_stat.aggregate(& event_name_array[m_index]);
+ }
}
void PFS_connection_statement_visitor::visit_account(PFS_account *pfs)
{
- m_stat.aggregate(& pfs->m_instr_class_statements_stats[m_index]);
+ const PFS_statement_stat *event_name_array;
+ event_name_array= pfs->read_instr_class_statements_stats();
+ if (event_name_array != NULL)
+ {
+ m_stat.aggregate(& event_name_array[m_index]);
+ }
}
void PFS_connection_statement_visitor::visit_thread(PFS_thread *pfs)
{
- m_stat.aggregate(& pfs->m_instr_class_statements_stats[m_index]);
+ const PFS_statement_stat *event_name_array;
+ event_name_array= pfs->read_instr_class_statements_stats();
+ if (event_name_array != NULL)
+ {
+ m_stat.aggregate(& event_name_array[m_index]);
+ }
}
/** Instance wait visitor */
@@ -826,11 +1130,14 @@ void PFS_connection_all_statement_visitor::visit_global()
void PFS_connection_all_statement_visitor::visit_connection_slice(PFS_connection_slice *pfs)
{
- PFS_statement_stat *stat= pfs->m_instr_class_statements_stats;
- PFS_statement_stat *stat_last= stat + statement_class_max;
- for ( ; stat < stat_last; stat++)
+ const PFS_statement_stat *stat= pfs->read_instr_class_statements_stats();
+ if (stat != NULL)
{
- m_stat.aggregate(stat);
+ const PFS_statement_stat *stat_last= stat + statement_class_max;
+ for ( ; stat < stat_last; stat++)
+ {
+ m_stat.aggregate(stat);
+ }
}
}
@@ -854,6 +1161,102 @@ void PFS_connection_all_statement_visitor::visit_thread(PFS_thread *pfs)
visit_connection_slice(pfs);
}
+PFS_connection_transaction_visitor
+::PFS_connection_transaction_visitor(PFS_transaction_class *klass)
+{
+ m_index= klass->m_event_name_index;
+}
+
+PFS_connection_transaction_visitor::~PFS_connection_transaction_visitor()
+{}
+
+void PFS_connection_transaction_visitor::visit_global()
+{
+ m_stat.aggregate(&global_transaction_stat);
+}
+
+void PFS_connection_transaction_visitor::visit_host(PFS_host *pfs)
+{
+ const PFS_transaction_stat *event_name_array;
+ event_name_array= pfs->read_instr_class_transactions_stats();
+ if (event_name_array != NULL)
+ {
+ m_stat.aggregate(& event_name_array[m_index]);
+ }
+}
+
+void PFS_connection_transaction_visitor::visit_user(PFS_user *pfs)
+{
+ const PFS_transaction_stat *event_name_array;
+ event_name_array= pfs->read_instr_class_transactions_stats();
+ if (event_name_array != NULL)
+ {
+ m_stat.aggregate(& event_name_array[m_index]);
+ }
+}
+
+void PFS_connection_transaction_visitor::visit_account(PFS_account *pfs)
+{
+ const PFS_transaction_stat *event_name_array;
+ event_name_array= pfs->read_instr_class_transactions_stats();
+ if (event_name_array != NULL)
+ {
+ m_stat.aggregate(& event_name_array[m_index]);
+ }
+}
+
+void PFS_connection_transaction_visitor::visit_thread(PFS_thread *pfs)
+{
+ const PFS_transaction_stat *event_name_array;
+ event_name_array= pfs->read_instr_class_transactions_stats();
+ if (event_name_array != NULL)
+ {
+ m_stat.aggregate(& event_name_array[m_index]);
+ }
+}
+
+/** Disabled pending code review */
+#if 0
+/** Instance wait visitor */
+PFS_connection_all_transaction_visitor
+::PFS_connection_all_transaction_visitor()
+{}
+
+PFS_connection_all_transaction_visitor::~PFS_connection_all_transaction_visitor()
+{}
+
+void PFS_connection_all_transaction_visitor::visit_global()
+{
+ m_stat.aggregate(&global_transaction_stat);
+}
+
+void PFS_connection_all_transaction_visitor::visit_connection_slice(PFS_connection_slice *pfs)
+{
+ PFS_transaction_stat *stat= pfs->m_instr_class_transactions_stats;
+ m_stat.aggregate(stat);
+}
+
+void PFS_connection_all_transaction_visitor::visit_host(PFS_host *pfs)
+{
+ visit_connection_slice(pfs);
+}
+
+void PFS_connection_all_transaction_visitor::visit_user(PFS_user *pfs)
+{
+ visit_connection_slice(pfs);
+}
+
+void PFS_connection_all_transaction_visitor::visit_account(PFS_account *pfs)
+{
+ visit_connection_slice(pfs);
+}
+
+void PFS_connection_all_transaction_visitor::visit_thread(PFS_thread *pfs)
+{
+ visit_connection_slice(pfs);
+}
+#endif
+
PFS_connection_stat_visitor::PFS_connection_stat_visitor()
{}
@@ -883,10 +1286,117 @@ void PFS_connection_stat_visitor::visit_thread(PFS_thread *)
m_stat.aggregate_active(1);
}
-PFS_instance_wait_visitor::PFS_instance_wait_visitor()
+PFS_connection_memory_visitor
+::PFS_connection_memory_visitor(PFS_memory_class *klass)
+{
+ m_index= klass->m_event_name_index;
+ m_stat.reset();
+}
+
+PFS_connection_memory_visitor::~PFS_connection_memory_visitor()
+{}
+
+void PFS_connection_memory_visitor::visit_global()
+{
+ PFS_memory_stat *stat;
+ stat= & global_instr_class_memory_array[m_index];
+ stat->full_aggregate_to(& m_stat);
+}
+
+void PFS_connection_memory_visitor::visit_host(PFS_host *pfs)
+{
+ const PFS_memory_stat *event_name_array;
+ event_name_array= pfs->read_instr_class_memory_stats();
+ if (event_name_array != NULL)
+ {
+ const PFS_memory_stat *stat;
+ stat= & event_name_array[m_index];
+ stat->full_aggregate_to(& m_stat);
+ }
+}
+
+void PFS_connection_memory_visitor::visit_user(PFS_user *pfs)
{
+ const PFS_memory_stat *event_name_array;
+ event_name_array= pfs->read_instr_class_memory_stats();
+ if (event_name_array != NULL)
+ {
+ const PFS_memory_stat *stat;
+ stat= & event_name_array[m_index];
+ stat->full_aggregate_to(& m_stat);
+ }
}
+void PFS_connection_memory_visitor::visit_account(PFS_account *pfs)
+{
+ const PFS_memory_stat *event_name_array;
+ event_name_array= pfs->read_instr_class_memory_stats();
+ if (event_name_array != NULL)
+ {
+ const PFS_memory_stat *stat;
+ stat= & event_name_array[m_index];
+ stat->full_aggregate_to(& m_stat);
+ }
+}
+
+void PFS_connection_memory_visitor::visit_thread(PFS_thread *pfs)
+{
+ const PFS_memory_stat *event_name_array;
+ event_name_array= pfs->read_instr_class_memory_stats();
+ if (event_name_array != NULL)
+ {
+ const PFS_memory_stat *stat;
+ stat= & event_name_array[m_index];
+ stat->full_aggregate_to(& m_stat);
+ }
+}
+
+
+PFS_connection_status_visitor::
+PFS_connection_status_visitor(STATUS_VAR *status_vars) : m_status_vars(status_vars)
+{
+ memset(m_status_vars, 0, sizeof(STATUS_VAR));
+}
+
+PFS_connection_status_visitor::~PFS_connection_status_visitor()
+{}
+
+/** Aggregate from global status. */
+void PFS_connection_status_visitor::visit_global()
+{
+ /* NOTE: Requires lock on LOCK_status. */
+ mysql_mutex_assert_owner(&LOCK_status);
+ add_to_status(m_status_vars, &global_status_var, false);
+}
+
+void PFS_connection_status_visitor::visit_host(PFS_host *pfs)
+{
+ pfs->m_status_stats.aggregate_to(m_status_vars);
+}
+
+void PFS_connection_status_visitor::visit_user(PFS_user *pfs)
+{
+ pfs->m_status_stats.aggregate_to(m_status_vars);
+}
+
+void PFS_connection_status_visitor::visit_account(PFS_account *pfs)
+{
+ pfs->m_status_stats.aggregate_to(m_status_vars);
+}
+
+void PFS_connection_status_visitor::visit_thread(PFS_thread *pfs)
+{
+}
+
+void PFS_connection_status_visitor::visit_THD(THD *thd)
+{
+ add_to_status(m_status_vars, &thd->status_var, false);
+}
+
+
+PFS_instance_wait_visitor::PFS_instance_wait_visitor()
+{}
+
PFS_instance_wait_visitor::~PFS_instance_wait_visitor()
{}
@@ -930,7 +1440,7 @@ void PFS_instance_wait_visitor::visit_cond(PFS_cond *pfs)
m_stat.aggregate(& pfs->m_cond_stat.m_wait_stat);
}
-void PFS_instance_wait_visitor::visit_file(PFS_file *pfs)
+void PFS_instance_wait_visitor::visit_file(PFS_file *pfs)
{
/* Combine per-operation file wait stats before aggregating */
PFS_single_stat stat;
@@ -938,7 +1448,7 @@ void PFS_instance_wait_visitor::visit_file(PFS_file *pfs)
m_stat.aggregate(&stat);
}
-void PFS_instance_wait_visitor::visit_socket(PFS_socket *pfs)
+void PFS_instance_wait_visitor::visit_socket(PFS_socket *pfs)
{
/* Combine per-operation socket wait stats before aggregating */
PFS_single_stat stat;
@@ -963,7 +1473,7 @@ void PFS_object_wait_visitor::visit_global()
void PFS_object_wait_visitor::visit_table_share(PFS_table_share *pfs)
{
uint safe_key_count= sanitize_index_count(pfs->m_key_count);
- pfs->m_table_stat.sum(& m_stat, safe_key_count);
+ pfs->sum(& m_stat, safe_key_count);
}
void PFS_object_wait_visitor::visit_table(PFS_table *pfs)
@@ -992,13 +1502,20 @@ 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;
+ PFS_table_share_index *index_stat;
/* Aggregate index stats */
for (index= 0; index < safe_key_count; index++)
- io_stat.aggregate(& pfs->m_table_stat.m_index_stat[index]);
+ {
+ index_stat= pfs->find_index_stat(index);
+ if (index_stat != NULL)
+ io_stat.aggregate(& index_stat->m_stat);
+ }
/* Aggregate global stats */
- io_stat.aggregate(& pfs->m_table_stat.m_index_stat[MAX_INDEXES]);
+ index_stat= pfs->find_index_stat(MAX_INDEXES);
+ if (index_stat != NULL)
+ io_stat.aggregate(& index_stat->m_stat);
io_stat.sum(& m_stat);
}
@@ -1036,13 +1553,20 @@ 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;
+ PFS_table_share_index *index_stat;
/* Aggregate index stats */
for (index= 0; index < safe_key_count; index++)
- m_stat.aggregate(& pfs->m_table_stat.m_index_stat[index]);
+ {
+ index_stat= pfs->find_index_stat(index);
+ if (index_stat != NULL)
+ m_stat.aggregate(& index_stat->m_stat);
+ }
/* Aggregate global stats */
- m_stat.aggregate(& pfs->m_table_stat.m_index_stat[MAX_INDEXES]);
+ index_stat= pfs->find_index_stat(MAX_INDEXES);
+ if (index_stat != NULL)
+ m_stat.aggregate(& index_stat->m_stat);
}
void PFS_table_io_stat_visitor::visit_table(PFS_table *pfs)
@@ -1073,7 +1597,11 @@ PFS_index_io_stat_visitor::~PFS_index_io_stat_visitor()
void PFS_index_io_stat_visitor::visit_table_share_index(PFS_table_share *pfs, uint index)
{
- m_stat.aggregate(& pfs->m_table_stat.m_index_stat[index]);
+ PFS_table_share_index *index_stat;
+
+ index_stat= pfs->find_index_stat(index);
+ if (index_stat != NULL)
+ m_stat.aggregate(& index_stat->m_stat);
}
void PFS_index_io_stat_visitor::visit_table_index(PFS_table *pfs, uint index)
@@ -1096,7 +1624,7 @@ void PFS_table_lock_wait_visitor::visit_global()
void PFS_table_lock_wait_visitor::visit_table_share(PFS_table_share *pfs)
{
- pfs->m_table_stat.sum_lock(& m_stat);
+ pfs->sum_lock(& m_stat);
}
void PFS_table_lock_wait_visitor::visit_table(PFS_table *pfs)
@@ -1114,7 +1642,11 @@ PFS_table_lock_stat_visitor::~PFS_table_lock_stat_visitor()
void PFS_table_lock_stat_visitor::visit_table_share(PFS_table_share *pfs)
{
- m_stat.aggregate(& pfs->m_table_stat.m_lock_stat);
+ PFS_table_share_lock *lock_stat;
+
+ lock_stat= pfs->find_lock_stat();
+ if (lock_stat != NULL)
+ m_stat.aggregate(& lock_stat->m_stat);
}
void PFS_table_lock_stat_visitor::visit_table(PFS_table *pfs)
@@ -1128,32 +1660,31 @@ PFS_instance_socket_io_stat_visitor::PFS_instance_socket_io_stat_visitor()
PFS_instance_socket_io_stat_visitor::~PFS_instance_socket_io_stat_visitor()
{}
-void PFS_instance_socket_io_stat_visitor::visit_socket_class(PFS_socket_class *pfs)
+void PFS_instance_socket_io_stat_visitor::visit_socket_class(PFS_socket_class *pfs)
{
/* Aggregate wait times, event counts and byte counts */
m_socket_io_stat.aggregate(&pfs->m_socket_stat.m_io_stat);
}
-void PFS_instance_socket_io_stat_visitor::visit_socket(PFS_socket *pfs)
+void PFS_instance_socket_io_stat_visitor::visit_socket(PFS_socket *pfs)
{
/* Aggregate wait times, event counts and byte counts */
m_socket_io_stat.aggregate(&pfs->m_socket_stat.m_io_stat);
}
-
PFS_instance_file_io_stat_visitor::PFS_instance_file_io_stat_visitor()
{}
PFS_instance_file_io_stat_visitor::~PFS_instance_file_io_stat_visitor()
{}
-void PFS_instance_file_io_stat_visitor::visit_file_class(PFS_file_class *pfs)
+void PFS_instance_file_io_stat_visitor::visit_file_class(PFS_file_class *pfs)
{
/* Aggregate wait times, event counts and byte counts */
m_file_io_stat.aggregate(&pfs->m_file_stat.m_io_stat);
}
-void PFS_instance_file_io_stat_visitor::visit_file(PFS_file *pfs)
+void PFS_instance_file_io_stat_visitor::visit_file(PFS_file *pfs)
{
/* Aggregate wait times, event counts and byte counts */
m_file_io_stat.aggregate(&pfs->m_file_stat.m_io_stat);
diff --git a/storage/perfschema/pfs_visitor.h b/storage/perfschema/pfs_visitor.h
index 120b5928045..a81567e9921 100644
--- a/storage/perfschema/pfs_visitor.h
+++ b/storage/perfschema/pfs_visitor.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -25,6 +25,8 @@
#include "pfs_stat.h"
+typedef struct system_status_var STATUS_VAR;
+
/**
@file storage/perfschema/pfs_visitor.h
Visitors (declarations).
@@ -45,6 +47,7 @@ struct PFS_rwlock_class;
struct PFS_cond_class;
struct PFS_file_class;
struct PFS_socket_class;
+struct PFS_memory_class;
struct PFS_table_share;
struct PFS_mutex;
struct PFS_rwlock;
@@ -53,6 +56,7 @@ struct PFS_file;
struct PFS_table;
struct PFS_stage_class;
struct PFS_statement_class;
+struct PFS_transaction_class;
struct PFS_socket;
struct PFS_connection_slice;
@@ -75,6 +79,8 @@ public:
virtual void visit_user(PFS_user *pfs) {}
/** Visit a thread. */
virtual void visit_thread(PFS_thread *pfs) {}
+ /** Visit a THD associated with a thread. */
+ virtual void visit_THD(THD *thd) {}
};
/**
@@ -90,37 +96,45 @@ public:
@param with_users when true, visit also all users.
@param with_accounts when true, visit also all user+host.
@param with_threads when true, visit also all threads.
+ @param with_THDs when true, visit also all threads THD.
@param visitor the visitor to call
*/
static void visit_global(bool with_hosts, bool with_users,
bool with_accounts, bool with_threads,
+ bool with_THDs,
PFS_connection_visitor *visitor);
/**
Visit all connections of a host.
@param host the host to visit.
@param with_accounts when true, visit also all related user+host.
@param with_threads when true, visit also all related threads.
+ @param with_THDs when true, visit also all related threads THD.
@param visitor the visitor to call
*/
static void visit_host(PFS_host *host, bool with_accounts, bool with_threads,
+ bool with_THDs,
PFS_connection_visitor *visitor);
/**
Visit all connections of a user.
@param user the user to visit.
@param with_accounts when true, visit also all related user+host.
@param with_threads when true, visit also all related threads.
+ @param with_THDs when true, visit also all related threads THD.
@param visitor the visitor to call
*/
static void visit_user(PFS_user *user, bool with_accounts, bool with_threads,
+ bool with_THDs,
PFS_connection_visitor *visitor);
/**
Visit all connections of a user+host.
@param account the user+host to visit.
@param with_threads when true, visit also all related threads.
+ @param with_THDs when true, visit also all related threads THD.
@param visitor the visitor to call
*/
static void visit_account(PFS_account *account, bool with_threads,
- PFS_connection_visitor *visitor);
+ bool with_THDs,
+ PFS_connection_visitor *visitor);
/**
Visit a thread or connection.
@param thread the thread to visit.
@@ -129,6 +143,13 @@ public:
static inline void visit_thread(PFS_thread *thread,
PFS_connection_visitor *visitor)
{ visitor->visit_thread(thread); }
+
+ /**
+ Visit THD.
+ @param thd the THD to visit.
+ @param visitor the visitor to call.
+ */
+ static void visit_THD(THD *thd, PFS_connection_visitor *visitor);
};
/**
@@ -397,6 +418,54 @@ private:
/**
A concrete connection visitor that aggregates
+ transaction statistics for a given event_name.
+*/
+class PFS_connection_transaction_visitor : public PFS_connection_visitor
+{
+public:
+ /** Constructor. */
+ PFS_connection_transaction_visitor(PFS_transaction_class *klass);
+ virtual ~PFS_connection_transaction_visitor();
+ virtual void visit_global();
+ virtual void visit_host(PFS_host *pfs);
+ virtual void visit_account(PFS_account *pfs);
+ virtual void visit_user(PFS_user *pfs);
+ virtual void visit_thread(PFS_thread *pfs);
+
+ /** EVENT_NAME instrument index. */
+ uint m_index;
+ /** Statement statistic collected. */
+ PFS_transaction_stat m_stat;
+};
+
+/** Disabled pending code review */
+#if 0
+/**
+ A concrete connection visitor that aggregates
+ transaction statistics for all events.
+*/
+class PFS_connection_all_transaction_visitor : public PFS_connection_visitor
+{
+public:
+ /** Constructor. */
+ PFS_connection_all_transaction_visitor();
+ virtual ~PFS_connection_all_transaction_visitor();
+ virtual void visit_global();
+ virtual void visit_host(PFS_host *pfs);
+ virtual void visit_account(PFS_account *pfs);
+ virtual void visit_user(PFS_user *pfs);
+ virtual void visit_thread(PFS_thread *pfs);
+
+ /** Statement statistic collected. */
+ PFS_transaction_stat m_stat;
+
+private:
+ void visit_connection_slice(PFS_connection_slice *pfs);
+};
+#endif
+
+/**
+ A concrete connection visitor that aggregates
connection statistics.
*/
class PFS_connection_stat_visitor : public PFS_connection_visitor
@@ -416,6 +485,49 @@ public:
};
/**
+ A concrete connection visitor that aggregates
+ memory statistics for a given event_name.
+*/
+class PFS_connection_memory_visitor : public PFS_connection_visitor
+{
+public:
+ /** Constructor. */
+ PFS_connection_memory_visitor(PFS_memory_class *klass);
+ virtual ~PFS_connection_memory_visitor();
+ virtual void visit_global();
+ virtual void visit_host(PFS_host *pfs);
+ virtual void visit_account(PFS_account *pfs);
+ virtual void visit_user(PFS_user *pfs);
+ virtual void visit_thread(PFS_thread *pfs);
+
+ /** EVENT_NAME instrument index. */
+ uint m_index;
+ /** Statement statistic collected. */
+ PFS_memory_stat m_stat;
+};
+
+/**
+ A concrete connection visitor that aggregates
+ status variables.
+*/
+class PFS_connection_status_visitor : public PFS_connection_visitor
+{
+public:
+ /** Constructor. */
+ PFS_connection_status_visitor(STATUS_VAR *status_vars);
+ virtual ~PFS_connection_status_visitor();
+ virtual void visit_global();
+ virtual void visit_host(PFS_host *pfs);
+ virtual void visit_account(PFS_account *pfs);
+ virtual void visit_user(PFS_user *pfs);
+ virtual void visit_thread(PFS_thread *pfs);
+ virtual void visit_THD(THD *thd);
+
+private:
+ STATUS_VAR *m_status_vars;
+};
+
+/**
A concrete instance visitor that aggregates
wait statistics.
*/
diff --git a/storage/perfschema/table_accounts.cc b/storage/perfschema/table_accounts.cc
index 708f8269a69..eb3f6481696 100644
--- a/storage/perfschema/table_accounts.cc
+++ b/storage/perfschema/table_accounts.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, 2015, 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, version 2.0,
@@ -21,12 +21,15 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "table_accounts.h"
#include "pfs_instr_class.h"
#include "pfs_instr.h"
#include "pfs_account.h"
#include "pfs_visitor.h"
+#include "pfs_memory.h"
+#include "pfs_status.h"
+#include "field.h"
THR_LOCK table_accounts::m_table_lock;
@@ -35,18 +38,18 @@ table_accounts::m_share=
{
{ C_STRING_WITH_LEN("accounts") },
&pfs_truncatable_acl,
- &table_accounts::create,
+ table_accounts::create,
NULL, /* write_row */
table_accounts::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ cursor_by_account::get_row_count,
sizeof(PFS_simple_index), /* ref length */
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE accounts("
- "USER CHAR(16) collate utf8_bin default null,"
+ "USER CHAR(" USERNAME_CHAR_LENGTH_STR ") collate utf8_bin default null,"
"HOST CHAR(60) collate utf8_bin default null,"
"CURRENT_CONNECTIONS bigint not null,"
- "TOTAL_CONNECTIONS bigint not null)") }
+ "TOTAL_CONNECTIONS bigint not null)") },
+ false /* perpetual */
};
PFS_engine_table* table_accounts::create()
@@ -63,6 +66,12 @@ table_accounts::delete_all_rows(void)
reset_events_stages_by_account();
reset_events_statements_by_thread();
reset_events_statements_by_account();
+ reset_events_transactions_by_thread();
+ reset_events_transactions_by_account();
+ reset_memory_by_thread();
+ reset_memory_by_account();
+ reset_status_by_thread();
+ reset_status_by_account();
purge_all_account();
return 0;
}
@@ -74,7 +83,7 @@ table_accounts::table_accounts()
void table_accounts::make_row(PFS_account *pfs)
{
- pfs_lock lock;
+ pfs_optimistic_state lock;
m_row_exists= false;
pfs->m_lock.begin_optimistic_lock(&lock);
@@ -83,7 +92,10 @@ void table_accounts::make_row(PFS_account *pfs)
return;
PFS_connection_stat_visitor visitor;
- PFS_connection_iterator::visit_account(pfs, true, & visitor);
+ PFS_connection_iterator::visit_account(pfs,
+ true, /* threads */
+ false, /* THDs */
+ & visitor);
if (! pfs->m_lock.end_optimistic_lock(& lock))
return;
diff --git a/storage/perfschema/table_accounts.h b/storage/perfschema/table_accounts.h
index dfc2cc322e0..7563e85c1d7 100644
--- a/storage/perfschema/table_accounts.h
+++ b/storage/perfschema/table_accounts.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, 2015, 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, version 2.0,
diff --git a/storage/perfschema/table_all_instr.cc b/storage/perfschema/table_all_instr.cc
index d48028b1539..b030b8824ca 100644
--- a/storage/perfschema/table_all_instr.cc
+++ b/storage/perfschema/table_all_instr.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -26,9 +26,20 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "table_all_instr.h"
#include "pfs_global.h"
+#include "pfs_buffer_container.h"
+
+ha_rows
+table_all_instr::get_row_count(void)
+{
+ return global_mutex_container.get_row_count()
+ + global_rwlock_container.get_row_count()
+ + global_cond_container.get_row_count()
+ + global_file_container.get_row_count()
+ + global_socket_container.get_row_count() ;
+}
table_all_instr::table_all_instr(const PFS_engine_table_share *share)
: PFS_engine_table(share, &m_pos),
@@ -55,10 +66,10 @@ int table_all_instr::rnd_next(void)
{
switch (m_pos.m_index_1) {
case pos_all_instr::VIEW_MUTEX:
- for ( ; m_pos.m_index_2 < mutex_max; m_pos.m_index_2++)
{
- mutex= &mutex_array[m_pos.m_index_2];
- if (mutex->m_lock.is_populated())
+ PFS_mutex_iterator it= global_mutex_container.iterate(m_pos.m_index_2);
+ mutex= it.scan_next(& m_pos.m_index_2);
+ if (mutex != NULL)
{
make_mutex_row(mutex);
m_next_pos.set_after(&m_pos);
@@ -67,10 +78,10 @@ int table_all_instr::rnd_next(void)
}
break;
case pos_all_instr::VIEW_RWLOCK:
- for ( ; m_pos.m_index_2 < rwlock_max; m_pos.m_index_2++)
{
- rwlock= &rwlock_array[m_pos.m_index_2];
- if (rwlock->m_lock.is_populated())
+ PFS_rwlock_iterator it= global_rwlock_container.iterate(m_pos.m_index_2);
+ rwlock= it.scan_next(& m_pos.m_index_2);
+ if (rwlock != NULL)
{
make_rwlock_row(rwlock);
m_next_pos.set_after(&m_pos);
@@ -79,10 +90,10 @@ int table_all_instr::rnd_next(void)
}
break;
case pos_all_instr::VIEW_COND:
- for ( ; m_pos.m_index_2 < cond_max; m_pos.m_index_2++)
{
- cond= &cond_array[m_pos.m_index_2];
- if (cond->m_lock.is_populated())
+ PFS_cond_iterator it= global_cond_container.iterate(m_pos.m_index_2);
+ cond= it.scan_next(& m_pos.m_index_2);
+ if (cond != NULL)
{
make_cond_row(cond);
m_next_pos.set_after(&m_pos);
@@ -91,10 +102,10 @@ int table_all_instr::rnd_next(void)
}
break;
case pos_all_instr::VIEW_FILE:
- for ( ; m_pos.m_index_2 < file_max; m_pos.m_index_2++)
{
- file= &file_array[m_pos.m_index_2];
- if (file->m_lock.is_populated())
+ PFS_file_iterator it= global_file_container.iterate(m_pos.m_index_2);
+ file= it.scan_next(& m_pos.m_index_2);
+ if (file != NULL)
{
make_file_row(file);
m_next_pos.set_after(&m_pos);
@@ -103,10 +114,10 @@ int table_all_instr::rnd_next(void)
}
break;
case pos_all_instr::VIEW_SOCKET:
- for ( ; m_pos.m_index_2 < socket_max; m_pos.m_index_2++)
{
- socket= &socket_array[m_pos.m_index_2];
- if (socket->m_lock.is_populated())
+ PFS_socket_iterator it= global_socket_container.iterate(m_pos.m_index_2);
+ socket= it.scan_next(& m_pos.m_index_2);
+ if (socket != NULL)
{
make_socket_row(socket);
m_next_pos.set_after(&m_pos);
@@ -132,45 +143,40 @@ int table_all_instr::rnd_pos(const void *pos)
switch (m_pos.m_index_1) {
case pos_all_instr::VIEW_MUTEX:
- DBUG_ASSERT(m_pos.m_index_2 < mutex_max);
- mutex= &mutex_array[m_pos.m_index_2];
- if (mutex->m_lock.is_populated())
+ mutex= global_mutex_container.get(m_pos.m_index_2);
+ if (mutex != NULL)
{
make_mutex_row(mutex);
return 0;
}
break;
case pos_all_instr::VIEW_RWLOCK:
- DBUG_ASSERT(m_pos.m_index_2 < rwlock_max);
- rwlock= &rwlock_array[m_pos.m_index_2];
- if (rwlock->m_lock.is_populated())
+ rwlock= global_rwlock_container.get(m_pos.m_index_2);
+ if (rwlock != NULL)
{
make_rwlock_row(rwlock);
return 0;
}
break;
case pos_all_instr::VIEW_COND:
- DBUG_ASSERT(m_pos.m_index_2 < cond_max);
- cond= &cond_array[m_pos.m_index_2];
- if (cond->m_lock.is_populated())
+ cond= global_cond_container.get(m_pos.m_index_2);
+ if (cond != NULL)
{
make_cond_row(cond);
return 0;
}
break;
case pos_all_instr::VIEW_FILE:
- DBUG_ASSERT(m_pos.m_index_2 < file_max);
- file= &file_array[m_pos.m_index_2];
- if (file->m_lock.is_populated())
+ file= global_file_container.get(m_pos.m_index_2);
+ if (file != NULL)
{
make_file_row(file);
return 0;
}
break;
case pos_all_instr::VIEW_SOCKET:
- DBUG_ASSERT(m_pos.m_index_2 < socket_max);
- socket= &socket_array[m_pos.m_index_2];
- if (socket->m_lock.is_populated())
+ socket= global_socket_container.get(m_pos.m_index_2);
+ if (socket != NULL)
{
make_socket_row(socket);
return 0;
diff --git a/storage/perfschema/table_all_instr.h b/storage/perfschema/table_all_instr.h
index 072221ba86e..3b5388dfb6e 100644
--- a/storage/perfschema/table_all_instr.h
+++ b/storage/perfschema/table_all_instr.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -74,6 +74,8 @@ struct pos_all_instr : public PFS_double_index,
class table_all_instr : public PFS_engine_table
{
public:
+ static ha_rows get_row_count();
+
virtual int rnd_next();
virtual int rnd_pos(const void *pos);
virtual void reset_position(void);
diff --git a/storage/perfschema/table_esgs_by_account_by_event_name.cc b/storage/perfschema/table_esgs_by_account_by_event_name.cc
index 22e4e0040f1..68b7b2f57e2 100644
--- a/storage/perfschema/table_esgs_by_account_by_event_name.cc
+++ b/storage/perfschema/table_esgs_by_account_by_event_name.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -26,13 +26,15 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_instr_class.h"
#include "pfs_column_types.h"
#include "pfs_column_values.h"
#include "table_esgs_by_account_by_event_name.h"
#include "pfs_global.h"
#include "pfs_visitor.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
THR_LOCK table_esgs_by_account_by_event_name::m_table_lock;
@@ -44,19 +46,19 @@ table_esgs_by_account_by_event_name::m_share=
table_esgs_by_account_by_event_name::create,
NULL, /* write_row */
table_esgs_by_account_by_event_name::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ table_esgs_by_account_by_event_name::get_row_count,
sizeof(pos_esgs_by_account_by_event_name),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE events_stages_summary_by_account_by_event_name("
- "USER CHAR(16) collate utf8_bin default null,"
+ "USER CHAR(" USERNAME_CHAR_LENGTH_STR ") collate utf8_bin default null,"
"HOST CHAR(60) collate utf8_bin default null,"
"EVENT_NAME VARCHAR(128) not null,"
"COUNT_STAR BIGINT unsigned not null,"
"SUM_TIMER_WAIT BIGINT unsigned not null,"
"MIN_TIMER_WAIT BIGINT unsigned not null,"
"AVG_TIMER_WAIT BIGINT unsigned not null,"
- "MAX_TIMER_WAIT BIGINT unsigned not null)") }
+ "MAX_TIMER_WAIT BIGINT unsigned not null)") },
+ false /* perpetual */
};
PFS_engine_table*
@@ -73,6 +75,12 @@ table_esgs_by_account_by_event_name::delete_all_rows(void)
return 0;
}
+ha_rows
+table_esgs_by_account_by_event_name::get_row_count(void)
+{
+ return global_account_container.get_row_count() * stage_class_max;
+}
+
table_esgs_by_account_by_event_name::table_esgs_by_account_by_event_name()
: PFS_engine_table(&m_share, &m_pos),
m_row_exists(false), m_pos(), m_next_pos()
@@ -94,13 +102,14 @@ int table_esgs_by_account_by_event_name::rnd_next(void)
{
PFS_account *account;
PFS_stage_class *stage_class;
+ bool has_more_account= true;
for (m_pos.set_at(&m_next_pos);
- m_pos.has_more_account();
+ has_more_account;
m_pos.next_account())
{
- account= &account_array[m_pos.m_index_1];
- if (account->m_lock.is_populated())
+ account= global_account_container.get(m_pos.m_index_1, & has_more_account);
+ if (account != NULL)
{
stage_class= find_stage_class(m_pos.m_index_2);
if (stage_class)
@@ -122,17 +131,16 @@ table_esgs_by_account_by_event_name::rnd_pos(const void *pos)
PFS_stage_class *stage_class;
set_position(pos);
- DBUG_ASSERT(m_pos.m_index_1 < account_max);
- account= &account_array[m_pos.m_index_1];
- if (! account->m_lock.is_populated())
- return HA_ERR_RECORD_DELETED;
-
- stage_class= find_stage_class(m_pos.m_index_2);
- if (stage_class)
+ account= global_account_container.get(m_pos.m_index_1);
+ if (account != NULL)
{
- make_row(account, stage_class);
- return 0;
+ stage_class= find_stage_class(m_pos.m_index_2);
+ if (stage_class)
+ {
+ make_row(account, stage_class);
+ return 0;
+ }
}
return HA_ERR_RECORD_DELETED;
@@ -141,7 +149,7 @@ table_esgs_by_account_by_event_name::rnd_pos(const void *pos)
void table_esgs_by_account_by_event_name
::make_row(PFS_account *account, PFS_stage_class *klass)
{
- pfs_lock lock;
+ pfs_optimistic_state lock;
m_row_exists= false;
account->m_lock.begin_optimistic_lock(&lock);
@@ -152,7 +160,10 @@ void table_esgs_by_account_by_event_name
m_row.m_event_name.make_row(klass);
PFS_connection_stage_visitor visitor(klass);
- PFS_connection_iterator::visit_account(account, true, & visitor);
+ PFS_connection_iterator::visit_account(account,
+ true, /* threads */
+ false, /* THDs */
+ & visitor);
if (! account->m_lock.end_optimistic_lock(&lock))
return;
diff --git a/storage/perfschema/table_esgs_by_account_by_event_name.h b/storage/perfschema/table_esgs_by_account_by_event_name.h
index ee855d42818..011503aa64b 100644
--- a/storage/perfschema/table_esgs_by_account_by_event_name.h
+++ b/storage/perfschema/table_esgs_by_account_by_event_name.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -57,7 +57,7 @@ struct row_esgs_by_account_by_event_name
/**
Position of a cursor on
PERFORMANCE_SCHEMA.EVENTS_STAGES_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME.
- Index 1 on user@host (0 based)
+ Index 1 on account (0 based)
Index 2 on stage class (1 based)
*/
struct pos_esgs_by_account_by_event_name
@@ -73,9 +73,6 @@ struct pos_esgs_by_account_by_event_name
m_index_2= 1;
}
- inline bool has_more_account(void)
- { return (m_index_1 < account_max); }
-
inline void next_account(void)
{
m_index_1++;
@@ -91,6 +88,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_init(bool scan);
virtual int rnd_next();
diff --git a/storage/perfschema/table_esgs_by_host_by_event_name.cc b/storage/perfschema/table_esgs_by_host_by_event_name.cc
index 86cc2eb1b86..1d3f6126862 100644
--- a/storage/perfschema/table_esgs_by_host_by_event_name.cc
+++ b/storage/perfschema/table_esgs_by_host_by_event_name.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -26,7 +26,7 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_instr_class.h"
#include "pfs_column_types.h"
#include "pfs_column_values.h"
@@ -34,6 +34,8 @@
#include "pfs_global.h"
#include "pfs_account.h"
#include "pfs_visitor.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
THR_LOCK table_esgs_by_host_by_event_name::m_table_lock;
@@ -45,8 +47,7 @@ table_esgs_by_host_by_event_name::m_share=
table_esgs_by_host_by_event_name::create,
NULL, /* write_row */
table_esgs_by_host_by_event_name::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ table_esgs_by_host_by_event_name::get_row_count,
sizeof(pos_esgs_by_host_by_event_name),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE events_stages_summary_by_host_by_event_name("
@@ -56,7 +57,8 @@ table_esgs_by_host_by_event_name::m_share=
"SUM_TIMER_WAIT BIGINT unsigned not null,"
"MIN_TIMER_WAIT BIGINT unsigned not null,"
"AVG_TIMER_WAIT BIGINT unsigned not null,"
- "MAX_TIMER_WAIT BIGINT unsigned not null)") }
+ "MAX_TIMER_WAIT BIGINT unsigned not null)") },
+ false /* perpetual */
};
PFS_engine_table*
@@ -74,6 +76,12 @@ table_esgs_by_host_by_event_name::delete_all_rows(void)
return 0;
}
+ha_rows
+table_esgs_by_host_by_event_name::get_row_count(void)
+{
+ return global_host_container.get_row_count() * stage_class_max;
+}
+
table_esgs_by_host_by_event_name::table_esgs_by_host_by_event_name()
: PFS_engine_table(&m_share, &m_pos),
m_row_exists(false), m_pos(), m_next_pos()
@@ -95,13 +103,14 @@ int table_esgs_by_host_by_event_name::rnd_next(void)
{
PFS_host *host;
PFS_stage_class *stage_class;
+ bool has_more_host= true;
for (m_pos.set_at(&m_next_pos);
- m_pos.has_more_host();
+ has_more_host;
m_pos.next_host())
{
- host= &host_array[m_pos.m_index_1];
- if (host->m_lock.is_populated())
+ host= global_host_container.get(m_pos.m_index_1, & has_more_host);
+ if (host != NULL)
{
stage_class= find_stage_class(m_pos.m_index_2);
if (stage_class)
@@ -123,17 +132,16 @@ table_esgs_by_host_by_event_name::rnd_pos(const void *pos)
PFS_stage_class *stage_class;
set_position(pos);
- DBUG_ASSERT(m_pos.m_index_1 < host_max);
- host= &host_array[m_pos.m_index_1];
- if (! host->m_lock.is_populated())
- return HA_ERR_RECORD_DELETED;
-
- stage_class= find_stage_class(m_pos.m_index_2);
- if (stage_class)
+ host= global_host_container.get(m_pos.m_index_1);
+ if (host != NULL)
{
- make_row(host, stage_class);
- return 0;
+ stage_class= find_stage_class(m_pos.m_index_2);
+ if (stage_class)
+ {
+ make_row(host, stage_class);
+ return 0;
+ }
}
return HA_ERR_RECORD_DELETED;
@@ -142,7 +150,7 @@ table_esgs_by_host_by_event_name::rnd_pos(const void *pos)
void table_esgs_by_host_by_event_name
::make_row(PFS_host *host, PFS_stage_class *klass)
{
- pfs_lock lock;
+ pfs_optimistic_state lock;
m_row_exists= false;
host->m_lock.begin_optimistic_lock(&lock);
@@ -153,7 +161,11 @@ void table_esgs_by_host_by_event_name
m_row.m_event_name.make_row(klass);
PFS_connection_stage_visitor visitor(klass);
- PFS_connection_iterator::visit_host(host, true, true, & visitor);
+ PFS_connection_iterator::visit_host(host,
+ true, /* accounts */
+ true, /* threads */
+ false, /* THDs */
+ & visitor);
if (! host->m_lock.end_optimistic_lock(&lock))
return;
diff --git a/storage/perfschema/table_esgs_by_host_by_event_name.h b/storage/perfschema/table_esgs_by_host_by_event_name.h
index 6042e6396af..14ddbb8b338 100644
--- a/storage/perfschema/table_esgs_by_host_by_event_name.h
+++ b/storage/perfschema/table_esgs_by_host_by_event_name.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -73,9 +73,6 @@ struct pos_esgs_by_host_by_event_name
m_index_2= 1;
}
- inline bool has_more_host(void)
- { return (m_index_1 < host_max); }
-
inline void next_host(void)
{
m_index_1++;
@@ -91,6 +88,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_init(bool scan);
virtual int rnd_next();
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 dfda9702abb..c266bfaf7a6 100644
--- a/storage/perfschema/table_esgs_by_thread_by_event_name.cc
+++ b/storage/perfschema/table_esgs_by_thread_by_event_name.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -26,13 +26,15 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_instr_class.h"
#include "pfs_column_types.h"
#include "pfs_column_values.h"
#include "table_esgs_by_thread_by_event_name.h"
#include "pfs_global.h"
#include "pfs_visitor.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
THR_LOCK table_esgs_by_thread_by_event_name::m_table_lock;
@@ -44,8 +46,7 @@ table_esgs_by_thread_by_event_name::m_share=
table_esgs_by_thread_by_event_name::create,
NULL, /* write_row */
table_esgs_by_thread_by_event_name::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ table_esgs_by_thread_by_event_name::get_row_count,
sizeof(pos_esgs_by_thread_by_event_name),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE events_stages_summary_by_thread_by_event_name("
@@ -55,7 +56,8 @@ table_esgs_by_thread_by_event_name::m_share=
"SUM_TIMER_WAIT BIGINT unsigned not null,"
"MIN_TIMER_WAIT BIGINT unsigned not null,"
"AVG_TIMER_WAIT BIGINT unsigned not null,"
- "MAX_TIMER_WAIT BIGINT unsigned not null)") }
+ "MAX_TIMER_WAIT BIGINT unsigned not null)") },
+ false /* perpetual */
};
PFS_engine_table*
@@ -71,6 +73,12 @@ table_esgs_by_thread_by_event_name::delete_all_rows(void)
return 0;
}
+ha_rows
+table_esgs_by_thread_by_event_name::get_row_count(void)
+{
+ return global_thread_container.get_row_count() * stage_class_max;
+}
+
table_esgs_by_thread_by_event_name::table_esgs_by_thread_by_event_name()
: PFS_engine_table(&m_share, &m_pos),
m_row_exists(false), m_pos(), m_next_pos()
@@ -92,18 +100,14 @@ int table_esgs_by_thread_by_event_name::rnd_next(void)
{
PFS_thread *thread;
PFS_stage_class *stage_class;
+ bool has_more_thread= true;
for (m_pos.set_at(&m_next_pos);
- m_pos.has_more_thread();
+ has_more_thread;
m_pos.next_thread())
{
- thread= &thread_array[m_pos.m_index_1];
-
- /*
- Important note: the thread scan is the outer loop (index 1),
- to minimize the number of calls to atomic operations.
- */
- if (thread->m_lock.is_populated())
+ thread= global_thread_container.get(m_pos.m_index_1, & has_more_thread);
+ if (thread != NULL)
{
stage_class= find_stage_class(m_pos.m_index_2);
if (stage_class)
@@ -125,17 +129,16 @@ table_esgs_by_thread_by_event_name::rnd_pos(const void *pos)
PFS_stage_class *stage_class;
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;
-
- stage_class= find_stage_class(m_pos.m_index_2);
- if (stage_class)
+ thread= global_thread_container.get(m_pos.m_index_1);
+ if (thread != NULL)
{
- make_row(thread, stage_class);
- return 0;
+ stage_class= find_stage_class(m_pos.m_index_2);
+ if (stage_class)
+ {
+ make_row(thread, stage_class);
+ return 0;
+ }
}
return HA_ERR_RECORD_DELETED;
@@ -144,7 +147,7 @@ table_esgs_by_thread_by_event_name::rnd_pos(const void *pos)
void table_esgs_by_thread_by_event_name
::make_row(PFS_thread *thread, PFS_stage_class *klass)
{
- pfs_lock lock;
+ pfs_optimistic_state lock;
m_row_exists= false;
/* Protect this reader against a thread termination */
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 6ff677a95e2..d3798e419b6 100644
--- a/storage/perfschema/table_esgs_by_thread_by_event_name.h
+++ b/storage/perfschema/table_esgs_by_thread_by_event_name.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -72,9 +72,6 @@ struct pos_esgs_by_thread_by_event_name
m_index_2= 1;
}
- inline bool has_more_thread(void)
- { return (m_index_1 < thread_max); }
-
inline void next_thread(void)
{
m_index_1++;
@@ -95,6 +92,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_init(bool scan);
virtual int rnd_next();
diff --git a/storage/perfschema/table_esgs_by_user_by_event_name.cc b/storage/perfschema/table_esgs_by_user_by_event_name.cc
index af73c1fc5fd..e6e6c321888 100644
--- a/storage/perfschema/table_esgs_by_user_by_event_name.cc
+++ b/storage/perfschema/table_esgs_by_user_by_event_name.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -26,14 +26,15 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_instr_class.h"
#include "pfs_column_types.h"
#include "pfs_column_values.h"
#include "table_esgs_by_user_by_event_name.h"
#include "pfs_global.h"
-#include "pfs_account.h"
#include "pfs_visitor.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
THR_LOCK table_esgs_by_user_by_event_name::m_table_lock;
@@ -45,18 +46,18 @@ table_esgs_by_user_by_event_name::m_share=
table_esgs_by_user_by_event_name::create,
NULL, /* write_row */
table_esgs_by_user_by_event_name::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ table_esgs_by_user_by_event_name::get_row_count,
sizeof(pos_esgs_by_user_by_event_name),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE events_stages_summary_by_user_by_event_name("
- "USER CHAR(16) collate utf8_bin default null,"
+ "USER CHAR(" USERNAME_CHAR_LENGTH_STR ") collate utf8_bin default null,"
"EVENT_NAME VARCHAR(128) not null,"
"COUNT_STAR BIGINT unsigned not null,"
"SUM_TIMER_WAIT BIGINT unsigned not null,"
"MIN_TIMER_WAIT BIGINT unsigned not null,"
"AVG_TIMER_WAIT BIGINT unsigned not null,"
- "MAX_TIMER_WAIT BIGINT unsigned not null)") }
+ "MAX_TIMER_WAIT BIGINT unsigned not null)") },
+ false /* perpetual */
};
PFS_engine_table*
@@ -74,6 +75,12 @@ table_esgs_by_user_by_event_name::delete_all_rows(void)
return 0;
}
+ha_rows
+table_esgs_by_user_by_event_name::get_row_count(void)
+{
+ return global_user_container.get_row_count() * stage_class_max;
+}
+
table_esgs_by_user_by_event_name::table_esgs_by_user_by_event_name()
: PFS_engine_table(&m_share, &m_pos),
m_row_exists(false), m_pos(), m_next_pos()
@@ -95,13 +102,14 @@ int table_esgs_by_user_by_event_name::rnd_next(void)
{
PFS_user *user;
PFS_stage_class *stage_class;
+ bool has_more_user= true;
for (m_pos.set_at(&m_next_pos);
- m_pos.has_more_user();
+ has_more_user;
m_pos.next_user())
{
- user= &user_array[m_pos.m_index_1];
- if (user->m_lock.is_populated())
+ user= global_user_container.get(m_pos.m_index_1, & has_more_user);
+ if (user != NULL)
{
stage_class= find_stage_class(m_pos.m_index_2);
if (stage_class)
@@ -123,17 +131,16 @@ table_esgs_by_user_by_event_name::rnd_pos(const void *pos)
PFS_stage_class *stage_class;
set_position(pos);
- DBUG_ASSERT(m_pos.m_index_1 < user_max);
- user= &user_array[m_pos.m_index_1];
- if (! user->m_lock.is_populated())
- return HA_ERR_RECORD_DELETED;
-
- stage_class= find_stage_class(m_pos.m_index_2);
- if (stage_class)
+ user= global_user_container.get(m_pos.m_index_1);
+ if (user != NULL)
{
- make_row(user, stage_class);
- return 0;
+ stage_class= find_stage_class(m_pos.m_index_2);
+ if (stage_class)
+ {
+ make_row(user, stage_class);
+ return 0;
+ }
}
return HA_ERR_RECORD_DELETED;
@@ -142,7 +149,7 @@ table_esgs_by_user_by_event_name::rnd_pos(const void *pos)
void table_esgs_by_user_by_event_name
::make_row(PFS_user *user, PFS_stage_class *klass)
{
- pfs_lock lock;
+ pfs_optimistic_state lock;
m_row_exists= false;
user->m_lock.begin_optimistic_lock(&lock);
@@ -153,7 +160,11 @@ void table_esgs_by_user_by_event_name
m_row.m_event_name.make_row(klass);
PFS_connection_stage_visitor visitor(klass);
- PFS_connection_iterator::visit_user(user, true, true, & visitor);
+ PFS_connection_iterator::visit_user(user,
+ true, /* accounts */
+ true, /* threads */
+ false, /* THDs */
+ & visitor);
if (! user->m_lock.end_optimistic_lock(&lock))
return;
diff --git a/storage/perfschema/table_esgs_by_user_by_event_name.h b/storage/perfschema/table_esgs_by_user_by_event_name.h
index bc545c2438a..464165a068a 100644
--- a/storage/perfschema/table_esgs_by_user_by_event_name.h
+++ b/storage/perfschema/table_esgs_by_user_by_event_name.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -73,9 +73,6 @@ struct pos_esgs_by_user_by_event_name
m_index_2= 1;
}
- inline bool has_more_user(void)
- { return (m_index_1 < user_max); }
-
inline void next_user(void)
{
m_index_1++;
@@ -96,6 +93,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_init(bool scan);
virtual int rnd_next();
diff --git a/storage/perfschema/table_esgs_global_by_event_name.cc b/storage/perfschema/table_esgs_global_by_event_name.cc
index 6c5f0866671..71145844f9d 100644
--- a/storage/perfschema/table_esgs_global_by_event_name.cc
+++ b/storage/perfschema/table_esgs_global_by_event_name.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -26,7 +26,7 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_instr_class.h"
#include "pfs_column_types.h"
#include "pfs_column_values.h"
@@ -35,6 +35,7 @@
#include "pfs_instr.h"
#include "pfs_timer.h"
#include "pfs_visitor.h"
+#include "field.h"
THR_LOCK table_esgs_global_by_event_name::m_table_lock;
@@ -46,8 +47,7 @@ table_esgs_global_by_event_name::m_share=
table_esgs_global_by_event_name::create,
NULL, /* write_row */
table_esgs_global_by_event_name::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ table_esgs_global_by_event_name::get_row_count,
sizeof(PFS_simple_index),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE events_stages_summary_global_by_event_name("
@@ -56,7 +56,8 @@ table_esgs_global_by_event_name::m_share=
"SUM_TIMER_WAIT BIGINT unsigned not null,"
"MIN_TIMER_WAIT BIGINT unsigned not null,"
"AVG_TIMER_WAIT BIGINT unsigned not null,"
- "MAX_TIMER_WAIT BIGINT unsigned not null)") }
+ "MAX_TIMER_WAIT BIGINT unsigned not null)") },
+ false /* perpetual */
};
PFS_engine_table*
@@ -76,6 +77,12 @@ table_esgs_global_by_event_name::delete_all_rows(void)
return 0;
}
+ha_rows
+table_esgs_global_by_event_name::get_row_count(void)
+{
+ return stage_class_max;
+}
+
table_esgs_global_by_event_name::table_esgs_global_by_event_name()
: PFS_engine_table(&m_share, &m_pos),
m_row_exists(false), m_pos(1), m_next_pos(1)
@@ -140,9 +147,12 @@ void table_esgs_global_by_event_name
m_row.m_event_name.make_row(klass);
PFS_connection_stage_visitor visitor(klass);
- PFS_connection_iterator::visit_global(true, /* hosts */
+ PFS_connection_iterator::visit_global(true, /* hosts */
false, /* users */
- true, true, & visitor);
+ true, /* accounts */
+ true, /* threads */
+ false, /* THDs */
+ & visitor);
m_row.m_stat.set(m_normalizer, & visitor.m_stat);
m_row_exists= true;
diff --git a/storage/perfschema/table_esgs_global_by_event_name.h b/storage/perfschema/table_esgs_global_by_event_name.h
index b8884355676..44b3ea5ce7b 100644
--- a/storage/perfschema/table_esgs_global_by_event_name.h
+++ b/storage/perfschema/table_esgs_global_by_event_name.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -59,6 +59,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_init(bool scan);
virtual int rnd_next();
diff --git a/storage/perfschema/table_esms_by_account_by_event_name.cc b/storage/perfschema/table_esms_by_account_by_event_name.cc
index 7afdabcbbfe..09b872e8ecb 100644
--- a/storage/perfschema/table_esms_by_account_by_event_name.cc
+++ b/storage/perfschema/table_esms_by_account_by_event_name.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -26,13 +26,15 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_instr_class.h"
#include "pfs_column_types.h"
#include "pfs_column_values.h"
#include "table_esms_by_account_by_event_name.h"
#include "pfs_global.h"
#include "pfs_visitor.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
THR_LOCK table_esms_by_account_by_event_name::m_table_lock;
@@ -44,12 +46,11 @@ table_esms_by_account_by_event_name::m_share=
table_esms_by_account_by_event_name::create,
NULL, /* write_row */
table_esms_by_account_by_event_name::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ table_esms_by_account_by_event_name::get_row_count,
sizeof(pos_esms_by_account_by_event_name),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE events_statements_summary_by_account_by_event_name("
- "USER CHAR(16) collate utf8_bin default null,"
+ "USER CHAR(" USERNAME_CHAR_LENGTH_STR ") collate utf8_bin default null,"
"HOST CHAR(60) collate utf8_bin default null,"
"EVENT_NAME VARCHAR(128) not null,"
"COUNT_STAR BIGINT unsigned not null,"
@@ -75,7 +76,8 @@ table_esms_by_account_by_event_name::m_share=
"SUM_SORT_ROWS BIGINT unsigned not null,"
"SUM_SORT_SCAN BIGINT unsigned not null,"
"SUM_NO_INDEX_USED BIGINT unsigned not null,"
- "SUM_NO_GOOD_INDEX_USED BIGINT unsigned not null)") }
+ "SUM_NO_GOOD_INDEX_USED BIGINT unsigned not null)") },
+ false /* perpetual */
};
PFS_engine_table*
@@ -92,6 +94,12 @@ table_esms_by_account_by_event_name::delete_all_rows(void)
return 0;
}
+ha_rows
+table_esms_by_account_by_event_name::get_row_count(void)
+{
+ return global_account_container.get_row_count() * statement_class_max;
+}
+
table_esms_by_account_by_event_name::table_esms_by_account_by_event_name()
: PFS_engine_table(&m_share, &m_pos),
m_row_exists(false), m_pos(), m_next_pos()
@@ -113,13 +121,14 @@ int table_esms_by_account_by_event_name::rnd_next(void)
{
PFS_account *account;
PFS_statement_class *statement_class;
+ bool has_more_account= true;
for (m_pos.set_at(&m_next_pos);
- m_pos.has_more_account();
+ has_more_account;
m_pos.next_account())
{
- account= &account_array[m_pos.m_index_1];
- if (account->m_lock.is_populated())
+ account= global_account_container.get(m_pos.m_index_1, & has_more_account);
+ if (account != NULL)
{
statement_class= find_statement_class(m_pos.m_index_2);
if (statement_class)
@@ -141,17 +150,16 @@ table_esms_by_account_by_event_name::rnd_pos(const void *pos)
PFS_statement_class *statement_class;
set_position(pos);
- DBUG_ASSERT(m_pos.m_index_1 < account_max);
- account= &account_array[m_pos.m_index_1];
- if (! account->m_lock.is_populated())
- return HA_ERR_RECORD_DELETED;
-
- statement_class= find_statement_class(m_pos.m_index_2);
- if (statement_class)
+ account= global_account_container.get(m_pos.m_index_1);
+ if (account != NULL)
{
- make_row(account, statement_class);
- return 0;
+ statement_class= find_statement_class(m_pos.m_index_2);
+ if (statement_class)
+ {
+ make_row(account, statement_class);
+ return 0;
+ }
}
return HA_ERR_RECORD_DELETED;
@@ -160,7 +168,7 @@ table_esms_by_account_by_event_name::rnd_pos(const void *pos)
void table_esms_by_account_by_event_name
::make_row(PFS_account *account, PFS_statement_class *klass)
{
- pfs_lock lock;
+ pfs_optimistic_state lock;
m_row_exists= false;
if (klass->is_mutable())
@@ -174,7 +182,10 @@ void table_esms_by_account_by_event_name
m_row.m_event_name.make_row(klass);
PFS_connection_statement_visitor visitor(klass);
- PFS_connection_iterator::visit_account(account, true, & visitor);
+ PFS_connection_iterator::visit_account(account,
+ true, /* threads */
+ false, /* THDs */
+ & visitor);
if (! account->m_lock.end_optimistic_lock(&lock))
return;
diff --git a/storage/perfschema/table_esms_by_account_by_event_name.h b/storage/perfschema/table_esms_by_account_by_event_name.h
index 64f2053cff6..3881dd5d978 100644
--- a/storage/perfschema/table_esms_by_account_by_event_name.h
+++ b/storage/perfschema/table_esms_by_account_by_event_name.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -57,7 +57,7 @@ struct row_esms_by_account_by_event_name
/**
Position of a cursor on
PERFORMANCE_SCHEMA.EVENTS_STATEMENTS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME.
- Index 1 on user@host (0 based)
+ Index 1 on account (0 based)
Index 2 on statement class (1 based)
*/
struct pos_esms_by_account_by_event_name
@@ -73,9 +73,6 @@ struct pos_esms_by_account_by_event_name
m_index_2= 1;
}
- inline bool has_more_account(void)
- { return (m_index_1 < account_max); }
-
inline void next_account(void)
{
m_index_1++;
@@ -91,6 +88,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_init(bool scan);
virtual int rnd_next();
diff --git a/storage/perfschema/table_esms_by_digest.cc b/storage/perfschema/table_esms_by_digest.cc
index 5295c29dc40..acb9e059711 100644
--- a/storage/perfschema/table_esms_by_digest.cc
+++ b/storage/perfschema/table_esms_by_digest.cc
@@ -26,7 +26,7 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_instr_class.h"
#include "pfs_column_types.h"
#include "pfs_column_values.h"
@@ -37,6 +37,7 @@
#include "pfs_visitor.h"
#include "table_esms_by_digest.h"
#include "pfs_digest.h"
+#include "field.h"
THR_LOCK table_esms_by_digest::m_table_lock;
@@ -48,8 +49,7 @@ table_esms_by_digest::m_share=
table_esms_by_digest::create,
NULL, /* write_row */
table_esms_by_digest::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ table_esms_by_digest::get_row_count,
sizeof(PFS_simple_index),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE events_statements_summary_by_digest("
@@ -81,7 +81,8 @@ table_esms_by_digest::m_share=
"SUM_NO_INDEX_USED BIGINT unsigned not null,"
"SUM_NO_GOOD_INDEX_USED BIGINT unsigned not null,"
"FIRST_SEEN TIMESTAMP(0) NOT NULL default 0,"
- "LAST_SEEN TIMESTAMP(0) NOT NULL default 0)") }
+ "LAST_SEEN TIMESTAMP(0) NOT NULL default 0)") },
+ false /* perpetual */
};
PFS_engine_table*
@@ -97,6 +98,12 @@ table_esms_by_digest::delete_all_rows(void)
return 0;
}
+ha_rows
+table_esms_by_digest::get_row_count(void)
+{
+ return digest_max;
+}
+
table_esms_by_digest::table_esms_by_digest()
: PFS_engine_table(&m_share, &m_pos),
m_row_exists(false), m_pos(0), m_next_pos(0)
@@ -183,7 +190,7 @@ int table_esms_by_digest
if (unlikely(! m_row_exists))
return HA_ERR_RECORD_DELETED;
- /*
+ /*
Set the null bits. It indicates how many fields could be null
in the table.
*/
diff --git a/storage/perfschema/table_esms_by_digest.h b/storage/perfschema/table_esms_by_digest.h
index 903b86110f6..9aa005bb6cc 100644
--- a/storage/perfschema/table_esms_by_digest.h
+++ b/storage/perfschema/table_esms_by_digest.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -62,6 +62,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_next();
virtual int rnd_pos(const void *pos);
diff --git a/storage/perfschema/table_esms_by_host_by_event_name.cc b/storage/perfschema/table_esms_by_host_by_event_name.cc
index 42629ab6c09..c77f5f1320f 100644
--- a/storage/perfschema/table_esms_by_host_by_event_name.cc
+++ b/storage/perfschema/table_esms_by_host_by_event_name.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -26,7 +26,7 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_instr_class.h"
#include "pfs_column_types.h"
#include "pfs_column_values.h"
@@ -34,6 +34,8 @@
#include "pfs_global.h"
#include "pfs_account.h"
#include "pfs_visitor.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
THR_LOCK table_esms_by_host_by_event_name::m_table_lock;
@@ -45,8 +47,7 @@ table_esms_by_host_by_event_name::m_share=
table_esms_by_host_by_event_name::create,
NULL, /* write_row */
table_esms_by_host_by_event_name::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ table_esms_by_host_by_event_name::get_row_count,
sizeof(pos_esms_by_host_by_event_name),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE events_statements_summary_by_host_by_event_name("
@@ -75,7 +76,8 @@ table_esms_by_host_by_event_name::m_share=
"SUM_SORT_ROWS BIGINT unsigned not null,"
"SUM_SORT_SCAN BIGINT unsigned not null,"
"SUM_NO_INDEX_USED BIGINT unsigned not null,"
- "SUM_NO_GOOD_INDEX_USED BIGINT unsigned not null)") }
+ "SUM_NO_GOOD_INDEX_USED BIGINT unsigned not null)") },
+ false /* perpetual */
};
PFS_engine_table*
@@ -93,6 +95,12 @@ table_esms_by_host_by_event_name::delete_all_rows(void)
return 0;
}
+ha_rows
+table_esms_by_host_by_event_name::get_row_count(void)
+{
+ return global_host_container.get_row_count() * statement_class_max;
+}
+
table_esms_by_host_by_event_name::table_esms_by_host_by_event_name()
: PFS_engine_table(&m_share, &m_pos),
m_row_exists(false), m_pos(), m_next_pos()
@@ -114,13 +122,14 @@ int table_esms_by_host_by_event_name::rnd_next(void)
{
PFS_host *host;
PFS_statement_class *statement_class;
+ bool has_more_host= true;
for (m_pos.set_at(&m_next_pos);
- m_pos.has_more_host();
+ has_more_host;
m_pos.next_host())
{
- host= &host_array[m_pos.m_index_1];
- if (host->m_lock.is_populated())
+ host= global_host_container.get(m_pos.m_index_1, & has_more_host);
+ if (host != NULL)
{
statement_class= find_statement_class(m_pos.m_index_2);
if (statement_class)
@@ -142,17 +151,16 @@ table_esms_by_host_by_event_name::rnd_pos(const void *pos)
PFS_statement_class *statement_class;
set_position(pos);
- DBUG_ASSERT(m_pos.m_index_1 < host_max);
- host= &host_array[m_pos.m_index_1];
- if (! host->m_lock.is_populated())
- return HA_ERR_RECORD_DELETED;
-
- statement_class= find_statement_class(m_pos.m_index_2);
- if (statement_class)
+ host= global_host_container.get(m_pos.m_index_1);
+ if (host != NULL)
{
- make_row(host, statement_class);
- return 0;
+ statement_class= find_statement_class(m_pos.m_index_2);
+ if (statement_class)
+ {
+ make_row(host, statement_class);
+ return 0;
+ }
}
return HA_ERR_RECORD_DELETED;
@@ -161,7 +169,7 @@ table_esms_by_host_by_event_name::rnd_pos(const void *pos)
void table_esms_by_host_by_event_name
::make_row(PFS_host *host, PFS_statement_class *klass)
{
- pfs_lock lock;
+ pfs_optimistic_state lock;
m_row_exists= false;
if (klass->is_mutable())
@@ -175,7 +183,11 @@ void table_esms_by_host_by_event_name
m_row.m_event_name.make_row(klass);
PFS_connection_statement_visitor visitor(klass);
- PFS_connection_iterator::visit_host(host, true, true, & visitor);
+ PFS_connection_iterator::visit_host(host,
+ true, /* accounts */
+ true, /* threads */
+ false, /* THDs */
+ & visitor);
if (! host->m_lock.end_optimistic_lock(&lock))
return;
diff --git a/storage/perfschema/table_esms_by_host_by_event_name.h b/storage/perfschema/table_esms_by_host_by_event_name.h
index a6985b48149..807db6d48d3 100644
--- a/storage/perfschema/table_esms_by_host_by_event_name.h
+++ b/storage/perfschema/table_esms_by_host_by_event_name.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -73,9 +73,6 @@ struct pos_esms_by_host_by_event_name
m_index_2= 1;
}
- inline bool has_more_host(void)
- { return (m_index_1 < host_max); }
-
inline void next_host(void)
{
m_index_1++;
@@ -91,6 +88,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_init(bool scan);
virtual int rnd_next();
diff --git a/storage/perfschema/table_esms_by_program.cc b/storage/perfschema/table_esms_by_program.cc
new file mode 100644
index 00000000000..3cb2e4a4d46
--- /dev/null
+++ b/storage/perfschema/table_esms_by_program.cc
@@ -0,0 +1,245 @@
+/* Copyright (c) 2010, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+
+/**
+ @file storage/perfschema/table_esms_by_program.cc
+ Table EVENTS_STATEMENTS_SUMMARY_BY_PROGRAM (implementation).
+*/
+
+#include "my_global.h"
+#include "my_thread.h"
+#include "pfs_instr_class.h"
+#include "pfs_column_types.h"
+#include "pfs_column_values.h"
+#include "pfs_global.h"
+#include "pfs_instr.h"
+#include "pfs_timer.h"
+#include "pfs_visitor.h"
+#include "pfs_program.h"
+#include "table_esms_by_program.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
+
+THR_LOCK table_esms_by_program::m_table_lock;
+
+PFS_engine_table_share
+table_esms_by_program::m_share=
+{
+ { C_STRING_WITH_LEN("events_statements_summary_by_program") },
+ &pfs_truncatable_acl,
+ table_esms_by_program::create,
+ NULL, /* write_row */
+ table_esms_by_program::delete_all_rows,
+ table_esms_by_program::get_row_count,
+ sizeof(PFS_simple_index),
+ &m_table_lock,
+ { C_STRING_WITH_LEN("CREATE TABLE events_statements_summary_by_program ("
+ "OBJECT_TYPE enum('EVENT', 'FUNCTION', 'PROCEDURE', 'TABLE', 'TRIGGER'),"
+ "OBJECT_SCHEMA varchar(64) NOT NULL,"
+ "OBJECT_NAME varchar(64) NOT NULL,"
+ "COUNT_STAR bigint(20) unsigned NOT NULL,"
+ "SUM_TIMER_WAIT bigint(20) unsigned NOT NULL,"
+ "MIN_TIMER_WAIT bigint(20) unsigned NOT NULL,"
+ "AVG_TIMER_WAIT bigint(20) unsigned NOT NULL,"
+ "MAX_TIMER_WAIT bigint(20) unsigned NOT NULL,"
+ "COUNT_STATEMENTS bigint(20) unsigned NOT NULL,"
+ "SUM_STATEMENTS_WAIT bigint(20) unsigned NOT NULL,"
+ "MIN_STATEMENTS_WAIT bigint(20) unsigned NOT NULL,"
+ "AVG_STATEMENTS_WAIT bigint(20) unsigned NOT NULL,"
+ "MAX_STATEMENTS_WAIT bigint(20) unsigned NOT NULL,"
+ "SUM_LOCK_TIME bigint(20) unsigned NOT NULL,"
+ "SUM_ERRORS bigint(20) unsigned NOT NULL,"
+ "SUM_WARNINGS bigint(20) unsigned NOT NULL,"
+ "SUM_ROWS_AFFECTED bigint(20) unsigned NOT NULL,"
+ "SUM_ROWS_SENT bigint(20) unsigned NOT NULL,"
+ "SUM_ROWS_EXAMINED bigint(20) unsigned NOT NULL,"
+ "SUM_CREATED_TMP_DISK_TABLES bigint(20) unsigned NOT NULL,"
+ "SUM_CREATED_TMP_TABLES bigint(20) unsigned NOT NULL,"
+ "SUM_SELECT_FULL_JOIN bigint(20) unsigned NOT NULL,"
+ "SUM_SELECT_FULL_RANGE_JOIN bigint(20) unsigned NOT NULL,"
+ "SUM_SELECT_RANGE bigint(20) unsigned NOT NULL,"
+ "SUM_SELECT_RANGE_CHECK bigint(20) unsigned NOT NULL,"
+ "SUM_SELECT_SCAN bigint(20) unsigned NOT NULL,"
+ "SUM_SORT_MERGE_PASSES bigint(20) unsigned NOT NULL,"
+ "SUM_SORT_RANGE bigint(20) unsigned NOT NULL,"
+ "SUM_SORT_ROWS bigint(20) unsigned NOT NULL,"
+ "SUM_SORT_SCAN bigint(20) unsigned NOT NULL,"
+ "SUM_NO_INDEX_USED bigint(20) unsigned NOT NULL,"
+ "SUM_NO_GOOD_INDEX_USED bigint(20) unsigned NOT NULL)")},
+ false /* perpetual */
+};
+
+PFS_engine_table*
+table_esms_by_program::create(void)
+{
+ return new table_esms_by_program();
+}
+
+int
+table_esms_by_program::delete_all_rows(void)
+{
+ reset_esms_by_program();
+ return 0;
+}
+
+ha_rows
+table_esms_by_program::get_row_count(void)
+{
+ return global_program_container.get_row_count();
+}
+
+table_esms_by_program::table_esms_by_program()
+ : PFS_engine_table(&m_share, &m_pos),
+ m_row_exists(false), m_pos(0), m_next_pos(0)
+{}
+
+void table_esms_by_program::reset_position(void)
+{
+ m_pos= 0;
+ m_next_pos= 0;
+}
+
+int table_esms_by_program::rnd_next(void)
+{
+ PFS_program* pfs;
+
+ m_pos.set_at(&m_next_pos);
+ PFS_program_iterator it= global_program_container.iterate(m_pos.m_index);
+ pfs= it.scan_next(& m_pos.m_index);
+ if (pfs != NULL)
+ {
+ make_row(pfs);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+
+ return HA_ERR_END_OF_FILE;
+}
+
+int
+table_esms_by_program::rnd_pos(const void *pos)
+{
+ PFS_program* pfs;
+
+ set_position(pos);
+
+ pfs= global_program_container.get(m_pos.m_index);
+ if (pfs != NULL)
+ {
+ make_row(pfs);
+ return 0;
+ }
+
+ return HA_ERR_RECORD_DELETED;
+}
+
+
+void table_esms_by_program::make_row(PFS_program* program)
+{
+ pfs_optimistic_state lock;
+ m_row_exists= false;
+
+ program->m_lock.begin_optimistic_lock(&lock);
+
+ m_row.m_object_type= program->m_type;
+
+ m_row.m_object_name_length= program->m_object_name_length;
+ if(m_row.m_object_name_length > 0)
+ memcpy(m_row.m_object_name, program->m_object_name,
+ m_row.m_object_name_length);
+
+ m_row.m_schema_name_length= program->m_schema_name_length;
+ if(m_row.m_schema_name_length > 0)
+ memcpy(m_row.m_schema_name, program->m_schema_name,
+ m_row.m_schema_name_length);
+
+ time_normalizer *normalizer= time_normalizer::get(statement_timer);
+ /* Get stored program's over all stats. */
+ m_row.m_sp_stat.set(normalizer, &program->m_sp_stat);
+ /* Get sub statements' stats. */
+ m_row.m_stmt_stat.set(normalizer, & program->m_stmt_stat);
+
+ if (! program->m_lock.end_optimistic_lock(&lock))
+ return;
+
+ m_row_exists= true;
+}
+
+int table_esms_by_program
+::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. It indicates how many fields could be null
+ in the table.
+ */
+ 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 0: /* OBJECT_TYPE */
+ if(m_row.m_object_type != 0)
+ set_field_enum(f, m_row.m_object_type);
+ else
+ f->set_null();
+ break;
+ case 1: /* OBJECT_SCHEMA */
+ if(m_row.m_schema_name_length > 0)
+ set_field_varchar_utf8(f, m_row.m_schema_name,
+ m_row.m_schema_name_length);
+ else
+ f->set_null();
+ break;
+ case 2: /* OBJECT_NAME */
+ if(m_row.m_object_name_length > 0)
+ set_field_varchar_utf8(f, m_row.m_object_name,
+ m_row.m_object_name_length);
+ else
+ f->set_null();
+ break;
+ case 3: /* COUNT_STAR */
+ case 4: /* SUM_TIMER_WAIT */
+ case 5: /* MIN_TIMER_WAIT */
+ case 6: /* AVG_TIMER_WAIT */
+ case 7: /* MAX_TIMER_WAIT */
+ m_row.m_sp_stat.set_field(f->field_index - 3, f);
+ break;
+ default: /* 8, ... COUNT/SUM/MIN/AVG/MAX */
+ m_row.m_stmt_stat.set_field(f->field_index - 8, f);
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
diff --git a/storage/perfschema/table_esms_by_program.h b/storage/perfschema/table_esms_by_program.h
new file mode 100644
index 00000000000..cc263878e28
--- /dev/null
+++ b/storage/perfschema/table_esms_by_program.h
@@ -0,0 +1,113 @@
+/* Copyright (c) 2013, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+
+#ifndef TABLE_ESMS_BY_PROGRAM_H
+#define TABLE_ESMS_BY_PROGRAM_H
+
+/**
+ @file storage/perfschema/table_esms_by_program.h
+ Table EVENTS_STATEMENTS_SUMMARY_BY_PROGRAM (declarations).
+*/
+
+#include "table_helper.h"
+#include "pfs_program.h"
+
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+/**
+ A row of table
+ PERFORMANCE_SCHEMA.EVENTS_STATEMENTS_SUMMARY_BY_PROGRAM.
+*/
+struct row_esms_by_program
+{
+ /** Column OBJECT_TYPE. */
+ enum_object_type m_object_type;
+ /** Column OBJECT_SCHEMA. */
+ char m_schema_name[COL_OBJECT_SCHEMA_SIZE];
+ int m_schema_name_length;
+ /** Column OBJECT_NAME. */
+ char m_object_name[COL_OBJECT_NAME_SIZE];
+ int m_object_name_length;
+
+ /**
+ Columns COUNT_STAR
+ SUM_TIMER_WAIT
+ MIN_TIMER_WAIT
+ AVG_TIMER_WAIT
+ MAX_TIMER_WAIT
+ */
+ PFS_sp_stat_row m_sp_stat;
+
+ /** Columns COUNT_STATEMENTS,SUM_STATEMENTS_WAIT...SUM_NO_GOOD_INDEX_USED. */
+ PFS_statement_stat_row m_stmt_stat;
+};
+
+/** Table PERFORMANCE_SCHEMA.EVENTS_STATEMENTS_SUMMARY_BY_PROGRAM. */
+class table_esms_by_program : public PFS_engine_table
+{
+public:
+ /** Table share */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static int delete_all_rows();
+ static ha_rows get_row_count();
+
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+protected:
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+
+ table_esms_by_program();
+
+public:
+ ~table_esms_by_program()
+ {}
+
+protected:
+ void make_row(PFS_program*);
+
+private:
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /** Fields definition. */
+ static TABLE_FIELD_DEF m_field_def;
+
+ /** Current row. */
+ row_esms_by_program m_row;
+ /** True is the current row exists. */
+ bool m_row_exists;
+ /** Current position. */
+ PFS_simple_index m_pos;
+ /** Next position. */
+ PFS_simple_index m_next_pos;
+};
+
+/** @} */
+#endif
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 0a7cf46986c..306edc769c8 100644
--- a/storage/perfschema/table_esms_by_thread_by_event_name.cc
+++ b/storage/perfschema/table_esms_by_thread_by_event_name.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -26,13 +26,15 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_instr_class.h"
#include "pfs_column_types.h"
#include "pfs_column_values.h"
#include "table_esms_by_thread_by_event_name.h"
#include "pfs_global.h"
#include "pfs_visitor.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
THR_LOCK table_esms_by_thread_by_event_name::m_table_lock;
@@ -44,8 +46,7 @@ table_esms_by_thread_by_event_name::m_share=
table_esms_by_thread_by_event_name::create,
NULL, /* write_row */
table_esms_by_thread_by_event_name::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ table_esms_by_thread_by_event_name::get_row_count,
sizeof(pos_esms_by_thread_by_event_name),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE events_statements_summary_by_thread_by_event_name("
@@ -74,7 +75,8 @@ table_esms_by_thread_by_event_name::m_share=
"SUM_SORT_ROWS BIGINT unsigned not null,"
"SUM_SORT_SCAN BIGINT unsigned not null,"
"SUM_NO_INDEX_USED BIGINT unsigned not null,"
- "SUM_NO_GOOD_INDEX_USED BIGINT unsigned not null)") }
+ "SUM_NO_GOOD_INDEX_USED BIGINT unsigned not null)") },
+ false /* perpetual */
};
PFS_engine_table*
@@ -90,6 +92,12 @@ table_esms_by_thread_by_event_name::delete_all_rows(void)
return 0;
}
+ha_rows
+table_esms_by_thread_by_event_name::get_row_count(void)
+{
+ return global_thread_container.get_row_count() * statement_class_max;
+}
+
table_esms_by_thread_by_event_name::table_esms_by_thread_by_event_name()
: PFS_engine_table(&m_share, &m_pos),
m_row_exists(false), m_pos(), m_next_pos()
@@ -111,18 +119,14 @@ int table_esms_by_thread_by_event_name::rnd_next(void)
{
PFS_thread *thread;
PFS_statement_class *statement_class;
+ bool has_more_thread= true;
for (m_pos.set_at(&m_next_pos);
- m_pos.has_more_thread();
+ has_more_thread;
m_pos.next_thread())
{
- thread= &thread_array[m_pos.m_index_1];
-
- /*
- Important note: the thread scan is the outer loop (index 1),
- to minimize the number of calls to atomic operations.
- */
- if (thread->m_lock.is_populated())
+ thread= global_thread_container.get(m_pos.m_index_1, & has_more_thread);
+ if (thread != NULL)
{
statement_class= find_statement_class(m_pos.m_index_2);
if (statement_class)
@@ -144,17 +148,16 @@ table_esms_by_thread_by_event_name::rnd_pos(const void *pos)
PFS_statement_class *statement_class;
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;
-
- statement_class= find_statement_class(m_pos.m_index_2);
- if (statement_class)
+ thread= global_thread_container.get(m_pos.m_index_1);
+ if (thread != NULL)
{
- make_row(thread, statement_class);
- return 0;
+ statement_class= find_statement_class(m_pos.m_index_2);
+ if (statement_class)
+ {
+ make_row(thread, statement_class);
+ return 0;
+ }
}
return HA_ERR_RECORD_DELETED;
@@ -163,7 +166,7 @@ table_esms_by_thread_by_event_name::rnd_pos(const void *pos)
void table_esms_by_thread_by_event_name
::make_row(PFS_thread *thread, PFS_statement_class *klass)
{
- pfs_lock lock;
+ pfs_optimistic_state lock;
m_row_exists= false;
if (klass->is_mutable())
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 72645d03389..41fec4e10d7 100644
--- a/storage/perfschema/table_esms_by_thread_by_event_name.h
+++ b/storage/perfschema/table_esms_by_thread_by_event_name.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -72,9 +72,6 @@ struct pos_esms_by_thread_by_event_name
m_index_2= 1;
}
- inline bool has_more_thread(void)
- { return (m_index_1 < thread_max); }
-
inline void next_thread(void)
{
m_index_1++;
@@ -95,6 +92,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_init(bool scan);
virtual int rnd_next();
diff --git a/storage/perfschema/table_esms_by_user_by_event_name.cc b/storage/perfschema/table_esms_by_user_by_event_name.cc
index f8708ac9a14..c0517748b99 100644
--- a/storage/perfschema/table_esms_by_user_by_event_name.cc
+++ b/storage/perfschema/table_esms_by_user_by_event_name.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -26,14 +26,15 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_instr_class.h"
#include "pfs_column_types.h"
#include "pfs_column_values.h"
#include "table_esms_by_user_by_event_name.h"
#include "pfs_global.h"
-#include "pfs_account.h"
#include "pfs_visitor.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
THR_LOCK table_esms_by_user_by_event_name::m_table_lock;
@@ -45,12 +46,11 @@ table_esms_by_user_by_event_name::m_share=
table_esms_by_user_by_event_name::create,
NULL, /* write_row */
table_esms_by_user_by_event_name::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ table_esms_by_user_by_event_name::get_row_count,
sizeof(pos_esms_by_user_by_event_name),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE events_statements_summary_by_user_by_event_name("
- "USER CHAR(16) collate utf8_bin default null,"
+ "USER CHAR(" USERNAME_CHAR_LENGTH_STR ") collate utf8_bin default null,"
"EVENT_NAME VARCHAR(128) not null,"
"COUNT_STAR BIGINT unsigned not null,"
"SUM_TIMER_WAIT BIGINT unsigned not null,"
@@ -75,7 +75,8 @@ table_esms_by_user_by_event_name::m_share=
"SUM_SORT_ROWS BIGINT unsigned not null,"
"SUM_SORT_SCAN BIGINT unsigned not null,"
"SUM_NO_INDEX_USED BIGINT unsigned not null,"
- "SUM_NO_GOOD_INDEX_USED BIGINT unsigned not null)") }
+ "SUM_NO_GOOD_INDEX_USED BIGINT unsigned not null)") },
+ false /* perpetual */
};
PFS_engine_table*
@@ -93,6 +94,12 @@ table_esms_by_user_by_event_name::delete_all_rows(void)
return 0;
}
+ha_rows
+table_esms_by_user_by_event_name::get_row_count(void)
+{
+ return global_user_container.get_row_count() * statement_class_max;
+}
+
table_esms_by_user_by_event_name::table_esms_by_user_by_event_name()
: PFS_engine_table(&m_share, &m_pos),
m_row_exists(false), m_pos(), m_next_pos()
@@ -114,13 +121,14 @@ int table_esms_by_user_by_event_name::rnd_next(void)
{
PFS_user *user;
PFS_statement_class *statement_class;
+ bool has_more_user= true;
for (m_pos.set_at(&m_next_pos);
- m_pos.has_more_user();
+ has_more_user;
m_pos.next_user())
{
- user= &user_array[m_pos.m_index_1];
- if (user->m_lock.is_populated())
+ user= global_user_container.get(m_pos.m_index_1, & has_more_user);
+ if (user != NULL)
{
statement_class= find_statement_class(m_pos.m_index_2);
if (statement_class)
@@ -142,17 +150,16 @@ table_esms_by_user_by_event_name::rnd_pos(const void *pos)
PFS_statement_class *statement_class;
set_position(pos);
- DBUG_ASSERT(m_pos.m_index_1 < user_max);
- user= &user_array[m_pos.m_index_1];
- if (! user->m_lock.is_populated())
- return HA_ERR_RECORD_DELETED;
-
- statement_class= find_statement_class(m_pos.m_index_2);
- if (statement_class)
+ user= global_user_container.get(m_pos.m_index_1);
+ if (user != NULL)
{
- make_row(user, statement_class);
- return 0;
+ statement_class= find_statement_class(m_pos.m_index_2);
+ if (statement_class)
+ {
+ make_row(user, statement_class);
+ return 0;
+ }
}
return HA_ERR_RECORD_DELETED;
@@ -161,7 +168,7 @@ table_esms_by_user_by_event_name::rnd_pos(const void *pos)
void table_esms_by_user_by_event_name
::make_row(PFS_user *user, PFS_statement_class *klass)
{
- pfs_lock lock;
+ pfs_optimistic_state lock;
m_row_exists= false;
if (klass->is_mutable())
@@ -175,7 +182,11 @@ void table_esms_by_user_by_event_name
m_row.m_event_name.make_row(klass);
PFS_connection_statement_visitor visitor(klass);
- PFS_connection_iterator::visit_user(user, true, true, & visitor);
+ PFS_connection_iterator::visit_user(user,
+ true, /* accounts */
+ true, /* threads */
+ false, /* THDs */
+ & visitor);
if (! user->m_lock.end_optimistic_lock(&lock))
return;
diff --git a/storage/perfschema/table_esms_by_user_by_event_name.h b/storage/perfschema/table_esms_by_user_by_event_name.h
index d1d1e5df85d..0ed9899dcf5 100644
--- a/storage/perfschema/table_esms_by_user_by_event_name.h
+++ b/storage/perfschema/table_esms_by_user_by_event_name.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -73,9 +73,6 @@ struct pos_esms_by_user_by_event_name
m_index_2= 1;
}
- inline bool has_more_user(void)
- { return (m_index_1 < user_max); }
-
inline void next_user(void)
{
m_index_1++;
@@ -91,6 +88,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_init(bool scan);
virtual int rnd_next();
diff --git a/storage/perfschema/table_esms_global_by_event_name.cc b/storage/perfschema/table_esms_global_by_event_name.cc
index 7d9584752b0..6e2408be26a 100644
--- a/storage/perfschema/table_esms_global_by_event_name.cc
+++ b/storage/perfschema/table_esms_global_by_event_name.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -26,7 +26,7 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_instr_class.h"
#include "pfs_column_types.h"
#include "pfs_column_values.h"
@@ -35,6 +35,7 @@
#include "pfs_instr.h"
#include "pfs_timer.h"
#include "pfs_visitor.h"
+#include "field.h"
THR_LOCK table_esms_global_by_event_name::m_table_lock;
@@ -46,8 +47,7 @@ table_esms_global_by_event_name::m_share=
table_esms_global_by_event_name::create,
NULL, /* write_row */
table_esms_global_by_event_name::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ table_esms_global_by_event_name::get_row_count,
sizeof(PFS_simple_index),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE events_statements_summary_global_by_event_name("
@@ -75,7 +75,8 @@ table_esms_global_by_event_name::m_share=
"SUM_SORT_ROWS BIGINT unsigned not null,"
"SUM_SORT_SCAN BIGINT unsigned not null,"
"SUM_NO_INDEX_USED BIGINT unsigned not null,"
- "SUM_NO_GOOD_INDEX_USED BIGINT unsigned not null)") }
+ "SUM_NO_GOOD_INDEX_USED BIGINT unsigned not null)") },
+ false /* perpetual */
};
PFS_engine_table*
@@ -95,6 +96,12 @@ table_esms_global_by_event_name::delete_all_rows(void)
return 0;
}
+ha_rows
+table_esms_global_by_event_name::get_row_count(void)
+{
+ return statement_class_max;
+}
+
table_esms_global_by_event_name::table_esms_global_by_event_name()
: PFS_engine_table(&m_share, &m_pos),
m_row_exists(false), m_pos(1), m_next_pos(1)
@@ -164,9 +171,12 @@ void table_esms_global_by_event_name
m_row.m_event_name.make_row(klass);
PFS_connection_statement_visitor visitor(klass);
- PFS_connection_iterator::visit_global(true, /* hosts */
+ PFS_connection_iterator::visit_global(true, /* hosts */
false, /* users */
- true, true, & visitor);
+ true, /* accounts */
+ true, /* threads */
+ false, /* THDs */
+ & visitor);
m_row.m_stat.set(m_normalizer, & visitor.m_stat);
m_row_exists= true;
diff --git a/storage/perfschema/table_esms_global_by_event_name.h b/storage/perfschema/table_esms_global_by_event_name.h
index b90c14c0c0f..d4e34b7cc18 100644
--- a/storage/perfschema/table_esms_global_by_event_name.h
+++ b/storage/perfschema/table_esms_global_by_event_name.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -59,6 +59,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_init(bool scan);
virtual int rnd_next();
diff --git a/storage/perfschema/table_ets_by_account_by_event_name.cc b/storage/perfschema/table_ets_by_account_by_event_name.cc
new file mode 100644
index 00000000000..f951be2104a
--- /dev/null
+++ b/storage/perfschema/table_ets_by_account_by_event_name.cc
@@ -0,0 +1,225 @@
+/* Copyright (c) 2010, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+
+/**
+ @file storage/perfschema/table_ets_by_account_by_event_name.cc
+ Table EVENTS_TRANSACTIONS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME (implementation).
+*/
+
+#include "my_global.h"
+#include "my_thread.h"
+#include "pfs_instr_class.h"
+#include "pfs_column_types.h"
+#include "pfs_column_values.h"
+#include "table_ets_by_account_by_event_name.h"
+#include "pfs_global.h"
+#include "pfs_visitor.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
+
+THR_LOCK table_ets_by_account_by_event_name::m_table_lock;
+
+PFS_engine_table_share
+table_ets_by_account_by_event_name::m_share=
+{
+ { C_STRING_WITH_LEN("events_transactions_summary_by_account_by_event_name") },
+ &pfs_truncatable_acl,
+ table_ets_by_account_by_event_name::create,
+ NULL, /* write_row */
+ table_ets_by_account_by_event_name::delete_all_rows,
+ table_ets_by_account_by_event_name::get_row_count,
+ sizeof(pos_ets_by_account_by_event_name),
+ &m_table_lock,
+ { C_STRING_WITH_LEN("CREATE TABLE events_transactions_summary_by_account_by_event_name("
+ "USER CHAR(32) collate utf8_bin default null,"
+ "HOST CHAR(60) collate utf8_bin default null,"
+ "EVENT_NAME VARCHAR(128) not null,"
+ "COUNT_STAR BIGINT unsigned not null,"
+ "SUM_TIMER_WAIT BIGINT unsigned not null,"
+ "MIN_TIMER_WAIT BIGINT unsigned not null,"
+ "AVG_TIMER_WAIT BIGINT unsigned not null,"
+ "MAX_TIMER_WAIT BIGINT unsigned not null,"
+ "COUNT_READ_WRITE BIGINT unsigned not null,"
+ "SUM_TIMER_READ_WRITE BIGINT unsigned not null,"
+ "MIN_TIMER_READ_WRITE BIGINT unsigned not null,"
+ "AVG_TIMER_READ_WRITE BIGINT unsigned not null,"
+ "MAX_TIMER_READ_WRITE BIGINT unsigned not null,"
+ "COUNT_READ_ONLY BIGINT unsigned not null,"
+ "SUM_TIMER_READ_ONLY BIGINT unsigned not null,"
+ "MIN_TIMER_READ_ONLY BIGINT unsigned not null,"
+ "AVG_TIMER_READ_ONLY BIGINT unsigned not null,"
+ "MAX_TIMER_READ_ONLY BIGINT unsigned not null)")},
+ false /* perpetual */
+};
+
+PFS_engine_table*
+table_ets_by_account_by_event_name::create(void)
+{
+ return new table_ets_by_account_by_event_name();
+}
+
+int
+table_ets_by_account_by_event_name::delete_all_rows(void)
+{
+ reset_events_transactions_by_thread();
+ reset_events_transactions_by_account();
+ return 0;
+}
+
+ha_rows
+table_ets_by_account_by_event_name::get_row_count(void)
+{
+ return global_account_container.get_row_count() * transaction_class_max;
+}
+
+table_ets_by_account_by_event_name::table_ets_by_account_by_event_name()
+ : PFS_engine_table(&m_share, &m_pos),
+ m_row_exists(false), m_pos(), m_next_pos()
+{}
+
+void table_ets_by_account_by_event_name::reset_position(void)
+{
+ m_pos.reset();
+ m_next_pos.reset();
+}
+
+int table_ets_by_account_by_event_name::rnd_init(bool scan)
+{
+ m_normalizer= time_normalizer::get(transaction_timer);
+ return 0;
+}
+
+int table_ets_by_account_by_event_name::rnd_next(void)
+{
+ PFS_account *account;
+ PFS_transaction_class *transaction_class;
+ bool has_more_account= true;
+
+ for (m_pos.set_at(&m_next_pos);
+ has_more_account;
+ m_pos.next_account())
+ {
+ account= global_account_container.get(m_pos.m_index_1, & has_more_account);
+ if (account != NULL)
+ {
+ transaction_class= find_transaction_class(m_pos.m_index_2);
+ if (transaction_class)
+ {
+ make_row(account, transaction_class);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+ }
+ }
+
+ return HA_ERR_END_OF_FILE;
+}
+
+int
+table_ets_by_account_by_event_name::rnd_pos(const void *pos)
+{
+ PFS_account *account;
+ PFS_transaction_class *transaction_class;
+
+ set_position(pos);
+
+ account= global_account_container.get(m_pos.m_index_1);
+ if (account != NULL)
+ {
+ transaction_class= find_transaction_class(m_pos.m_index_2);
+ if (transaction_class)
+ {
+ make_row(account, transaction_class);
+ return 0;
+ }
+ }
+
+ return HA_ERR_RECORD_DELETED;
+}
+
+void table_ets_by_account_by_event_name
+::make_row(PFS_account *account, PFS_transaction_class *klass)
+{
+ pfs_optimistic_state lock;
+ m_row_exists= false;
+
+ account->m_lock.begin_optimistic_lock(&lock);
+
+ if (m_row.m_account.make_row(account))
+ return;
+
+ m_row.m_event_name.make_row(klass);
+
+ PFS_connection_transaction_visitor visitor(klass);
+ PFS_connection_iterator::visit_account(account,
+ true, /* threads */
+ false, /* THDs */
+ &visitor);
+
+ if (! account->m_lock.end_optimistic_lock(&lock))
+ return;
+
+ m_row_exists= true;
+ m_row.m_stat.set(m_normalizer, &visitor.m_stat);
+}
+
+int table_ets_by_account_by_event_name
+::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 0: /* USER */
+ case 1: /* HOST */
+ m_row.m_account.set_field(f->field_index, f);
+ break;
+ case 2: /* EVENT_NAME */
+ m_row.m_event_name.set_field(f);
+ break;
+ default:
+ /**
+ COUNT_STAR, SUM/MIN/AVG/MAX_TIMER_WAIT,
+ COUNT_READ_WRITE, SUM/MIN/AVG/MAX_TIMER_READ_WRITE,
+ COUNT_READ_ONLY, SUM/MIN/AVG/MAX_TIMER_READ_ONLY
+ */
+ m_row.m_stat.set_field(f->field_index-3, f);
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
diff --git a/storage/perfschema/table_ets_by_account_by_event_name.h b/storage/perfschema/table_ets_by_account_by_event_name.h
new file mode 100644
index 00000000000..98fb45f79dd
--- /dev/null
+++ b/storage/perfschema/table_ets_by_account_by_event_name.h
@@ -0,0 +1,134 @@
+/* Copyright (c) 2010, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+
+#ifndef TABLE_ETS_BY_ACCOUNT_BY_EVENT_NAME_H
+#define TABLE_ETS_BY_ACCOUNT_BY_EVENT_NAME_H
+
+/**
+ @file storage/perfschema/table_ets_by_account_by_event_name.h
+ Table EVENTS_TRANSACTIONS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "pfs_instr_class.h"
+#include "pfs_instr.h"
+#include "pfs_account.h"
+#include "table_helper.h"
+
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+/**
+ A row of table
+ PERFORMANCE_SCHEMA.EVENTS_TRANSACTIONS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME.
+*/
+struct row_ets_by_account_by_event_name
+{
+ /** Columns USER, HOST. */
+ PFS_account_row m_account;
+ /** Column EVENT_NAME. */
+ PFS_event_name_row m_event_name;
+ /**
+ Columns COUNT_STAR, SUM/MIN/AVG/MAX_TIMER_WAIT,
+ COUNT_READ_WRITE, SUM/MIN/AVG/MAX_TIMER_READ_WRITE,
+ COUNT_READ_ONLY, SUM/MIN/AVG/MAX_TIMER_READ_ONLY
+ */
+ PFS_transaction_stat_row m_stat;
+};
+
+/**
+ Position of a cursor on
+ PERFORMANCE_SCHEMA.EVENTS_TRANSACTIONS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME.
+ Index 1 on account (0 based)
+ Index 2 on transaction class (1 based)
+*/
+struct pos_ets_by_account_by_event_name
+: public PFS_double_index
+{
+ pos_ets_by_account_by_event_name()
+ : PFS_double_index(0, 1)
+ {}
+
+ inline void reset(void)
+ {
+ m_index_1= 0;
+ m_index_2= 1;
+ }
+
+ inline void next_account(void)
+ {
+ m_index_1++;
+ m_index_2= 1;
+ }
+};
+
+/** Table PERFORMANCE_SCHEMA.EVENTS_TRANSACTIONS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME. */
+class table_ets_by_account_by_event_name : public PFS_engine_table
+{
+public:
+ /** Table share */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static int delete_all_rows();
+ static ha_rows get_row_count();
+
+ virtual int rnd_init(bool scan);
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+protected:
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+
+ table_ets_by_account_by_event_name();
+
+public:
+ ~table_ets_by_account_by_event_name()
+ {}
+
+protected:
+ void make_row(PFS_account *account, PFS_transaction_class *klass);
+
+private:
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /** Fields definition. */
+ static TABLE_FIELD_DEF m_field_def;
+
+ /** Current row. */
+ row_ets_by_account_by_event_name m_row;
+ /** True is the current row exists. */
+ bool m_row_exists;
+ /** Current position. */
+ pos_ets_by_account_by_event_name m_pos;
+ /** Next position. */
+ pos_ets_by_account_by_event_name m_next_pos;
+};
+
+/** @} */
+#endif
diff --git a/storage/perfschema/table_ets_by_host_by_event_name.cc b/storage/perfschema/table_ets_by_host_by_event_name.cc
new file mode 100644
index 00000000000..f02936241a0
--- /dev/null
+++ b/storage/perfschema/table_ets_by_host_by_event_name.cc
@@ -0,0 +1,226 @@
+/* Copyright (c) 2010, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+
+/**
+ @file storage/perfschema/table_ets_by_host_by_event_name.cc
+ Table EVENTS_TRANSACTIONS_SUMMARY_BY_HOST_BY_EVENT_NAME (implementation).
+*/
+
+#include "my_global.h"
+#include "my_thread.h"
+#include "pfs_instr_class.h"
+#include "pfs_column_types.h"
+#include "pfs_column_values.h"
+#include "table_ets_by_host_by_event_name.h"
+#include "pfs_global.h"
+#include "pfs_account.h"
+#include "pfs_visitor.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
+
+THR_LOCK table_ets_by_host_by_event_name::m_table_lock;
+
+PFS_engine_table_share
+table_ets_by_host_by_event_name::m_share=
+{
+ { C_STRING_WITH_LEN("events_transactions_summary_by_host_by_event_name") },
+ &pfs_truncatable_acl,
+ table_ets_by_host_by_event_name::create,
+ NULL, /* write_row */
+ table_ets_by_host_by_event_name::delete_all_rows,
+ table_ets_by_host_by_event_name::get_row_count,
+ sizeof(pos_ets_by_host_by_event_name),
+ &m_table_lock,
+ { C_STRING_WITH_LEN("CREATE TABLE events_transactions_summary_by_host_by_event_name("
+ "HOST CHAR(60) collate utf8_bin default null,"
+ "EVENT_NAME VARCHAR(128) not null,"
+ "COUNT_STAR BIGINT unsigned not null,"
+ "SUM_TIMER_WAIT BIGINT unsigned not null,"
+ "MIN_TIMER_WAIT BIGINT unsigned not null,"
+ "AVG_TIMER_WAIT BIGINT unsigned not null,"
+ "MAX_TIMER_WAIT BIGINT unsigned not null,"
+ "COUNT_READ_WRITE BIGINT unsigned not null,"
+ "SUM_TIMER_READ_WRITE BIGINT unsigned not null,"
+ "MIN_TIMER_READ_WRITE BIGINT unsigned not null,"
+ "AVG_TIMER_READ_WRITE BIGINT unsigned not null,"
+ "MAX_TIMER_READ_WRITE BIGINT unsigned not null,"
+ "COUNT_READ_ONLY BIGINT unsigned not null,"
+ "SUM_TIMER_READ_ONLY BIGINT unsigned not null,"
+ "MIN_TIMER_READ_ONLY BIGINT unsigned not null,"
+ "AVG_TIMER_READ_ONLY BIGINT unsigned not null,"
+ "MAX_TIMER_READ_ONLY BIGINT unsigned not null)")},
+ false /* perpetual */
+};
+
+PFS_engine_table*
+table_ets_by_host_by_event_name::create(void)
+{
+ return new table_ets_by_host_by_event_name();
+}
+
+int
+table_ets_by_host_by_event_name::delete_all_rows(void)
+{
+ reset_events_transactions_by_thread();
+ reset_events_transactions_by_account();
+ reset_events_transactions_by_host();
+ return 0;
+}
+
+ha_rows
+table_ets_by_host_by_event_name::get_row_count(void)
+{
+ return global_host_container.get_row_count() * transaction_class_max;
+}
+
+table_ets_by_host_by_event_name::table_ets_by_host_by_event_name()
+ : PFS_engine_table(&m_share, &m_pos),
+ m_row_exists(false), m_pos(), m_next_pos()
+{}
+
+void table_ets_by_host_by_event_name::reset_position(void)
+{
+ m_pos.reset();
+ m_next_pos.reset();
+}
+
+int table_ets_by_host_by_event_name::rnd_init(bool scan)
+{
+ m_normalizer= time_normalizer::get(transaction_timer);
+ return 0;
+}
+
+int table_ets_by_host_by_event_name::rnd_next(void)
+{
+ PFS_host *host;
+ PFS_transaction_class *transaction_class;
+ bool has_more_host= true;
+
+ for (m_pos.set_at(&m_next_pos);
+ has_more_host;
+ m_pos.next_host())
+ {
+ host= global_host_container.get(m_pos.m_index_1, & has_more_host);
+ if (host != NULL)
+ {
+ transaction_class= find_transaction_class(m_pos.m_index_2);
+ if (transaction_class)
+ {
+ make_row(host, transaction_class);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+ }
+ }
+
+ return HA_ERR_END_OF_FILE;
+}
+
+int
+table_ets_by_host_by_event_name::rnd_pos(const void *pos)
+{
+ PFS_host *host;
+ PFS_transaction_class *transaction_class;
+
+ set_position(pos);
+
+ host= global_host_container.get(m_pos.m_index_1);
+ if (host != NULL)
+ {
+ transaction_class= find_transaction_class(m_pos.m_index_2);
+ if (transaction_class)
+ {
+ make_row(host, transaction_class);
+ return 0;
+ }
+ }
+
+ return HA_ERR_RECORD_DELETED;
+}
+
+void table_ets_by_host_by_event_name
+::make_row(PFS_host *host, PFS_transaction_class *klass)
+{
+ pfs_optimistic_state lock;
+ m_row_exists= false;
+
+ host->m_lock.begin_optimistic_lock(&lock);
+
+ if (m_row.m_host.make_row(host))
+ return;
+
+ m_row.m_event_name.make_row(klass);
+
+ PFS_connection_transaction_visitor visitor(klass);
+ PFS_connection_iterator::visit_host(host,
+ true, /* accounts */
+ true, /* threads */
+ false, /* THDs */
+ & visitor);
+
+ if (! host->m_lock.end_optimistic_lock(&lock))
+ return;
+
+ m_row_exists= true;
+ m_row.m_stat.set(m_normalizer, & visitor.m_stat);
+}
+
+int table_ets_by_host_by_event_name
+::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 0: /* HOST */
+ m_row.m_host.set_field(f);
+ break;
+ case 1: /* EVENT_NAME */
+ m_row.m_event_name.set_field(f);
+ break;
+ default:
+ /**
+ COUNT_STAR, SUM/MIN/AVG/MAX_TIMER_WAIT,
+ COUNT_READ_WRITE, SUM/MIN/AVG/MAX_TIMER_READ_WRITE,
+ COUNT_READ_ONLY, SUM/MIN/AVG/MAX_TIMER_READ_ONLY
+ */
+ m_row.m_stat.set_field(f->field_index-2, f);
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
diff --git a/storage/perfschema/table_ets_by_host_by_event_name.h b/storage/perfschema/table_ets_by_host_by_event_name.h
new file mode 100644
index 00000000000..341c3878253
--- /dev/null
+++ b/storage/perfschema/table_ets_by_host_by_event_name.h
@@ -0,0 +1,134 @@
+/* Copyright (c) 2010, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+
+#ifndef TABLE_ETS_BY_HOST_BY_EVENT_NAME_H
+#define TABLE_ETS_BY_HOST_BY_EVENT_NAME_H
+
+/**
+ @file storage/perfschema/table_ets_by_host_by_event_name.h
+ Table EVENTS_TRANSACTIONS_SUMMARY_BY_HOST_BY_EVENT_NAME (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "pfs_instr_class.h"
+#include "pfs_instr.h"
+#include "pfs_host.h"
+#include "table_helper.h"
+
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+/**
+ A row of table
+ PERFORMANCE_SCHEMA.EVENTS_TRANSACTIONS_SUMMARY_BY_HOST_BY_EVENT_NAME.
+*/
+struct row_ets_by_host_by_event_name
+{
+ /** Column HOST */
+ PFS_host_row m_host;
+ /** Column EVENT_NAME */
+ PFS_event_name_row m_event_name;
+ /**
+ Columns COUNT_STAR, SUM/MIN/AVG/MAX_TIMER_WAIT,
+ COUNT_READ_WRITE, SUM/MIN/AVG/MAX_TIMER_READ_WRITE,
+ COUNT_READ_ONLY, SUM/MIN/AVG/MAX_TIMER_READ_ONLY
+ */
+ PFS_transaction_stat_row m_stat;
+};
+
+/**
+ Position of a cursor on
+ PERFORMANCE_SCHEMA.EVENTS_TRANSACTIONS_SUMMARY_BY_HOST_BY_EVENT_NAME.
+ Index 1 on host (0 based)
+ Index 2 on transaction class (1 based)
+*/
+struct pos_ets_by_host_by_event_name
+: public PFS_double_index
+{
+ pos_ets_by_host_by_event_name()
+ : PFS_double_index(0, 1)
+ {}
+
+ inline void reset(void)
+ {
+ m_index_1= 0;
+ m_index_2= 1;
+ }
+
+ inline void next_host(void)
+ {
+ m_index_1++;
+ m_index_2= 1;
+ }
+};
+
+/** Table PERFORMANCE_SCHEMA.EVENTS_TRANSACTIONS_SUMMARY_BY_HOST_BY_EVENT_NAME. */
+class table_ets_by_host_by_event_name : public PFS_engine_table
+{
+public:
+ /** Table share */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static int delete_all_rows();
+ static ha_rows get_row_count();
+
+ virtual int rnd_init(bool scan);
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+protected:
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+
+ table_ets_by_host_by_event_name();
+
+public:
+ ~table_ets_by_host_by_event_name()
+ {}
+
+protected:
+ void make_row(PFS_host *host, PFS_transaction_class *klass);
+
+private:
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /** Fields definition. */
+ static TABLE_FIELD_DEF m_field_def;
+
+ /** Current row. */
+ row_ets_by_host_by_event_name m_row;
+ /** True is the current row exists. */
+ bool m_row_exists;
+ /** Current position. */
+ pos_ets_by_host_by_event_name m_pos;
+ /** Next position. */
+ pos_ets_by_host_by_event_name m_next_pos;
+};
+
+/** @} */
+#endif
diff --git a/storage/perfschema/table_ets_by_thread_by_event_name.cc b/storage/perfschema/table_ets_by_thread_by_event_name.cc
new file mode 100644
index 00000000000..81ebf23bbfb
--- /dev/null
+++ b/storage/perfschema/table_ets_by_thread_by_event_name.cc
@@ -0,0 +1,218 @@
+/* Copyright (c) 2010, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/**
+ @file storage/perfschema/table_ets_by_thread_by_event_name.cc
+ Table EVENTS_TRANSACTIONS_SUMMARY_BY_HOST_BY_EVENT_NAME (implementation).
+*/
+
+#include "my_global.h"
+#include "my_thread.h"
+#include "pfs_instr_class.h"
+#include "pfs_column_types.h"
+#include "pfs_column_values.h"
+#include "table_ets_by_thread_by_event_name.h"
+#include "pfs_global.h"
+#include "pfs_visitor.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
+
+THR_LOCK table_ets_by_thread_by_event_name::m_table_lock;
+
+PFS_engine_table_share
+table_ets_by_thread_by_event_name::m_share=
+{
+ { C_STRING_WITH_LEN("events_transactions_summary_by_thread_by_event_name") },
+ &pfs_truncatable_acl,
+ table_ets_by_thread_by_event_name::create,
+ NULL, /* write_row */
+ table_ets_by_thread_by_event_name::delete_all_rows,
+ table_ets_by_thread_by_event_name::get_row_count,
+ sizeof(pos_ets_by_thread_by_event_name),
+ &m_table_lock,
+ { C_STRING_WITH_LEN("CREATE TABLE events_transactions_summary_by_thread_by_event_name("
+ "THREAD_ID BIGINT unsigned not null,"
+ "EVENT_NAME VARCHAR(128) not null,"
+ "COUNT_STAR BIGINT unsigned not null,"
+ "SUM_TIMER_WAIT BIGINT unsigned not null,"
+ "MIN_TIMER_WAIT BIGINT unsigned not null,"
+ "AVG_TIMER_WAIT BIGINT unsigned not null,"
+ "MAX_TIMER_WAIT BIGINT unsigned not null,"
+ "COUNT_READ_WRITE BIGINT unsigned not null,"
+ "SUM_TIMER_READ_WRITE BIGINT unsigned not null,"
+ "MIN_TIMER_READ_WRITE BIGINT unsigned not null,"
+ "AVG_TIMER_READ_WRITE BIGINT unsigned not null,"
+ "MAX_TIMER_READ_WRITE BIGINT unsigned not null,"
+ "COUNT_READ_ONLY BIGINT unsigned not null,"
+ "SUM_TIMER_READ_ONLY BIGINT unsigned not null,"
+ "MIN_TIMER_READ_ONLY BIGINT unsigned not null,"
+ "AVG_TIMER_READ_ONLY BIGINT unsigned not null,"
+ "MAX_TIMER_READ_ONLY BIGINT unsigned not null)")},
+ false /* perpetual */
+};
+
+PFS_engine_table*
+table_ets_by_thread_by_event_name::create(void)
+{
+ return new table_ets_by_thread_by_event_name();
+}
+
+int
+table_ets_by_thread_by_event_name::delete_all_rows(void)
+{
+ reset_events_transactions_by_thread();
+ return 0;
+}
+
+ha_rows
+table_ets_by_thread_by_event_name::get_row_count(void)
+{
+ return global_thread_container.get_row_count() * transaction_class_max;
+}
+
+table_ets_by_thread_by_event_name::table_ets_by_thread_by_event_name()
+ : PFS_engine_table(&m_share, &m_pos),
+ m_row_exists(false), m_pos(), m_next_pos()
+{}
+
+void table_ets_by_thread_by_event_name::reset_position(void)
+{
+ m_pos.reset();
+ m_next_pos.reset();
+}
+
+int table_ets_by_thread_by_event_name::rnd_init(bool scan)
+{
+ m_normalizer= time_normalizer::get(transaction_timer);
+ return 0;
+}
+
+int table_ets_by_thread_by_event_name::rnd_next(void)
+{
+ PFS_thread *thread;
+ PFS_transaction_class *transaction_class;
+ bool has_more_thread= true;
+
+ for (m_pos.set_at(&m_next_pos);
+ has_more_thread;
+ m_pos.next_thread())
+ {
+ thread= global_thread_container.get(m_pos.m_index_1, & has_more_thread);
+ if (thread != NULL)
+ {
+ transaction_class= find_transaction_class(m_pos.m_index_2);
+ if (transaction_class)
+ {
+ make_row(thread, transaction_class);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+ }
+ }
+
+ return HA_ERR_END_OF_FILE;
+}
+
+int
+table_ets_by_thread_by_event_name::rnd_pos(const void *pos)
+{
+ PFS_thread *thread;
+ PFS_transaction_class *transaction_class;
+
+ set_position(pos);
+
+ thread= global_thread_container.get(m_pos.m_index_1);
+ if (thread != NULL)
+ {
+ transaction_class= find_transaction_class(m_pos.m_index_2);
+ if (transaction_class)
+ {
+ make_row(thread, transaction_class);
+ return 0;
+ }
+ }
+
+ return HA_ERR_RECORD_DELETED;
+}
+
+void table_ets_by_thread_by_event_name
+::make_row(PFS_thread *thread, PFS_transaction_class *klass)
+{
+ pfs_optimistic_state lock;
+ m_row_exists= false;
+
+ /* Protect this reader against a thread termination */
+ thread->m_lock.begin_optimistic_lock(&lock);
+
+ m_row.m_thread_internal_id= thread->m_thread_internal_id;
+
+ m_row.m_event_name.make_row(klass);
+
+ PFS_connection_transaction_visitor visitor(klass);
+ PFS_connection_iterator::visit_thread(thread, &visitor);
+
+ if (! thread->m_lock.end_optimistic_lock(&lock))
+ return;
+
+ m_row_exists= true;
+ m_row.m_stat.set(m_normalizer, &visitor.m_stat);
+}
+
+int table_ets_by_thread_by_event_name
+::read_row_values(TABLE *table, unsigned char *, 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 == 0);
+
+ for (; (f= *fields) ; fields++)
+ {
+ if (read_all || bitmap_is_set(table->read_set, f->field_index))
+ {
+ switch(f->field_index)
+ {
+ case 0: /* THREAD_ID */
+ set_field_ulonglong(f, m_row.m_thread_internal_id);
+ break;
+ case 1: /* EVENT_NAME */
+ m_row.m_event_name.set_field(f);
+ break;
+ default:
+ /**
+ COUNT_STAR, SUM/MIN/AVG/MAX_TIMER_WAIT
+ COUNT_READ_WRITE, SUM/MIN/AVG/MAX_TIMER_READ_WRITE
+ COUNT_READ_ONLY, SUM/MIN/AVG/MAX_TIMER_READ_ONLY
+ */
+ m_row.m_stat.set_field(f->field_index-2, f);
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
diff --git a/storage/perfschema/table_ets_by_thread_by_event_name.h b/storage/perfschema/table_ets_by_thread_by_event_name.h
new file mode 100644
index 00000000000..ad63efa3f1a
--- /dev/null
+++ b/storage/perfschema/table_ets_by_thread_by_event_name.h
@@ -0,0 +1,138 @@
+/* Copyright (c) 2010, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#ifndef TABLE_ETS_BY_THREAD_BY_EVENT_NAME_H
+#define TABLE_ETS_BY_THREAD_BY_EVENT_NAME_H
+
+/**
+ @file storage/perfschema/table_ets_by_thread_by_event_name.h
+ Table EVENTS_TRANSACTIONS_SUMMARY_BY_THREAD_BY_EVENT_NAME (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "pfs_instr_class.h"
+#include "pfs_instr.h"
+#include "table_helper.h"
+
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+/**
+ A row of table
+ PERFORMANCE_SCHEMA.EVENTS_TRANSACTIONS_SUMMARY_BY_THREAD_BY_EVENT_NAME.
+*/
+struct row_ets_by_thread_by_event_name
+{
+ /** Column THREAD_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,
+ COUNT_READ_WRITE, SUM/MIN/AVG/MAX_TIMER_READ_WRITE,
+ COUNT_READ_ONLY, SUM/MIN/AVG/MAX_TIMER_READ_ONLY
+ */
+ PFS_transaction_stat_row m_stat;
+};
+
+/**
+ Position of a cursor on
+ PERFORMANCE_SCHEMA.EVENTS_TRANSACTIONS_SUMMARY_BY_THREAD_BY_EVENT_NAME.
+ Index 1 on thread (0 based).
+ Index 2 on transaction class (1 based).
+*/
+struct pos_ets_by_thread_by_event_name
+: public PFS_double_index, public PFS_instrument_view_constants
+{
+ pos_ets_by_thread_by_event_name()
+ : PFS_double_index(0, 1)
+ {}
+
+ inline void reset(void)
+ {
+ m_index_1= 0;
+ m_index_2= 1;
+ }
+
+ inline void next_thread(void)
+ {
+ m_index_1++;
+ m_index_2= 1;
+ }
+
+ inline void next_transaction(void)
+ {
+ m_index_2++;
+ }
+};
+
+/** Table PERFORMANCE_SCHEMA.EVENTS_TRANSACTIONS_SUMMARY_BY_THREAD_BY_EVENT_NAME. */
+class table_ets_by_thread_by_event_name : public PFS_engine_table
+{
+public:
+ /** Table share */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static int delete_all_rows();
+ static ha_rows get_row_count();
+
+ virtual int rnd_init(bool scan);
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+protected:
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+
+ table_ets_by_thread_by_event_name();
+
+public:
+ ~table_ets_by_thread_by_event_name()
+ {}
+
+protected:
+ void make_row(PFS_thread *thread, PFS_transaction_class *klass);
+
+private:
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /** Fields definition. */
+ static TABLE_FIELD_DEF m_field_def;
+
+ /** Current row. */
+ row_ets_by_thread_by_event_name m_row;
+ /** True is the current row exists. */
+ bool m_row_exists;
+ /** Current position. */
+ pos_ets_by_thread_by_event_name m_pos;
+ /** Next position. */
+ pos_ets_by_thread_by_event_name m_next_pos;
+};
+
+/** @} */
+#endif
diff --git a/storage/perfschema/table_ets_by_user_by_event_name.cc b/storage/perfschema/table_ets_by_user_by_event_name.cc
new file mode 100644
index 00000000000..66aae431782
--- /dev/null
+++ b/storage/perfschema/table_ets_by_user_by_event_name.cc
@@ -0,0 +1,225 @@
+/* Copyright (c) 2010, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+
+/**
+ @file storage/perfschema/table_ets_by_user_by_event_name.cc
+ Table EVENTS_TRANSACTIONS_SUMMARY_BY_USER_BY_EVENT_NAME (implementation).
+*/
+
+#include "my_global.h"
+#include "my_thread.h"
+#include "pfs_instr_class.h"
+#include "pfs_column_types.h"
+#include "pfs_column_values.h"
+#include "table_ets_by_user_by_event_name.h"
+#include "pfs_global.h"
+#include "pfs_visitor.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
+
+THR_LOCK table_ets_by_user_by_event_name::m_table_lock;
+
+PFS_engine_table_share
+table_ets_by_user_by_event_name::m_share=
+{
+ { C_STRING_WITH_LEN("events_transactions_summary_by_user_by_event_name") },
+ &pfs_truncatable_acl,
+ table_ets_by_user_by_event_name::create,
+ NULL, /* write_row */
+ table_ets_by_user_by_event_name::delete_all_rows,
+ table_ets_by_user_by_event_name::get_row_count,
+ sizeof(pos_ets_by_user_by_event_name),
+ &m_table_lock,
+ { C_STRING_WITH_LEN("CREATE TABLE events_transactions_summary_by_user_by_event_name("
+ "USER CHAR(32) collate utf8_bin default null,"
+ "EVENT_NAME VARCHAR(128) not null,"
+ "COUNT_STAR BIGINT unsigned not null,"
+ "SUM_TIMER_WAIT BIGINT unsigned not null,"
+ "MIN_TIMER_WAIT BIGINT unsigned not null,"
+ "AVG_TIMER_WAIT BIGINT unsigned not null,"
+ "MAX_TIMER_WAIT BIGINT unsigned not null,"
+ "COUNT_READ_WRITE BIGINT unsigned not null,"
+ "SUM_TIMER_READ_WRITE BIGINT unsigned not null,"
+ "MIN_TIMER_READ_WRITE BIGINT unsigned not null,"
+ "AVG_TIMER_READ_WRITE BIGINT unsigned not null,"
+ "MAX_TIMER_READ_WRITE BIGINT unsigned not null,"
+ "COUNT_READ_ONLY BIGINT unsigned not null,"
+ "SUM_TIMER_READ_ONLY BIGINT unsigned not null,"
+ "MIN_TIMER_READ_ONLY BIGINT unsigned not null,"
+ "AVG_TIMER_READ_ONLY BIGINT unsigned not null,"
+ "MAX_TIMER_READ_ONLY BIGINT unsigned not null)")},
+ false /* perpetual */
+};
+
+PFS_engine_table*
+table_ets_by_user_by_event_name::create(void)
+{
+ return new table_ets_by_user_by_event_name();
+}
+
+int
+table_ets_by_user_by_event_name::delete_all_rows(void)
+{
+ reset_events_transactions_by_thread();
+ reset_events_transactions_by_account();
+ reset_events_transactions_by_user();
+ return 0;
+}
+
+ha_rows
+table_ets_by_user_by_event_name::get_row_count(void)
+{
+ return global_user_container.get_row_count() * transaction_class_max;
+}
+
+table_ets_by_user_by_event_name::table_ets_by_user_by_event_name()
+ : PFS_engine_table(&m_share, &m_pos),
+ m_row_exists(false), m_pos(), m_next_pos()
+{}
+
+void table_ets_by_user_by_event_name::reset_position(void)
+{
+ m_pos.reset();
+ m_next_pos.reset();
+}
+
+int table_ets_by_user_by_event_name::rnd_init(bool scan)
+{
+ m_normalizer= time_normalizer::get(transaction_timer);
+ return 0;
+}
+
+int table_ets_by_user_by_event_name::rnd_next(void)
+{
+ PFS_user *user;
+ PFS_transaction_class *transaction_class;
+ bool has_more_user= true;
+
+ for (m_pos.set_at(&m_next_pos);
+ has_more_user;
+ m_pos.next_user())
+ {
+ user= global_user_container.get(m_pos.m_index_1, & has_more_user);
+ if (user != NULL)
+ {
+ transaction_class= find_transaction_class(m_pos.m_index_2);
+ if (transaction_class)
+ {
+ make_row(user, transaction_class);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+ }
+ }
+
+ return HA_ERR_END_OF_FILE;
+}
+
+int
+table_ets_by_user_by_event_name::rnd_pos(const void *pos)
+{
+ PFS_user *user;
+ PFS_transaction_class *transaction_class;
+
+ set_position(pos);
+
+ user= global_user_container.get(m_pos.m_index_1);
+ if (user != NULL)
+ {
+ transaction_class= find_transaction_class(m_pos.m_index_2);
+ if (transaction_class)
+ {
+ make_row(user, transaction_class);
+ return 0;
+ }
+ }
+
+ return HA_ERR_RECORD_DELETED;
+}
+
+void table_ets_by_user_by_event_name
+::make_row(PFS_user *user, PFS_transaction_class *klass)
+{
+ pfs_optimistic_state lock;
+ m_row_exists= false;
+
+ user->m_lock.begin_optimistic_lock(&lock);
+
+ if (m_row.m_user.make_row(user))
+ return;
+
+ m_row.m_event_name.make_row(klass);
+
+ PFS_connection_transaction_visitor visitor(klass);
+ PFS_connection_iterator::visit_user(user,
+ true, /* accounts */
+ true, /* threads */
+ false, /* THDs */
+ & visitor);
+
+ if (! user->m_lock.end_optimistic_lock(&lock))
+ return;
+
+ m_row_exists= true;
+ m_row.m_stat.set(m_normalizer, & visitor.m_stat);
+}
+
+int table_ets_by_user_by_event_name
+::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 0: /* USER */
+ m_row.m_user.set_field(f);
+ break;
+ case 1: /* EVENT_NAME */
+ m_row.m_event_name.set_field(f);
+ break;
+ default:
+ /**
+ COUNT_STAR, SUM/MIN/AVG/MAX_TIMER_WAIT,
+ COUNT_READ_WRITE, SUM/MIN/AVG/MAX_TIMER_READ_WRITE,
+ COUNT_READ_ONLY, SUM/MIN/AVG/MAX_TIMER_READ_ONLY
+ */
+ m_row.m_stat.set_field(f->field_index-2, f);
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
diff --git a/storage/perfschema/table_ets_by_user_by_event_name.h b/storage/perfschema/table_ets_by_user_by_event_name.h
new file mode 100644
index 00000000000..c3a1d0b5c0a
--- /dev/null
+++ b/storage/perfschema/table_ets_by_user_by_event_name.h
@@ -0,0 +1,134 @@
+/* Copyright (c) 2010, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+
+#ifndef TABLE_ETS_BY_USER_BY_EVENT_NAME_H
+#define TABLE_ETS_BY_USER_BY_EVENT_NAME_H
+
+/**
+ @file storage/perfschema/table_ets_by_user_by_event_name.h
+ Table EVENTS_TRANSACTIONS_SUMMARY_BY_USER_BY_EVENT_NAME (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "pfs_instr_class.h"
+#include "pfs_instr.h"
+#include "pfs_user.h"
+#include "table_helper.h"
+
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+/**
+ A row of table
+ PERFORMANCE_SCHEMA.EVENTS_TRANSACTIONS_SUMMARY_BY_USER_BY_EVENT_NAME.
+*/
+struct row_ets_by_user_by_event_name
+{
+ /** Column USER */
+ PFS_user_row m_user;
+ /** Column EVENT_NAME */
+ PFS_event_name_row m_event_name;
+ /**
+ Columns COUNT_STAR, SUM/MIN/AVG/MAX_TIMER_WAIT,
+ COUNT_READ_WRITE, SUM/MIN/AVG/MAX_TIMER_READ_WRITE,
+ COUNT_READ_ONLY, SUM/MIN/AVG/MAX_TIMER_READ_ONLY
+ */
+ PFS_transaction_stat_row m_stat;
+};
+
+/**
+ Position of a cursor on
+ PERFORMANCE_SCHEMA.EVENTS_TRANSACTIONS_SUMMARY_BY_USER_BY_EVENT_NAME.
+ Index 1 on user (0 based)
+ Index 2 on transaction class (1 based)
+*/
+struct pos_ets_by_user_by_event_name
+: public PFS_double_index
+{
+ pos_ets_by_user_by_event_name()
+ : PFS_double_index(0, 1)
+ {}
+
+ inline void reset(void)
+ {
+ m_index_1= 0;
+ m_index_2= 1;
+ }
+
+ inline void next_user(void)
+ {
+ m_index_1++;
+ m_index_2= 1;
+ }
+};
+
+/** Table PERFORMANCE_SCHEMA.EVENTS_TRANSACTIONS_SUMMARY_BY_USER_BY_EVENT_NAME. */
+class table_ets_by_user_by_event_name : public PFS_engine_table
+{
+public:
+ /** Table share */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static int delete_all_rows();
+ static ha_rows get_row_count();
+
+ virtual int rnd_init(bool scan);
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+protected:
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+
+ table_ets_by_user_by_event_name();
+
+public:
+ ~table_ets_by_user_by_event_name()
+ {}
+
+protected:
+ void make_row(PFS_user *user, PFS_transaction_class *klass);
+
+private:
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /** Fields definition. */
+ static TABLE_FIELD_DEF m_field_def;
+
+ /** Current row. */
+ row_ets_by_user_by_event_name m_row;
+ /** True is the current row exists. */
+ bool m_row_exists;
+ /** Current position. */
+ pos_ets_by_user_by_event_name m_pos;
+ /** Next position. */
+ pos_ets_by_user_by_event_name m_next_pos;
+};
+
+/** @} */
+#endif
diff --git a/storage/perfschema/table_ets_global_by_event_name.cc b/storage/perfschema/table_ets_global_by_event_name.cc
new file mode 100644
index 00000000000..6c13871a746
--- /dev/null
+++ b/storage/perfschema/table_ets_global_by_event_name.cc
@@ -0,0 +1,200 @@
+/* Copyright (c) 2010, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/**
+ @file storage/perfschema/table_ets_global_by_event_name.cc
+ Table EVENTS_TRANSACTIONS_SUMMARY_GLOBAL_BY_EVENT_NAME (implementation).
+*/
+
+#include "my_global.h"
+#include "my_thread.h"
+#include "pfs_instr_class.h"
+#include "pfs_column_types.h"
+#include "pfs_column_values.h"
+#include "table_ets_global_by_event_name.h"
+#include "pfs_global.h"
+#include "pfs_instr.h"
+#include "pfs_timer.h"
+#include "pfs_visitor.h"
+#include "field.h"
+
+THR_LOCK table_ets_global_by_event_name::m_table_lock;
+
+PFS_engine_table_share
+table_ets_global_by_event_name::m_share=
+{
+ { C_STRING_WITH_LEN("events_transactions_summary_global_by_event_name") },
+ &pfs_truncatable_acl,
+ table_ets_global_by_event_name::create,
+ NULL, /* write_row */
+ table_ets_global_by_event_name::delete_all_rows,
+ table_ets_global_by_event_name::get_row_count,
+ sizeof(PFS_simple_index),
+ &m_table_lock,
+ { C_STRING_WITH_LEN("CREATE TABLE events_transactions_summary_global_by_event_name("
+ "EVENT_NAME VARCHAR(128) not null,"
+ "COUNT_STAR BIGINT unsigned not null,"
+ "SUM_TIMER_WAIT BIGINT unsigned not null,"
+ "MIN_TIMER_WAIT BIGINT unsigned not null,"
+ "AVG_TIMER_WAIT BIGINT unsigned not null,"
+ "MAX_TIMER_WAIT BIGINT unsigned not null,"
+ "COUNT_READ_WRITE BIGINT unsigned not null,"
+ "SUM_TIMER_READ_WRITE BIGINT unsigned not null,"
+ "MIN_TIMER_READ_WRITE BIGINT unsigned not null,"
+ "AVG_TIMER_READ_WRITE BIGINT unsigned not null,"
+ "MAX_TIMER_READ_WRITE BIGINT unsigned not null,"
+ "COUNT_READ_ONLY BIGINT unsigned not null,"
+ "SUM_TIMER_READ_ONLY BIGINT unsigned not null,"
+ "MIN_TIMER_READ_ONLY BIGINT unsigned not null,"
+ "AVG_TIMER_READ_ONLY BIGINT unsigned not null,"
+ "MAX_TIMER_READ_ONLY BIGINT unsigned not null)")},
+ false /* perpetual */
+};
+
+PFS_engine_table*
+table_ets_global_by_event_name::create(void)
+{
+ return new table_ets_global_by_event_name();
+}
+
+int
+table_ets_global_by_event_name::delete_all_rows(void)
+{
+ reset_events_transactions_by_thread();
+ reset_events_transactions_by_account();
+ reset_events_transactions_by_user();
+ reset_events_transactions_by_host();
+ reset_events_transactions_global();
+ return 0;
+}
+
+ha_rows
+table_ets_global_by_event_name::get_row_count(void)
+{
+ return transaction_class_max;
+}
+
+table_ets_global_by_event_name::table_ets_global_by_event_name()
+ : PFS_engine_table(&m_share, &m_pos),
+ m_row_exists(false), m_pos(1), m_next_pos(1)
+{}
+
+void table_ets_global_by_event_name::reset_position(void)
+{
+ m_pos= 1;
+ m_next_pos= 1;
+}
+
+int table_ets_global_by_event_name::rnd_init(bool scan)
+{
+ m_normalizer= time_normalizer::get(transaction_timer);
+ return 0;
+}
+
+int table_ets_global_by_event_name::rnd_next(void)
+{
+ PFS_transaction_class *transaction_class;
+
+ m_pos.set_at(&m_next_pos);
+
+ transaction_class= find_transaction_class(m_pos.m_index);
+ if (transaction_class)
+ {
+ make_row(transaction_class);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+
+ return HA_ERR_END_OF_FILE;
+}
+
+int
+table_ets_global_by_event_name::rnd_pos(const void *pos)
+{
+ PFS_transaction_class *transaction_class;
+
+ set_position(pos);
+
+ transaction_class=find_transaction_class(m_pos.m_index);
+ if (transaction_class)
+ {
+ make_row(transaction_class);
+ return 0;
+ }
+
+ return HA_ERR_RECORD_DELETED;
+}
+
+
+void table_ets_global_by_event_name
+::make_row(PFS_transaction_class *klass)
+{
+ m_row.m_event_name.make_row(klass);
+
+ PFS_connection_transaction_visitor visitor(klass);
+ PFS_connection_iterator::visit_global(true, /* hosts */
+ false, /* users */
+ true, /* accounts */
+ true, /* threads */
+ false, /* THDs */
+ & visitor);
+
+ m_row.m_stat.set(m_normalizer, & visitor.m_stat);
+ m_row_exists= true;
+}
+
+int table_ets_global_by_event_name
+::read_row_values(TABLE *table, unsigned char *, 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 == 0);
+
+ for (; (f= *fields) ; fields++)
+ {
+ if (read_all || bitmap_is_set(table->read_set, f->field_index))
+ {
+ switch(f->field_index)
+ {
+ case 0: /* NAME */
+ m_row.m_event_name.set_field(f);
+ break;
+ default:
+ /**
+ Columns COUNT_STAR, SUM/MIN/AVG/MAX_TIMER_WAIT,
+ COUNT_READ_WRITE, SUM/MIN/AVG/MAX_TIMER_READ_WRITE,
+ COUNT_READ_ONLY, SUM/MIN/AVG/MAX_TIMER_READ_ONLY
+ */
+ m_row.m_stat.set_field(f->field_index - 1, f);
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
diff --git a/storage/perfschema/table_ets_global_by_event_name.h b/storage/perfschema/table_ets_global_by_event_name.h
new file mode 100644
index 00000000000..47c8828cb47
--- /dev/null
+++ b/storage/perfschema/table_ets_global_by_event_name.h
@@ -0,0 +1,105 @@
+/* Copyright (c) 2010, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#ifndef TABLE_ETS_GLOBAL_BY_EVENT_NAME_H
+#define TABLE_ETS_GLOBAL_BY_EVENT_NAME_H
+
+/**
+ @file storage/perfschema/table_ets_global_by_event_name.h
+ Table EVENTS_TRANSACTIONS_SUMMARY_GLOBAL_BY_EVENT_NAME (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "pfs_instr_class.h"
+#include "pfs_instr.h"
+#include "table_helper.h"
+
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+/**
+ A row of table
+ PERFORMANCE_SCHEMA.EVENTS_TRANSACTIONS_SUMMARY_GLOBAL_BY_EVENT_NAME.
+*/
+struct row_ets_global_by_event_name
+{
+ /** Column EVENT_NAME. */
+ PFS_event_name_row m_event_name;
+ /**
+ Columns COUNT_STAR, SUM/MIN/AVG/MAX_TIMER_WAIT,
+ COUNT_READ_WRITE, SUM/MIN/AVG/MAX_TIMER_READ_WRITE,
+ COUNT_READ_ONLY, SUM/MIN/AVG/MAX_TIMER_READ_ONLY
+ */
+ PFS_transaction_stat_row m_stat;
+};
+
+/** Table PERFORMANCE_SCHEMA.EVENTS_TRANSACTIONS_SUMMARY_GLOBAL_BY_EVENT_NAME. */
+class table_ets_global_by_event_name : public PFS_engine_table
+{
+public:
+ /** Table share */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static int delete_all_rows();
+ static ha_rows get_row_count();
+
+ virtual int rnd_init(bool scan);
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+protected:
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+
+ table_ets_global_by_event_name();
+
+public:
+ ~table_ets_global_by_event_name()
+ {}
+
+protected:
+ void make_row(PFS_transaction_class *klass);
+
+private:
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /** Fields definition. */
+ static TABLE_FIELD_DEF m_field_def;
+
+ /** Current row. */
+ row_ets_global_by_event_name m_row;
+ /** True is the current row exists. */
+ bool m_row_exists;
+ /** Current position. */
+ PFS_simple_index m_pos;
+ /** Next position. */
+ PFS_simple_index m_next_pos;
+};
+
+/** @} */
+#endif
diff --git a/storage/perfschema/table_events_stages.cc b/storage/perfschema/table_events_stages.cc
index 95e7f187d24..cd6c79df36c 100644
--- a/storage/perfschema/table_events_stages.cc
+++ b/storage/perfschema/table_events_stages.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2018, 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, version 2.0,
@@ -26,12 +26,14 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "table_events_stages.h"
#include "pfs_instr_class.h"
#include "pfs_instr.h"
#include "pfs_events_stages.h"
#include "pfs_timer.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
THR_LOCK table_events_stages_current::m_table_lock;
@@ -40,11 +42,10 @@ table_events_stages_current::m_share=
{
{ C_STRING_WITH_LEN("events_stages_current") },
&pfs_truncatable_acl,
- &table_events_stages_current::create,
+ table_events_stages_current::create,
NULL, /* write_row */
- &table_events_stages_current::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ table_events_stages_current::delete_all_rows,
+ table_events_stages_current::get_row_count,
sizeof(PFS_simple_index), /* ref length */
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE events_stages_current("
@@ -56,8 +57,11 @@ table_events_stages_current::m_share=
"TIMER_START BIGINT unsigned,"
"TIMER_END BIGINT unsigned,"
"TIMER_WAIT BIGINT unsigned,"
+ "WORK_COMPLETED BIGINT unsigned,"
+ "WORK_ESTIMATED BIGINT unsigned,"
"NESTING_EVENT_ID BIGINT unsigned,"
- "NESTING_EVENT_TYPE ENUM('STATEMENT', 'STAGE', 'WAIT'))") }
+ "NESTING_EVENT_TYPE ENUM('TRANSACTION', 'STATEMENT', 'STAGE', 'WAIT'))") },
+ false /* perpetual */
};
THR_LOCK table_events_stages_history::m_table_lock;
@@ -67,11 +71,10 @@ table_events_stages_history::m_share=
{
{ C_STRING_WITH_LEN("events_stages_history") },
&pfs_truncatable_acl,
- &table_events_stages_history::create,
+ table_events_stages_history::create,
NULL, /* write_row */
- &table_events_stages_history::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ table_events_stages_history::delete_all_rows,
+ table_events_stages_history::get_row_count,
sizeof(pos_events_stages_history), /* ref length */
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE events_stages_history("
@@ -83,8 +86,11 @@ table_events_stages_history::m_share=
"TIMER_START BIGINT unsigned,"
"TIMER_END BIGINT unsigned,"
"TIMER_WAIT BIGINT unsigned,"
+ "WORK_COMPLETED BIGINT unsigned,"
+ "WORK_ESTIMATED BIGINT unsigned,"
"NESTING_EVENT_ID BIGINT unsigned,"
- "NESTING_EVENT_TYPE ENUM('STATEMENT', 'STAGE', 'WAIT'))") }
+ "NESTING_EVENT_TYPE ENUM('TRANSACTION', 'STATEMENT', 'STAGE', 'WAIT'))") },
+ false /* perpetual */
};
THR_LOCK table_events_stages_history_long::m_table_lock;
@@ -94,11 +100,10 @@ table_events_stages_history_long::m_share=
{
{ C_STRING_WITH_LEN("events_stages_history_long") },
&pfs_truncatable_acl,
- &table_events_stages_history_long::create,
+ table_events_stages_history_long::create,
NULL, /* write_row */
- &table_events_stages_history_long::delete_all_rows,
- NULL, /* get_row_count */
- 10000, /* records */
+ table_events_stages_history_long::delete_all_rows,
+ table_events_stages_history_long::get_row_count,
sizeof(PFS_simple_index), /* ref length */
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE events_stages_history_long("
@@ -110,8 +115,11 @@ table_events_stages_history_long::m_share=
"TIMER_START BIGINT unsigned,"
"TIMER_END BIGINT unsigned,"
"TIMER_WAIT BIGINT unsigned,"
+ "WORK_COMPLETED BIGINT unsigned,"
+ "WORK_ESTIMATED BIGINT unsigned,"
"NESTING_EVENT_ID BIGINT unsigned,"
- "NESTING_EVENT_TYPE ENUM('STATEMENT', 'STAGE', 'WAIT'))") }
+ "NESTING_EVENT_TYPE ENUM('TRANSACTION', 'STATEMENT', 'STAGE', 'WAIT'))") },
+ false /* perpetual */
};
table_events_stages_common::table_events_stages_common
@@ -126,8 +134,6 @@ table_events_stages_common::table_events_stages_common
*/
void table_events_stages_common::make_row(PFS_events_stages *stage)
{
- const char *base;
- const char *safe_source_file;
ulonglong timer_end;
m_row_exists= false;
@@ -158,15 +164,19 @@ void table_events_stages_common::make_row(PFS_events_stages *stage)
m_row.m_name= klass->m_name;
m_row.m_name_length= klass->m_name_length;
- safe_source_file= stage->m_source_file;
- if (unlikely(safe_source_file == NULL))
- return;
+ /* Disable source file and line to avoid stale __FILE__ pointers. */
+ m_row.m_source_length= 0;
- base= base_name(safe_source_file);
- m_row.m_source_length= (uint)my_snprintf(m_row.m_source, sizeof(m_row.m_source),
- "%s:%d", base, stage->m_source_line);
- if (m_row.m_source_length > sizeof(m_row.m_source))
- m_row.m_source_length= sizeof(m_row.m_source);
+ if (klass->is_progress())
+ {
+ m_row.m_progress= true;
+ m_row.m_work_completed= stage->m_progress.m_work_completed;
+ m_row.m_work_estimated= stage->m_progress.m_work_estimated;
+ }
+ else
+ {
+ m_row.m_progress= false;
+ }
m_row_exists= true;
return;
@@ -183,8 +193,9 @@ int table_events_stages_common::read_row_values(TABLE *table,
return HA_ERR_RECORD_DELETED;
/* Set the null bits */
- DBUG_ASSERT(table->s->null_bytes == 1);
+ DBUG_ASSERT(table->s->null_bytes == 2);
buf[0]= 0;
+ buf[1]= 0;
for (; (f= *fields) ; fields++)
{
@@ -228,13 +239,25 @@ int table_events_stages_common::read_row_values(TABLE *table,
else
f->set_null();
break;
- case 8: /* NESTING_EVENT_ID */
+ case 8: /* WORK_COMPLETED */
+ if (m_row.m_progress)
+ set_field_ulonglong(f, m_row.m_work_completed);
+ else
+ f->set_null();
+ break;
+ case 9: /* WORK_ESTIMATED */
+ if (m_row.m_progress)
+ set_field_ulonglong(f, m_row.m_work_estimated);
+ else
+ f->set_null();
+ break;
+ case 10: /* NESTING_EVENT_ID */
if (m_row.m_nesting_event_id != 0)
set_field_ulonglong(f, m_row.m_nesting_event_id);
else
f->set_null();
break;
- case 9: /* NESTING_EVENT_TYPE */
+ case 11: /* NESTING_EVENT_TYPE */
if (m_row.m_nesting_event_id != 0)
set_field_enum(f, m_row.m_nesting_event_type);
else
@@ -275,20 +298,12 @@ int table_events_stages_current::rnd_next(void)
PFS_thread *pfs_thread;
PFS_events_stages *stage;
- for (m_pos.set_at(&m_next_pos);
- m_pos.m_index < thread_max;
- m_pos.next())
+ m_pos.set_at(&m_next_pos);
+ PFS_thread_iterator it= global_thread_container.iterate(m_pos.m_index);
+ pfs_thread= it.scan_next(& m_pos.m_index);
+ if (pfs_thread != NULL)
{
- pfs_thread= &thread_array[m_pos.m_index];
-
- if (! pfs_thread->m_lock.is_populated())
- {
- /* This thread does not exist */
- continue;
- }
-
stage= &pfs_thread->m_stage_current;
-
make_row(stage);
m_next_pos.set_after(&m_pos);
return 0;
@@ -303,15 +318,16 @@ int table_events_stages_current::rnd_pos(const void *pos)
PFS_events_stages *stage;
set_position(pos);
- DBUG_ASSERT(m_pos.m_index < thread_max);
- pfs_thread= &thread_array[m_pos.m_index];
- if (! pfs_thread->m_lock.is_populated())
- return HA_ERR_RECORD_DELETED;
+ pfs_thread= global_thread_container.get(m_pos.m_index);
+ if (pfs_thread != NULL)
+ {
+ stage= &pfs_thread->m_stage_current;
+ make_row(stage);
+ return 0;
+ }
- stage= &pfs_thread->m_stage_current;
- make_row(stage);
- return 0;
+ return HA_ERR_RECORD_DELETED;
}
int table_events_stages_current::delete_all_rows(void)
@@ -320,6 +336,12 @@ int table_events_stages_current::delete_all_rows(void)
return 0;
}
+ha_rows
+table_events_stages_current::get_row_count(void)
+{
+ return global_thread_container.get_row_count();
+}
+
PFS_engine_table* table_events_stages_history::create(void)
{
return new table_events_stages_history();
@@ -346,43 +368,40 @@ int table_events_stages_history::rnd_next(void)
{
PFS_thread *pfs_thread;
PFS_events_stages *stage;
+ bool has_more_thread= true;
if (events_stages_history_per_thread == 0)
return HA_ERR_END_OF_FILE;
for (m_pos.set_at(&m_next_pos);
- m_pos.m_index_1 < thread_max;
+ has_more_thread;
m_pos.next_thread())
{
- pfs_thread= &thread_array[m_pos.m_index_1];
-
- if (! pfs_thread->m_lock.is_populated())
- {
- /* This thread does not exist */
- continue;
- }
-
- if (m_pos.m_index_2 >= events_stages_history_per_thread)
+ pfs_thread= global_thread_container.get(m_pos.m_index_1, & has_more_thread);
+ if (pfs_thread != NULL)
{
- /* This thread does not have more (full) history */
- continue;
- }
+ if (m_pos.m_index_2 >= events_stages_history_per_thread)
+ {
+ /* This thread does not have more (full) history */
+ continue;
+ }
- if ( ! pfs_thread->m_stages_history_full &&
- (m_pos.m_index_2 >= pfs_thread->m_stages_history_index))
- {
- /* This thread does not have more (not full) history */
- continue;
- }
+ if ( ! pfs_thread->m_stages_history_full &&
+ (m_pos.m_index_2 >= pfs_thread->m_stages_history_index))
+ {
+ /* This thread does not have more (not full) history */
+ continue;
+ }
- stage= &pfs_thread->m_stages_history[m_pos.m_index_2];
+ stage= &pfs_thread->m_stages_history[m_pos.m_index_2];
- if (stage->m_class != NULL)
- {
- make_row(stage);
- /* Next iteration, look for the next history in this thread */
- m_next_pos.set_after(&m_pos);
- return 0;
+ if (stage->m_class != NULL)
+ {
+ make_row(stage);
+ /* Next iteration, look for the next history in this thread */
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
}
}
@@ -396,25 +415,26 @@ int table_events_stages_history::rnd_pos(const void *pos)
DBUG_ASSERT(events_stages_history_per_thread != 0);
set_position(pos);
- DBUG_ASSERT(m_pos.m_index_1 < thread_max);
- pfs_thread= &thread_array[m_pos.m_index_1];
-
- if (! pfs_thread->m_lock.is_populated())
- return HA_ERR_RECORD_DELETED;
DBUG_ASSERT(m_pos.m_index_2 < events_stages_history_per_thread);
- if ( ! pfs_thread->m_stages_history_full &&
- (m_pos.m_index_2 >= pfs_thread->m_stages_history_index))
- return HA_ERR_RECORD_DELETED;
+ pfs_thread= global_thread_container.get(m_pos.m_index_1);
+ if (pfs_thread != NULL)
+ {
+ if ( ! pfs_thread->m_stages_history_full &&
+ (m_pos.m_index_2 >= pfs_thread->m_stages_history_index))
+ return HA_ERR_RECORD_DELETED;
- stage= &pfs_thread->m_stages_history[m_pos.m_index_2];
+ stage= &pfs_thread->m_stages_history[m_pos.m_index_2];
- if (stage->m_class == NULL)
- return HA_ERR_RECORD_DELETED;
+ if (stage->m_class != NULL)
+ {
+ make_row(stage);
+ return 0;
+ }
+ }
- make_row(stage);
- return 0;
+ return HA_ERR_RECORD_DELETED;
}
int table_events_stages_history::delete_all_rows(void)
@@ -423,6 +443,12 @@ int table_events_stages_history::delete_all_rows(void)
return 0;
}
+ha_rows
+table_events_stages_history::get_row_count(void)
+{
+ return events_stages_history_per_thread * global_thread_container.get_row_count();
+}
+
PFS_engine_table* table_events_stages_history_long::create(void)
{
return new table_events_stages_history_long();
@@ -456,7 +482,7 @@ int table_events_stages_history_long::rnd_next(void)
if (events_stages_history_long_full)
limit= events_stages_history_long_size;
else
- limit= events_stages_history_long_index % events_stages_history_long_size;
+ limit= events_stages_history_long_index.m_u32 % events_stages_history_long_size;
for (m_pos.set_at(&m_next_pos); m_pos.m_index < limit; m_pos.next())
{
@@ -487,7 +513,7 @@ int table_events_stages_history_long::rnd_pos(const void *pos)
if (events_stages_history_long_full)
limit= events_stages_history_long_size;
else
- limit= events_stages_history_long_index % events_stages_history_long_size;
+ limit= events_stages_history_long_index.m_u32 % events_stages_history_long_size;
if (m_pos.m_index > limit)
return HA_ERR_RECORD_DELETED;
@@ -507,3 +533,9 @@ int table_events_stages_history_long::delete_all_rows(void)
return 0;
}
+ha_rows
+table_events_stages_history_long::get_row_count(void)
+{
+ return events_stages_history_long_size;
+}
+
diff --git a/storage/perfschema/table_events_stages.h b/storage/perfschema/table_events_stages.h
index ae8760cd953..16e3fc9651a 100644
--- a/storage/perfschema/table_events_stages.h
+++ b/storage/perfschema/table_events_stages.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -66,6 +66,11 @@ struct row_events_stages
char m_source[COL_SOURCE_SIZE];
/** Length in bytes of @c m_source. */
uint m_source_length;
+ bool m_progress;
+ /** Column WORK_COMPLETED. */
+ ulonglong m_work_completed;
+ /** Column WORK_ESTIMATED. */
+ ulonglong m_work_estimated;
};
/** Position of a cursor on PERFORMANCE_SCHEMA.EVENTS_STAGES_HISTORY. */
@@ -121,6 +126,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_init(bool scan);
virtual int rnd_next();
@@ -155,6 +161,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_init(bool scan);
virtual int rnd_next();
@@ -186,6 +193,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_init(bool scan);
virtual int rnd_next();
diff --git a/storage/perfschema/table_events_statements.cc b/storage/perfschema/table_events_statements.cc
index 16fc58d626d..24c2ff4ff74 100644
--- a/storage/perfschema/table_events_statements.cc
+++ b/storage/perfschema/table_events_statements.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2018, 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, version 2.0,
@@ -26,7 +26,7 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "table_events_statements.h"
#include "pfs_instr_class.h"
#include "pfs_instr.h"
@@ -35,6 +35,7 @@
#include "sp_head.h" /* TYPE_ENUM_FUNCTION, ... */
#include "table_helper.h"
#include "my_md5.h"
+#include "pfs_buffer_container.h"
THR_LOCK table_events_statements_current::m_table_lock;
@@ -43,11 +44,10 @@ table_events_statements_current::m_share=
{
{ C_STRING_WITH_LEN("events_statements_current") },
&pfs_truncatable_acl,
- &table_events_statements_current::create,
+ table_events_statements_current::create,
NULL, /* write_row */
- &table_events_statements_current::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ table_events_statements_current::delete_all_rows,
+ table_events_statements_current::get_row_count,
sizeof(pos_events_statements_current), /* ref length */
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE events_statements_current("
@@ -90,7 +90,9 @@ table_events_statements_current::m_share=
"NO_INDEX_USED BIGINT unsigned not null,"
"NO_GOOD_INDEX_USED BIGINT unsigned not null,"
"NESTING_EVENT_ID BIGINT unsigned,"
- "NESTING_EVENT_TYPE ENUM('STATEMENT', 'STAGE', 'WAIT'))") }
+ "NESTING_EVENT_TYPE ENUM('TRANSACTION', 'STATEMENT', 'STAGE', 'WAIT'),"
+ "NESTING_EVENT_LEVEL INT unsigned)") },
+ false /* perpetual */
};
THR_LOCK table_events_statements_history::m_table_lock;
@@ -100,11 +102,10 @@ table_events_statements_history::m_share=
{
{ C_STRING_WITH_LEN("events_statements_history") },
&pfs_truncatable_acl,
- &table_events_statements_history::create,
+ table_events_statements_history::create,
NULL, /* write_row */
- &table_events_statements_history::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ table_events_statements_history::delete_all_rows,
+ table_events_statements_history::get_row_count,
sizeof(pos_events_statements_history), /* ref length */
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE events_statements_history("
@@ -147,7 +148,9 @@ table_events_statements_history::m_share=
"NO_INDEX_USED BIGINT unsigned not null,"
"NO_GOOD_INDEX_USED BIGINT unsigned not null,"
"NESTING_EVENT_ID BIGINT unsigned,"
- "NESTING_EVENT_TYPE ENUM('STATEMENT', 'STAGE', 'WAIT'))") }
+ "NESTING_EVENT_TYPE ENUM('TRANSACTION', 'STATEMENT', 'STAGE', 'WAIT'),"
+ "NESTING_EVENT_LEVEL INT unsigned)") },
+ false /* perpetual */
};
THR_LOCK table_events_statements_history_long::m_table_lock;
@@ -157,11 +160,10 @@ table_events_statements_history_long::m_share=
{
{ C_STRING_WITH_LEN("events_statements_history_long") },
&pfs_truncatable_acl,
- &table_events_statements_history_long::create,
+ table_events_statements_history_long::create,
NULL, /* write_row */
- &table_events_statements_history_long::delete_all_rows,
- NULL, /* get_row_count */
- 10000, /* records */
+ table_events_statements_history_long::delete_all_rows,
+ table_events_statements_history_long::get_row_count,
sizeof(PFS_simple_index), /* ref length */
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE events_statements_history_long("
@@ -204,7 +206,9 @@ table_events_statements_history_long::m_share=
"NO_INDEX_USED BIGINT unsigned not null,"
"NO_GOOD_INDEX_USED BIGINT unsigned not null,"
"NESTING_EVENT_ID BIGINT unsigned,"
- "NESTING_EVENT_TYPE ENUM('STATEMENT', 'STAGE', 'WAIT'))") }
+ "NESTING_EVENT_TYPE ENUM('TRANSACTION', 'STATEMENT', 'STAGE', 'WAIT'),"
+ "NESTING_EVENT_LEVEL INT unsigned)") },
+ false /* perpetual */
};
table_events_statements_common::table_events_statements_common
@@ -220,8 +224,6 @@ table_events_statements_common::table_events_statements_common
void table_events_statements_common::make_row_part_1(PFS_events_statements *statement,
sql_digest_storage *digest)
{
- const char *base;
- const char *safe_source_file;
ulonglong timer_end;
m_row_exists= false;
@@ -236,6 +238,7 @@ void table_events_statements_common::make_row_part_1(PFS_events_statements *stat
m_row.m_end_event_id= statement->m_end_event_id;
m_row.m_nesting_event_id= statement->m_nesting_event_id;
m_row.m_nesting_event_type= statement->m_nesting_event_type;
+ m_row.m_nesting_event_level= statement->m_nesting_event_level;
if (m_row.m_end_event_id == 0)
{
@@ -287,15 +290,18 @@ void table_events_statements_common::make_row_part_1(PFS_events_statements *stat
if (m_row.m_current_schema_name_length > 0)
memcpy(m_row.m_current_schema_name, statement->m_current_schema_name, m_row.m_current_schema_name_length);
- safe_source_file= statement->m_source_file;
- if (unlikely(safe_source_file == NULL))
- return;
+ m_row.m_object_type= statement->m_sp_type;
+
+ m_row.m_schema_name_length= statement->m_schema_name_length;
+ if (m_row.m_schema_name_length > 0)
+ memcpy(m_row.m_schema_name, statement->m_schema_name, m_row.m_schema_name_length);
- base= base_name(safe_source_file);
- m_row.m_source_length= (uint)my_snprintf(m_row.m_source, sizeof(m_row.m_source),
- "%s:%d", base, statement->m_source_line);
- if (m_row.m_source_length > sizeof(m_row.m_source))
- m_row.m_source_length= sizeof(m_row.m_source);
+ m_row.m_object_name_length= statement->m_object_name_length;
+ if (m_row.m_object_name_length > 0)
+ memcpy(m_row.m_object_name, statement->m_object_name, m_row.m_object_name_length);
+
+ /* Disable source file and line to avoid stale __FILE__ pointers. */
+ m_row.m_source_length= 0;
memcpy(m_row.m_message_text, statement->m_message_text, sizeof(m_row.m_message_text));
m_row.m_sql_errno= statement->m_sql_errno;
@@ -319,6 +325,7 @@ void table_events_statements_common::make_row_part_1(PFS_events_statements *stat
m_row.m_sort_scan= statement->m_sort_scan;
m_row.m_no_index_used= statement->m_no_index_used;
m_row.m_no_good_index_used= statement->m_no_good_index_used;
+
/*
Making a copy of digest storage.
*/
@@ -328,7 +335,6 @@ void table_events_statements_common::make_row_part_1(PFS_events_statements *stat
return;
}
-
void table_events_statements_common::make_row_part_2(const sql_digest_storage *digest)
{
/*
@@ -445,18 +451,30 @@ int table_events_statements_common::read_row_values(TABLE *table,
break;
case 12: /* CURRENT_SCHEMA */
if (m_row.m_current_schema_name_length)
- set_field_varchar_utf8(f, m_row.m_current_schema_name, m_row.m_current_schema_name_length);
+ set_field_varchar_utf8(f, m_row.m_current_schema_name,
+ m_row.m_current_schema_name_length);
else
f->set_null();
break;
- case 13: /* OBJECT_TYPE */
- f->set_null();
+ case 13: /* OBJECT_TYPE */
+ if (m_row.m_object_name_length > 0)
+ set_field_object_type(f, m_row.m_object_type);
+ else
+ f->set_null();
break;
case 14: /* OBJECT_SCHEMA */
- f->set_null();
+ if (m_row.m_schema_name_length)
+ set_field_varchar_utf8(f, m_row.m_schema_name,
+ m_row.m_schema_name_length);
+ else
+ f->set_null();
break;
case 15: /* OBJECT_NAME */
- f->set_null();
+ if (m_row.m_object_name_length)
+ set_field_varchar_utf8(f, m_row.m_object_name,
+ m_row.m_object_name_length);
+ else
+ f->set_null();
break;
case 16: /* OBJECT_INSTANCE_BEGIN */
f->set_null();
@@ -471,7 +489,7 @@ int table_events_statements_common::read_row_values(TABLE *table,
f->set_null();
break;
case 19: /* MESSAGE_TEXT */
- len= (uint)strlen(m_row.m_message_text);
+ len= strlen(m_row.m_message_text);
if (len)
set_field_varchar_utf8(f, m_row.m_message_text, len);
else
@@ -543,6 +561,9 @@ int table_events_statements_common::read_row_values(TABLE *table,
else
f->set_null();
break;
+ case 40: /* NESTING_EVENT_LEVEL */
+ set_field_ulong(f, m_row.m_nesting_event_level);
+ break;
default:
DBUG_ASSERT(false);
}
@@ -577,39 +598,36 @@ int table_events_statements_current::rnd_next(void)
{
PFS_thread *pfs_thread;
PFS_events_statements *statement;
+ bool has_more_thread= true;
for (m_pos.set_at(&m_next_pos);
- m_pos.m_index_1 < thread_max;
+ has_more_thread;
m_pos.next_thread())
{
- pfs_thread= &thread_array[m_pos.m_index_1];
-
- if (! pfs_thread->m_lock.is_populated())
+ pfs_thread= global_thread_container.get(m_pos.m_index_1, & has_more_thread);
+ if (pfs_thread != NULL)
{
- /* This thread does not exist */
- continue;
- }
-
- uint safe_events_statements_count= pfs_thread->m_events_statements_count;
+ uint safe_events_statements_count= pfs_thread->m_events_statements_count;
- if (safe_events_statements_count == 0)
- {
- /* Display the last top level statement, when completed */
- if (m_pos.m_index_2 >= 1)
- continue;
- }
- else
- {
- /* Display all pending statements, when in progress */
- if (m_pos.m_index_2 >= safe_events_statements_count)
- continue;
- }
+ if (safe_events_statements_count == 0)
+ {
+ /* Display the last top level statement, when completed */
+ if (m_pos.m_index_2 >= 1)
+ continue;
+ }
+ else
+ {
+ /* Display all pending statements, when in progress */
+ if (m_pos.m_index_2 >= safe_events_statements_count)
+ continue;
+ }
- statement= &pfs_thread->m_statement_stack[m_pos.m_index_2];
+ statement= &pfs_thread->m_statement_stack[m_pos.m_index_2];
- make_row(pfs_thread, statement);
- m_next_pos.set_after(&m_pos);
- return 0;
+ make_row(pfs_thread, statement);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
}
return HA_ERR_END_OF_FILE;
@@ -621,44 +639,45 @@ int table_events_statements_current::rnd_pos(const void *pos)
PFS_events_statements *statement;
set_position(pos);
- DBUG_ASSERT(m_pos.m_index_1 < thread_max);
- pfs_thread= &thread_array[m_pos.m_index_1];
-
- if (! pfs_thread->m_lock.is_populated())
- return HA_ERR_RECORD_DELETED;
-
- uint safe_events_statements_count= pfs_thread->m_events_statements_count;
- if (safe_events_statements_count == 0)
- {
- /* Display the last top level statement, when completed */
- if (m_pos.m_index_2 >= 1)
- return HA_ERR_RECORD_DELETED;
- }
- else
+ pfs_thread= global_thread_container.get(m_pos.m_index_1);
+ if (pfs_thread != NULL)
{
- /* Display all pending statements, when in progress */
- if (m_pos.m_index_2 >= safe_events_statements_count)
- return HA_ERR_RECORD_DELETED;
- }
+ uint safe_events_statements_count= pfs_thread->m_events_statements_count;
- DBUG_ASSERT(m_pos.m_index_2 < statement_stack_max);
+ if (safe_events_statements_count == 0)
+ {
+ /* Display the last top level statement, when completed */
+ if (m_pos.m_index_2 >= 1)
+ return HA_ERR_RECORD_DELETED;
+ }
+ else
+ {
+ /* Display all pending statements, when in progress */
+ if (m_pos.m_index_2 >= safe_events_statements_count)
+ return HA_ERR_RECORD_DELETED;
+ }
- statement= &pfs_thread->m_statement_stack[m_pos.m_index_2];
+ DBUG_ASSERT(m_pos.m_index_2 < statement_stack_max);
- if (statement->m_class == NULL)
- return HA_ERR_RECORD_DELETED;
+ statement= &pfs_thread->m_statement_stack[m_pos.m_index_2];
- make_row(pfs_thread, statement);
- return 0;
+ if (statement->m_class != NULL)
+ {
+ make_row(pfs_thread, statement);
+ return 0;
+ }
+ }
+
+ return HA_ERR_RECORD_DELETED;
}
void table_events_statements_current::make_row(PFS_thread *pfs_thread,
PFS_events_statements *statement)
{
sql_digest_storage digest;
- pfs_lock lock;
- pfs_lock stmt_lock;
+ pfs_optimistic_state lock;
+ pfs_optimistic_state stmt_lock;
digest.reset(m_token_array, MAX_DIGEST_STORAGE_SIZE);
/* Protect this reader against thread termination. */
@@ -684,6 +703,12 @@ int table_events_statements_current::delete_all_rows(void)
return 0;
}
+ha_rows
+table_events_statements_current::get_row_count(void)
+{
+ return global_thread_container.get_row_count() * statement_stack_max;
+}
+
PFS_engine_table* table_events_statements_history::create(void)
{
return new table_events_statements_history();
@@ -710,43 +735,40 @@ int table_events_statements_history::rnd_next(void)
{
PFS_thread *pfs_thread;
PFS_events_statements *statement;
+ bool has_more_thread= true;
if (events_statements_history_per_thread == 0)
return HA_ERR_END_OF_FILE;
for (m_pos.set_at(&m_next_pos);
- m_pos.m_index_1 < thread_max;
+ has_more_thread;
m_pos.next_thread())
{
- pfs_thread= &thread_array[m_pos.m_index_1];
-
- if (! pfs_thread->m_lock.is_populated())
- {
- /* This thread does not exist */
- continue;
- }
-
- if (m_pos.m_index_2 >= events_statements_history_per_thread)
+ pfs_thread= global_thread_container.get(m_pos.m_index_1, & has_more_thread);
+ if (pfs_thread != NULL)
{
- /* This thread does not have more (full) history */
- continue;
- }
+ if (m_pos.m_index_2 >= events_statements_history_per_thread)
+ {
+ /* This thread does not have more (full) history */
+ continue;
+ }
- if ( ! pfs_thread->m_statements_history_full &&
- (m_pos.m_index_2 >= pfs_thread->m_statements_history_index))
- {
- /* This thread does not have more (not full) history */
- continue;
- }
+ if ( ! pfs_thread->m_statements_history_full &&
+ (m_pos.m_index_2 >= pfs_thread->m_statements_history_index))
+ {
+ /* This thread does not have more (not full) history */
+ continue;
+ }
- statement= &pfs_thread->m_statements_history[m_pos.m_index_2];
+ statement= &pfs_thread->m_statements_history[m_pos.m_index_2];
- if (statement->m_class != NULL)
- {
- make_row(pfs_thread, statement);
- /* Next iteration, look for the next history in this thread */
- m_next_pos.set_after(&m_pos);
- return 0;
+ if (statement->m_class != NULL)
+ {
+ make_row(pfs_thread, statement);
+ /* Next iteration, look for the next history in this thread */
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
}
}
@@ -760,32 +782,32 @@ int table_events_statements_history::rnd_pos(const void *pos)
DBUG_ASSERT(events_statements_history_per_thread != 0);
set_position(pos);
- DBUG_ASSERT(m_pos.m_index_1 < thread_max);
- pfs_thread= &thread_array[m_pos.m_index_1];
- if (! pfs_thread->m_lock.is_populated())
- return HA_ERR_RECORD_DELETED;
-
- DBUG_ASSERT(m_pos.m_index_2 < events_statements_history_per_thread);
-
- if ( ! pfs_thread->m_statements_history_full &&
- (m_pos.m_index_2 >= pfs_thread->m_statements_history_index))
- return HA_ERR_RECORD_DELETED;
+ pfs_thread= global_thread_container.get(m_pos.m_index_1);
+ if (pfs_thread != NULL)
+ {
+ DBUG_ASSERT(m_pos.m_index_2 < events_statements_history_per_thread);
- statement= &pfs_thread->m_statements_history[m_pos.m_index_2];
+ if ( ! pfs_thread->m_statements_history_full &&
+ (m_pos.m_index_2 >= pfs_thread->m_statements_history_index))
+ return HA_ERR_RECORD_DELETED;
- if (statement->m_class == NULL)
- return HA_ERR_RECORD_DELETED;
+ statement= &pfs_thread->m_statements_history[m_pos.m_index_2];
+ if (statement->m_class != NULL)
+ {
+ make_row(pfs_thread, statement);
+ return 0;
+ }
+ }
- make_row(pfs_thread, statement);
- return 0;
+ return HA_ERR_RECORD_DELETED;
}
void table_events_statements_history::make_row(PFS_thread *pfs_thread,
PFS_events_statements *statement)
{
sql_digest_storage digest;
- pfs_lock lock;
+ pfs_optimistic_state lock;
digest.reset(m_token_array, MAX_DIGEST_STORAGE_SIZE);
/* Protect this reader against thread termination. */
@@ -799,15 +821,22 @@ void table_events_statements_history::make_row(PFS_thread *pfs_thread,
return;
}
table_events_statements_common::make_row_part_2(&digest);
- return;
+ return;
}
+
int table_events_statements_history::delete_all_rows(void)
{
reset_events_statements_history();
return 0;
}
+ha_rows
+table_events_statements_history::get_row_count(void)
+{
+ return events_statements_history_per_thread * global_thread_container.get_row_count();
+}
+
PFS_engine_table* table_events_statements_history_long::create(void)
{
return new table_events_statements_history_long();
@@ -833,7 +862,7 @@ int table_events_statements_history_long::rnd_init(bool scan)
int table_events_statements_history_long::rnd_next(void)
{
PFS_events_statements *statement;
- size_t limit;
+ uint limit;
if (events_statements_history_long_size == 0)
return HA_ERR_END_OF_FILE;
@@ -841,7 +870,7 @@ int table_events_statements_history_long::rnd_next(void)
if (events_statements_history_long_full)
limit= events_statements_history_long_size;
else
- limit= events_statements_history_long_index % events_statements_history_long_size;
+ limit= events_statements_history_long_index.m_u32 % events_statements_history_long_size;
for (m_pos.set_at(&m_next_pos); m_pos.m_index < limit; m_pos.next())
{
@@ -862,7 +891,7 @@ int table_events_statements_history_long::rnd_next(void)
int table_events_statements_history_long::rnd_pos(const void *pos)
{
PFS_events_statements *statement;
- size_t limit;
+ uint limit;
if (events_statements_history_long_size == 0)
return HA_ERR_RECORD_DELETED;
@@ -872,7 +901,7 @@ int table_events_statements_history_long::rnd_pos(const void *pos)
if (events_statements_history_long_full)
limit= events_statements_history_long_size;
else
- limit= events_statements_history_long_index % events_statements_history_long_size;
+ limit= events_statements_history_long_index.m_u32 % events_statements_history_long_size;
if (m_pos.m_index >= limit)
return HA_ERR_RECORD_DELETED;
@@ -903,3 +932,9 @@ int table_events_statements_history_long::delete_all_rows(void)
return 0;
}
+ha_rows
+table_events_statements_history_long::get_row_count(void)
+{
+ return events_statements_history_long_size;
+}
+
diff --git a/storage/perfschema/table_events_statements.h b/storage/perfschema/table_events_statements.h
index cec28628f3e..02127cadecc 100644
--- a/storage/perfschema/table_events_statements.h
+++ b/storage/perfschema/table_events_statements.h
@@ -53,6 +53,8 @@ struct row_events_statements
ulonglong m_nesting_event_id;
/** Column NESTING_EVENT_TYPE. */
enum_event_type m_nesting_event_type;
+ /** Column NESTING_EVENT_LEVEL. */
+ uint m_nesting_event_level;
/** Column EVENT_NAME. */
const char *m_name;
/** Length in bytes of @c m_name. */
@@ -73,11 +75,23 @@ struct row_events_statements
String m_sqltext;
/** Column DIGEST and DIGEST_TEXT. */
PFS_digest_row m_digest;
- /** Column CURRENT_SCHEMA. */
+ /** Column CURRENT_SCHEMA. */
char m_current_schema_name[NAME_LEN];
/** Length in bytes of @c m_current_schema_name. */
uint m_current_schema_name_length;
+ /** Column OBJECT_TYPE. */
+ enum_object_type m_object_type;
+ /** Column OBJECT_SCHEMA. */
+ char m_schema_name[NAME_LEN];
+ /** Length in bytes of @c m_schema_name. */
+ uint m_schema_name_length;
+ /** Column OBJECT_NAME. */
+ char m_object_name[NAME_LEN];
+ /** Length in bytes of @c m_object_name. */
+ uint m_object_name_length;
+
+
/** Column MESSAGE_TEXT. */
char m_message_text[MYSQL_ERRMSG_SIZE+1];
/** Column MYSQL_ERRNO. */
@@ -199,6 +213,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_init(bool scan);
virtual int rnd_next();
@@ -235,6 +250,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_init(bool scan);
virtual int rnd_next();
@@ -268,6 +284,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_init(bool scan);
virtual int rnd_next();
diff --git a/storage/perfschema/table_events_transactions.cc b/storage/perfschema/table_events_transactions.cc
new file mode 100644
index 00000000000..31d146fa11a
--- /dev/null
+++ b/storage/perfschema/table_events_transactions.cc
@@ -0,0 +1,718 @@
+/* Copyright (c) 2010, 2018, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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/table_events_transactions.cc
+ Table EVENTS_TRANSACTIONS_xxx (implementation).
+*/
+
+#include "my_global.h"
+#include "my_thread.h"
+#include "table_events_transactions.h"
+#include "pfs_instr_class.h"
+#include "pfs_instr.h"
+#include "pfs_events_transactions.h"
+#include "pfs_timer.h"
+#include "table_helper.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
+//#include "xa.h"
+
+THR_LOCK table_events_transactions_current::m_table_lock;
+
+PFS_engine_table_share
+table_events_transactions_current::m_share=
+{
+ { C_STRING_WITH_LEN("events_transactions_current") },
+ &pfs_truncatable_acl,
+ table_events_transactions_current::create,
+ NULL, /* write_row */
+ table_events_transactions_current::delete_all_rows,
+ table_events_transactions_current::get_row_count,
+ sizeof(PFS_simple_index), /* ref length */
+ &m_table_lock,
+ { C_STRING_WITH_LEN("CREATE TABLE events_transactions_current("
+ "THREAD_ID BIGINT unsigned not null,"
+ "EVENT_ID BIGINT unsigned not null,"
+ "END_EVENT_ID BIGINT unsigned,"
+ "EVENT_NAME VARCHAR(128) not null,"
+ "STATE ENUM('ACTIVE', 'COMMITTED', 'ROLLED BACK'),"
+ "TRX_ID BIGINT unsigned,"
+ "GTID VARCHAR(64),"
+ "XID_FORMAT_ID INTEGER,"
+ "XID_GTRID VARCHAR(130),"
+ "XID_BQUAL VARCHAR(130),"
+ "XA_STATE VARCHAR(64),"
+ "SOURCE VARCHAR(64),"
+ "TIMER_START BIGINT unsigned,"
+ "TIMER_END BIGINT unsigned,"
+ "TIMER_WAIT BIGINT unsigned,"
+ "ACCESS_MODE ENUM('READ ONLY', 'READ WRITE'),"
+ "ISOLATION_LEVEL VARCHAR(64),"
+ "AUTOCOMMIT ENUM('YES','NO') not null,"
+ "NUMBER_OF_SAVEPOINTS BIGINT unsigned,"
+ "NUMBER_OF_ROLLBACK_TO_SAVEPOINT BIGINT unsigned,"
+ "NUMBER_OF_RELEASE_SAVEPOINT BIGINT unsigned,"
+ "OBJECT_INSTANCE_BEGIN BIGINT unsigned,"
+ "NESTING_EVENT_ID BIGINT unsigned,"
+ "NESTING_EVENT_TYPE ENUM('TRANSACTION', 'STATEMENT', 'STAGE', 'WAIT'))")},
+ false /* perpetual */
+};
+
+THR_LOCK table_events_transactions_history::m_table_lock;
+
+PFS_engine_table_share
+table_events_transactions_history::m_share=
+{
+ { C_STRING_WITH_LEN("events_transactions_history") },
+ &pfs_truncatable_acl,
+ table_events_transactions_history::create,
+ NULL, /* write_row */
+ table_events_transactions_history::delete_all_rows,
+ table_events_transactions_history::get_row_count,
+ sizeof(pos_events_transactions_history), /* ref length */
+ &m_table_lock,
+ { C_STRING_WITH_LEN("CREATE TABLE events_transactions_history("
+ "THREAD_ID BIGINT unsigned not null,"
+ "EVENT_ID BIGINT unsigned not null,"
+ "END_EVENT_ID BIGINT unsigned,"
+ "EVENT_NAME VARCHAR(128) not null,"
+ "STATE ENUM('ACTIVE', 'COMMITTED', 'ROLLED BACK'),"
+ "TRX_ID BIGINT unsigned,"
+ "GTID VARCHAR(64),"
+ "XID_FORMAT_ID INTEGER,"
+ "XID_GTRID VARCHAR(130),"
+ "XID_BQUAL VARCHAR(130),"
+ "XA_STATE VARCHAR(64),"
+ "SOURCE VARCHAR(64),"
+ "TIMER_START BIGINT unsigned,"
+ "TIMER_END BIGINT unsigned,"
+ "TIMER_WAIT BIGINT unsigned,"
+ "ACCESS_MODE ENUM('READ ONLY', 'READ WRITE'),"
+ "ISOLATION_LEVEL VARCHAR(64),"
+ "AUTOCOMMIT ENUM('YES','NO') not null,"
+ "NUMBER_OF_SAVEPOINTS BIGINT unsigned,"
+ "NUMBER_OF_ROLLBACK_TO_SAVEPOINT BIGINT unsigned,"
+ "NUMBER_OF_RELEASE_SAVEPOINT BIGINT unsigned,"
+ "OBJECT_INSTANCE_BEGIN BIGINT unsigned,"
+ "NESTING_EVENT_ID BIGINT unsigned,"
+ "NESTING_EVENT_TYPE ENUM('TRANSACTION', 'STATEMENT', 'STAGE', 'WAIT'))")},
+ false /* perpetual */
+};
+
+THR_LOCK table_events_transactions_history_long::m_table_lock;
+
+PFS_engine_table_share
+table_events_transactions_history_long::m_share=
+{
+ { C_STRING_WITH_LEN("events_transactions_history_long") },
+ &pfs_truncatable_acl,
+ table_events_transactions_history_long::create,
+ NULL, /* write_row */
+ table_events_transactions_history_long::delete_all_rows,
+ table_events_transactions_history_long::get_row_count,
+ sizeof(PFS_simple_index), /* ref length */
+ &m_table_lock,
+ { C_STRING_WITH_LEN("CREATE TABLE events_transactions_history_long("
+ "THREAD_ID BIGINT unsigned not null,"
+ "EVENT_ID BIGINT unsigned not null,"
+ "END_EVENT_ID BIGINT unsigned,"
+ "EVENT_NAME VARCHAR(128) not null,"
+ "STATE ENUM('ACTIVE', 'COMMITTED', 'ROLLED BACK'),"
+ "TRX_ID BIGINT unsigned,"
+ "GTID VARCHAR(64),"
+ "XID_FORMAT_ID INTEGER,"
+ "XID_GTRID VARCHAR(130),"
+ "XID_BQUAL VARCHAR(130),"
+ "XA_STATE VARCHAR(64),"
+ "SOURCE VARCHAR(64),"
+ "TIMER_START BIGINT unsigned,"
+ "TIMER_END BIGINT unsigned,"
+ "TIMER_WAIT BIGINT unsigned,"
+ "ACCESS_MODE ENUM('READ ONLY', 'READ WRITE'),"
+ "ISOLATION_LEVEL VARCHAR(64),"
+ "AUTOCOMMIT ENUM('YES','NO') not null,"
+ "NUMBER_OF_SAVEPOINTS BIGINT unsigned,"
+ "NUMBER_OF_ROLLBACK_TO_SAVEPOINT BIGINT unsigned,"
+ "NUMBER_OF_RELEASE_SAVEPOINT BIGINT unsigned,"
+ "OBJECT_INSTANCE_BEGIN BIGINT unsigned,"
+ "NESTING_EVENT_ID BIGINT unsigned,"
+ "NESTING_EVENT_TYPE ENUM('TRANSACTION', 'STATEMENT', 'STAGE', 'WAIT'))")},
+ false /* perpetual */
+};
+
+table_events_transactions_common::table_events_transactions_common
+(const PFS_engine_table_share *share, void *pos)
+ : PFS_engine_table(share, pos),
+ m_row_exists(false)
+{}
+
+/**
+ Build a row.
+ @param transaction the transaction the cursor is reading
+*/
+void table_events_transactions_common::make_row(PFS_events_transactions *transaction)
+{
+ ulonglong timer_end;
+
+ m_row_exists= false;
+
+ PFS_transaction_class *unsafe= (PFS_transaction_class*) transaction->m_class;
+ PFS_transaction_class *klass= sanitize_transaction_class(unsafe);
+ if (unlikely(klass == NULL))
+ return;
+
+ m_row.m_thread_internal_id= transaction->m_thread_internal_id;
+ m_row.m_event_id= transaction->m_event_id;
+ m_row.m_end_event_id= transaction->m_end_event_id;
+ m_row.m_nesting_event_id= transaction->m_nesting_event_id;
+ m_row.m_nesting_event_type= transaction->m_nesting_event_type;
+
+ if (m_row.m_end_event_id == 0)
+ {
+ timer_end= get_timer_raw_value(transaction_timer);
+ }
+ else
+ {
+ timer_end= transaction->m_timer_end;
+ }
+
+ m_normalizer->to_pico(transaction->m_timer_start, timer_end,
+ &m_row.m_timer_start, &m_row.m_timer_end, &m_row.m_timer_wait);
+ m_row.m_name= klass->m_name;
+ m_row.m_name_length= klass->m_name_length;
+
+ /* Disable source file and line to avoid stale __FILE__ pointers. */
+ m_row.m_source_length= 0;
+
+ /* A GTID consists of the SID (source id) and GNO (transaction number).
+ The SID is stored in transaction->m_sid and the GNO is stored in
+ transaction->m_gtid_spec.gno.
+
+ On a master, the GTID is assigned when the transaction commit.
+ On a slave, the GTID is assigned before the transaction starts.
+ If GTID_MODE = OFF, all transactions have the special GTID
+ 'ANONYMOUS'.
+
+ Therefore, a transaction can be in three different states wrt GTIDs:
+ - Before the GTID has been assigned, the state is 'AUTOMATIC'.
+ On a master, this is the state until the transaction commits.
+ On a slave, this state does not appear.
+ - If GTID_MODE = ON, and a GTID is assigned, the GTID is a string
+ of the form 'UUID:NUMBER'.
+ - If GTID_MODE = OFF, and a GTID is assigned, the GTID is a string
+ of the form 'ANONYMOUS'.
+
+ The Gtid_specification contains the GNO, as well as a type code
+ that specifies which of the three modes is currently in effect.
+ Given a SID, it can generate the textual representation of the
+ GTID.
+ */
+ //rpl_sid *sid= &transaction->m_sid;
+ Gtid_specification *gtid_spec= &transaction->m_gtid_spec;
+ m_row.m_gtid_length= gtid_spec->to_string(m_row.m_gtid);
+
+ m_row.m_xid= transaction->m_xid;
+ m_row.m_isolation_level= transaction->m_isolation_level;
+ m_row.m_read_only= transaction->m_read_only;
+ m_row.m_trxid= transaction->m_trxid;
+ m_row.m_state= transaction->m_state;
+ m_row.m_xa_state= transaction->m_xa_state;
+ m_row.m_xa= transaction->m_xa;
+ m_row.m_autocommit= transaction->m_autocommit;
+ m_row.m_savepoint_count= transaction->m_savepoint_count;
+ m_row.m_rollback_to_savepoint_count= transaction->m_rollback_to_savepoint_count;
+ m_row.m_release_savepoint_count= transaction->m_release_savepoint_count;
+ m_row_exists= true;
+ return;
+}
+
+/** Size of XID converted to null-terminated hex string prefixed with 0x. */
+static const ulong XID_BUFFER_SIZE= XIDDATASIZE*2 + 2 + 1;
+
+/**
+ Convert the XID to HEX string prefixed by '0x'
+
+ @param[out] buf output hex string buffer, null-terminated
+ @param buf_len size of buffer, must be at least @c XID_BUFFER_SIZE
+ @param xid XID structure
+ @param offset offset into XID.data[]
+ @param length number of bytes to process
+ @return number of bytes in hex string
+*/
+static uint xid_to_hex(char *buf, size_t buf_len, PSI_xid *xid, size_t offset, size_t length)
+{
+ DBUG_ASSERT(buf_len >= XID_BUFFER_SIZE);
+ DBUG_ASSERT(offset + length <= XIDDATASIZE);
+ *buf++= '0';
+ *buf++= 'x';
+ return bin_to_hex_str(buf, buf_len-2, (char*)(xid->data + offset), length) + 2;
+}
+
+/**
+ Store the XID in printable format if possible, otherwise convert
+ to a string of hex digits.
+
+ @param field Record field
+ @param xid XID structure
+ @param offset offset into XID.data[]
+ @param length number of bytes to process
+*/
+static void xid_store(Field *field, PSI_xid *xid, size_t offset, size_t length)
+{
+ DBUG_ASSERT(!xid->is_null());
+ if (xid_printable(xid, offset, length))
+ {
+ field->store(xid->data + offset, length, &my_charset_bin);
+ }
+ else
+ {
+ /*
+ xid_buf contains enough space for 0x followed by hex representation of
+ the binary XID data and one null termination character.
+ */
+ char xid_buf[XID_BUFFER_SIZE];
+
+ size_t xid_str_len= xid_to_hex(xid_buf, sizeof(xid_buf), xid, offset, length);
+ field->store(xid_buf, xid_str_len, &my_charset_bin);
+ }
+}
+
+static void xid_store_bqual(Field *field, PSI_xid *xid)
+{
+ xid_store(field, xid, xid->gtrid_length, xid->bqual_length);
+}
+
+static void xid_store_gtrid(Field *field, PSI_xid *xid)
+{
+ xid_store(field, xid, 0, xid->gtrid_length);
+}
+
+int table_events_transactions_common::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 == 3);
+ buf[0]= 0;
+ buf[1]= 0;
+ buf[2]= 0;
+
+ for (; (f= *fields) ; fields++)
+ {
+ if (read_all || bitmap_is_set(table->read_set, f->field_index))
+ {
+ switch(f->field_index)
+ {
+ case 0: /* THREAD_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);
+ break;
+ case 2: /* END_EVENT_ID */
+ if (m_row.m_end_event_id > 0)
+ set_field_ulonglong(f, m_row.m_end_event_id - 1);
+ else
+ f->set_null();
+ break;
+ case 3: /* EVENT_NAME */
+ set_field_varchar_utf8(f, m_row.m_name, m_row.m_name_length);
+ break;
+ case 4: /* STATE */
+ set_field_enum(f, m_row.m_state);
+ break;
+ case 5: /* TRX_ID */
+ if (m_row.m_trxid != 0)
+ set_field_ulonglong(f, m_row.m_trxid);
+ else
+ f->set_null();
+ break;
+ case 6: /* GTID */
+ set_field_varchar_utf8(f, m_row.m_gtid, m_row.m_gtid_length);
+ break;
+ case 7: /* XID_FORMAT_ID */
+ if (!m_row.m_xa || m_row.m_xid.is_null())
+ f->set_null();
+ else
+ set_field_long(f, m_row.m_xid.formatID);
+ break;
+ case 8: /* XID_GTRID */
+ if (!m_row.m_xa || m_row.m_xid.is_null() || m_row.m_xid.gtrid_length <= 0)
+ f->set_null();
+ else
+ xid_store_gtrid(f, &m_row.m_xid);
+ break;
+ case 9: /* XID_BQUAL */
+ if (!m_row.m_xa || m_row.m_xid.is_null() || m_row.m_xid.bqual_length <= 0)
+ f->set_null();
+ else
+ xid_store_bqual(f, &m_row.m_xid);
+ break;
+ case 10: /* XA STATE */
+ if (!m_row.m_xa || m_row.m_xid.is_null())
+ f->set_null();
+ else
+ set_field_xa_state(f, m_row.m_xa_state);
+ break;
+ case 11: /* SOURCE */
+ set_field_varchar_utf8(f, m_row.m_source, m_row.m_source_length);
+ break;
+ case 12: /* TIMER_START */
+ if (m_row.m_timer_start != 0)
+ set_field_ulonglong(f, m_row.m_timer_start);
+ else
+ f->set_null();
+ break;
+ case 13: /* TIMER_END */
+ if (m_row.m_timer_end != 0)
+ set_field_ulonglong(f, m_row.m_timer_end);
+ else
+ f->set_null();
+ break;
+ case 14: /* TIMER_WAIT */
+ if (m_row.m_timer_wait != 0)
+ set_field_ulonglong(f, m_row.m_timer_wait);
+ else
+ f->set_null();
+ break;
+ case 15: /* ACCESS_MODE */
+ set_field_enum(f, m_row.m_read_only ? TRANS_MODE_READ_ONLY
+ : TRANS_MODE_READ_WRITE);
+ break;
+ case 16: /* ISOLATION_LEVEL */
+ set_field_isolation_level(f, m_row.m_isolation_level);
+ break;
+ case 17: /* AUTOCOMMIT */
+ set_field_enum(f, m_row.m_autocommit ? ENUM_YES : ENUM_NO);
+ break;
+ case 18: /* NUMBER_OF_SAVEPOINTS */
+ set_field_ulonglong(f, m_row.m_savepoint_count);
+ break;
+ case 19: /* NUMBER_OF_ROLLBACK_TO_SAVEPOINT */
+ set_field_ulonglong(f, m_row.m_rollback_to_savepoint_count);
+ break;
+ case 20: /* NUMBER_OF_RELEASE_SAVEPOINT */
+ set_field_ulonglong(f, m_row.m_release_savepoint_count);
+ break;
+ case 21: /* OBJECT_INSTANCE_BEGIN */
+ f->set_null();
+ break;
+ case 22: /* NESTING_EVENT_ID */
+ if (m_row.m_nesting_event_id != 0)
+ set_field_ulonglong(f, m_row.m_nesting_event_id);
+ else
+ f->set_null();
+ break;
+ case 23: /* NESTING_EVENT_TYPE */
+ if (m_row.m_nesting_event_id != 0)
+ set_field_enum(f, m_row.m_nesting_event_type);
+ else
+ f->set_null();
+ break;
+ default:
+ DBUG_ASSERT(false);
+ }
+ }
+ }
+ return 0;
+}
+
+PFS_engine_table* table_events_transactions_current::create(void)
+{
+ return new table_events_transactions_current();
+}
+
+table_events_transactions_current::table_events_transactions_current()
+ : table_events_transactions_common(&m_share, &m_pos),
+ m_pos(0), m_next_pos(0)
+{}
+
+void table_events_transactions_current::reset_position(void)
+{
+ m_pos.m_index= 0;
+ m_next_pos.m_index= 0;
+}
+
+int table_events_transactions_current::rnd_init(bool scan)
+{
+ m_normalizer= time_normalizer::get(transaction_timer);
+ return 0;
+}
+
+int table_events_transactions_current::rnd_next(void)
+{
+ PFS_thread *pfs_thread;
+ PFS_events_transactions *transaction;
+ bool has_more_thread= true;
+
+ for (m_pos.set_at(&m_next_pos);
+ has_more_thread;
+ m_pos.next())
+ {
+ pfs_thread= global_thread_container.get(m_pos.m_index, & has_more_thread);
+ if (pfs_thread != NULL)
+ {
+ transaction= &pfs_thread->m_transaction_current;
+ make_row(transaction);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+ }
+
+ return HA_ERR_END_OF_FILE;
+}
+
+int table_events_transactions_current::rnd_pos(const void *pos)
+{
+ PFS_thread *pfs_thread;
+ PFS_events_transactions *transaction;
+
+ set_position(pos);
+
+ pfs_thread= global_thread_container.get(m_pos.m_index);
+ if (pfs_thread != NULL)
+ {
+ transaction= &pfs_thread->m_transaction_current;
+ if (transaction->m_class != NULL)
+ {
+ make_row(transaction);
+ return 0;
+ }
+ }
+
+ return HA_ERR_RECORD_DELETED;
+}
+
+int table_events_transactions_current::delete_all_rows(void)
+{
+ reset_events_transactions_current();
+ return 0;
+}
+
+ha_rows
+table_events_transactions_current::get_row_count(void)
+{
+ return global_thread_container.get_row_count();
+}
+
+PFS_engine_table* table_events_transactions_history::create(void)
+{
+ return new table_events_transactions_history();
+}
+
+table_events_transactions_history::table_events_transactions_history()
+ : table_events_transactions_common(&m_share, &m_pos),
+ m_pos(), m_next_pos()
+{}
+
+void table_events_transactions_history::reset_position(void)
+{
+ m_pos.reset();
+ m_next_pos.reset();
+}
+
+int table_events_transactions_history::rnd_init(bool scan)
+{
+ m_normalizer= time_normalizer::get(transaction_timer);
+ return 0;
+}
+
+int table_events_transactions_history::rnd_next(void)
+{
+ PFS_thread *pfs_thread;
+ PFS_events_transactions *transaction;
+ bool has_more_thread= true;
+
+ if (events_transactions_history_per_thread == 0)
+ return HA_ERR_END_OF_FILE;
+
+ for (m_pos.set_at(&m_next_pos);
+ has_more_thread;
+ m_pos.next_thread())
+ {
+ pfs_thread= global_thread_container.get(m_pos.m_index_1, & has_more_thread);
+ if (pfs_thread != NULL)
+ {
+ if (m_pos.m_index_2 >= events_transactions_history_per_thread)
+ {
+ /* This thread does not have more (full) history */
+ continue;
+ }
+
+ if ( ! pfs_thread->m_transactions_history_full &&
+ (m_pos.m_index_2 >= pfs_thread->m_transactions_history_index))
+ {
+ /* This thread does not have more (not full) history */
+ continue;
+ }
+
+ transaction= &pfs_thread->m_transactions_history[m_pos.m_index_2];
+ if (transaction->m_class != NULL)
+ {
+ make_row(transaction);
+ /* Next iteration, look for the next history in this thread */
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+ }
+ }
+
+ return HA_ERR_END_OF_FILE;
+}
+
+int table_events_transactions_history::rnd_pos(const void *pos)
+{
+ PFS_thread *pfs_thread;
+ PFS_events_transactions *transaction;
+
+ DBUG_ASSERT(events_transactions_history_per_thread != 0);
+ set_position(pos);
+
+ DBUG_ASSERT(m_pos.m_index_2 < events_transactions_history_per_thread);
+
+ pfs_thread= global_thread_container.get(m_pos.m_index_1);
+ if (pfs_thread != NULL)
+ {
+ if ( ! pfs_thread->m_transactions_history_full &&
+ (m_pos.m_index_2 >= pfs_thread->m_transactions_history_index))
+ return HA_ERR_RECORD_DELETED;
+
+ transaction= &pfs_thread->m_transactions_history[m_pos.m_index_2];
+ if (transaction->m_class != NULL)
+ {
+ make_row(transaction);
+ return 0;
+ }
+ }
+
+ return HA_ERR_RECORD_DELETED;
+}
+
+int table_events_transactions_history::delete_all_rows(void)
+{
+ reset_events_transactions_history();
+ return 0;
+}
+
+ha_rows
+table_events_transactions_history::get_row_count(void)
+{
+ return events_transactions_history_per_thread * global_thread_container.get_row_count();
+}
+
+PFS_engine_table* table_events_transactions_history_long::create(void)
+{
+ return new table_events_transactions_history_long();
+}
+
+table_events_transactions_history_long::table_events_transactions_history_long()
+ : table_events_transactions_common(&m_share, &m_pos),
+ m_pos(0), m_next_pos(0)
+{}
+
+void table_events_transactions_history_long::reset_position(void)
+{
+ m_pos.m_index= 0;
+ m_next_pos.m_index= 0;
+}
+
+int table_events_transactions_history_long::rnd_init(bool scan)
+{
+ m_normalizer= time_normalizer::get(transaction_timer);
+ return 0;
+}
+
+int table_events_transactions_history_long::rnd_next(void)
+{
+ PFS_events_transactions *transaction;
+ uint limit;
+
+ if (events_transactions_history_long_size == 0)
+ return HA_ERR_END_OF_FILE;
+
+ if (events_transactions_history_long_full)
+ limit= events_transactions_history_long_size;
+ else
+ limit= events_transactions_history_long_index.m_u32 % events_transactions_history_long_size;
+
+ for (m_pos.set_at(&m_next_pos); m_pos.m_index < limit; m_pos.next())
+ {
+ transaction= &events_transactions_history_long_array[m_pos.m_index];
+
+ if (transaction->m_class != NULL)
+ {
+ make_row(transaction);
+ /* Next iteration, look for the next entry */
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+ }
+
+ return HA_ERR_END_OF_FILE;
+}
+
+int table_events_transactions_history_long::rnd_pos(const void *pos)
+{
+ PFS_events_transactions *transaction;
+ uint limit;
+
+ if (events_transactions_history_long_size == 0)
+ return HA_ERR_RECORD_DELETED;
+
+ set_position(pos);
+
+ if (events_transactions_history_long_full)
+ limit= events_transactions_history_long_size;
+ else
+ limit= events_transactions_history_long_index.m_u32 % events_transactions_history_long_size;
+
+ if (m_pos.m_index >= limit)
+ return HA_ERR_RECORD_DELETED;
+
+ transaction= &events_transactions_history_long_array[m_pos.m_index];
+
+ if (transaction->m_class == NULL)
+ return HA_ERR_RECORD_DELETED;
+
+ make_row(transaction);
+ return 0;
+}
+
+int table_events_transactions_history_long::delete_all_rows(void)
+{
+ reset_events_transactions_history_long();
+ return 0;
+}
+
+ha_rows
+table_events_transactions_history_long::get_row_count(void)
+{
+ return events_transactions_history_long_size;
+}
+
diff --git a/storage/perfschema/table_events_transactions.h b/storage/perfschema/table_events_transactions.h
new file mode 100644
index 00000000000..9987319abb2
--- /dev/null
+++ b/storage/perfschema/table_events_transactions.h
@@ -0,0 +1,254 @@
+/* Copyright (c) 2010, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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_EVENTS_TRANSACTIONS_H
+#define TABLE_EVENTS_TRANSACTIONS_H
+
+/**
+ @file storage/perfschema/table_events_HA_ERR_WRONG_COMMAND.h
+ Table EVENTS_TRANSACTIONS_xxx (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "pfs_events_transactions.h"
+#include "table_helper.h"
+#include "rpl_gtid.h"
+
+struct PFS_thread;
+
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+/** A row of table_events_transactions_common. */
+struct row_events_transactions
+{
+ /** Column THREAD_ID. */
+ ulonglong m_thread_internal_id;
+ /** Column EVENT_ID. */
+ ulonglong m_event_id;
+ /** Column END_EVENT_ID. */
+ ulonglong m_end_event_id;
+ /** Column NESTING_EVENT_ID. */
+ ulonglong m_nesting_event_id;
+ /** Column NESTING_EVENT_TYPE. */
+ enum_event_type m_nesting_event_type;
+ /** Column EVENT_NAME. */
+ const char *m_name;
+ /** Length in bytes of @c m_name. */
+ uint m_name_length;
+ /** Column TIMER_START. */
+ ulonglong m_timer_start;
+ /** Column TIMER_END. */
+ ulonglong m_timer_end;
+ /** Column TIMER_WAIT. */
+ ulonglong m_timer_wait;
+ /** Column SOURCE. */
+ char m_source[COL_SOURCE_SIZE];
+ /** Length in bytes of @c m_source. */
+ uint m_source_length;
+ /** InnoDB transaction id. */
+ ulonglong m_trxid;
+ /** Transaction state. */
+ enum_transaction_state m_state;
+ /** Global Transaction ID. */
+ char m_gtid[GTID_MAX_STR_LENGTH + 1];
+ /** GTID length in bytes*/
+ int m_gtid_length;
+ /** XA transaction ID. */
+ PSI_xid m_xid;
+ /** XA transaction state. */
+ enum_xa_transaction_state m_xa_state;
+ /** True if XA transaction. */
+ bool m_xa;
+ /** True if autocommit transaction. */
+ bool m_autocommit;
+ /** Isolation level. */
+ enum_isolation_level m_isolation_level;
+ /** True if read-only, read-write otherwise. */
+ bool m_read_only;
+ /** Column NUMBER_OF_SAVEPOINTS. */
+ ulonglong m_savepoint_count;
+ /** Column NUMBER_OF_ROLLBACK_TO_SAVEPOINT. */
+ ulonglong m_rollback_to_savepoint_count;
+ /** Column NUMBER_OF_RELEASE_SAVEPOINT. */
+ ulonglong m_release_savepoint_count;
+};
+
+/**
+ Position of a cursor on PERFORMANCE_SCHEMA.EVENTS_TRANSACTIONS_HISTORY.
+ Index 1 on thread (0 based)
+ Index 2 on transaction event record in thread history (0 based)
+*/
+struct pos_events_transactions_history : public PFS_double_index
+{
+ pos_events_transactions_history()
+ : PFS_double_index(0, 0)
+ {}
+
+ inline void reset(void)
+ {
+ m_index_1= 0;
+ m_index_2= 0;
+ }
+
+ inline void next_thread(void)
+ {
+ m_index_1++;
+ m_index_2= 0;
+ }
+};
+
+/**
+ Adapter, for table sharing the structure of
+ PERFORMANCE_SCHEMA.EVENTS_TRANSACTIONS_CURRENT.
+*/
+class table_events_transactions_common : public PFS_engine_table
+{
+protected:
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+
+ table_events_transactions_common(const PFS_engine_table_share *share, void *pos);
+
+ ~table_events_transactions_common()
+ {}
+
+ void make_row(PFS_events_transactions *statement);
+
+ /** Current row. */
+ row_events_transactions m_row;
+ /** True if the current row exists. */
+ bool m_row_exists;
+};
+
+/** Table PERFORMANCE_SCHEMA.EVENTS_TRANSACTIONS_CURRENT. */
+class table_events_transactions_current : public table_events_transactions_common
+{
+public:
+ /** Table share */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static int delete_all_rows();
+ static ha_rows get_row_count();
+
+ virtual int rnd_init(bool scan);
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+protected:
+ table_events_transactions_current();
+
+public:
+ ~table_events_transactions_current()
+ {}
+
+private:
+ friend class table_events_transactions_history;
+ friend class table_events_transactions_history_long;
+
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /**
+ Fields definition.
+ Also used by table_events_transactions_history
+ and table_events_transactions_history_long.
+ */
+ static TABLE_FIELD_DEF m_field_def;
+
+ /** Current position. */
+ PFS_simple_index m_pos;
+ /** Next position. */
+ PFS_simple_index m_next_pos;
+};
+
+/** Table PERFORMANCE_SCHEMA.EVENTS_TRANSACTIONS_HISTORY. */
+class table_events_transactions_history : public table_events_transactions_common
+{
+public:
+ /** Table share */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static int delete_all_rows();
+ static ha_rows get_row_count();
+
+ virtual int rnd_init(bool scan);
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+protected:
+ table_events_transactions_history();
+
+public:
+ ~table_events_transactions_history()
+ {}
+
+private:
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+
+ /** Current position. */
+ pos_events_transactions_history m_pos;
+ /** Next position. */
+ pos_events_transactions_history m_next_pos;
+};
+
+/** Table PERFORMANCE_SCHEMA.EVENTS_TRANSACTIONS_HISTORY_LONG. */
+class table_events_transactions_history_long : public table_events_transactions_common
+{
+public:
+ /** Table share */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static int delete_all_rows();
+ static ha_rows get_row_count();
+
+ virtual int rnd_init(bool scan);
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+protected:
+ table_events_transactions_history_long();
+
+public:
+ ~table_events_transactions_history_long()
+ {}
+
+private:
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+
+ /** Current position. */
+ PFS_simple_index m_pos;
+ /** Next position. */
+ PFS_simple_index m_next_pos;
+};
+
+/** @} */
+#endif
diff --git a/storage/perfschema/table_events_waits.cc b/storage/perfschema/table_events_waits.cc
index 6cfc754f8c2..ae2dde9b39c 100644
--- a/storage/perfschema/table_events_waits.cc
+++ b/storage/perfschema/table_events_waits.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2018, 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, version 2.0,
@@ -26,7 +26,7 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "table_events_waits.h"
#include "pfs_global.h"
#include "pfs_instr_class.h"
@@ -34,6 +34,8 @@
#include "pfs_events_waits.h"
#include "pfs_timer.h"
#include "m_string.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
THR_LOCK table_events_waits_current::m_table_lock;
@@ -42,11 +44,10 @@ table_events_waits_current::m_share=
{
{ C_STRING_WITH_LEN("events_waits_current") },
&pfs_truncatable_acl,
- &table_events_waits_current::create,
+ table_events_waits_current::create,
NULL, /* write_row */
- &table_events_waits_current::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ table_events_waits_current::delete_all_rows,
+ table_events_waits_current::get_row_count,
sizeof(pos_events_waits_current), /* ref length */
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE events_waits_current("
@@ -65,10 +66,11 @@ table_events_waits_current::m_share=
"OBJECT_TYPE VARCHAR(64),"
"OBJECT_INSTANCE_BEGIN BIGINT unsigned not null,"
"NESTING_EVENT_ID BIGINT unsigned,"
- "NESTING_EVENT_TYPE ENUM('STATEMENT', 'STAGE', 'WAIT'),"
+ "NESTING_EVENT_TYPE ENUM('TRANSACTION', 'STATEMENT', 'STAGE', 'WAIT'),"
"OPERATION VARCHAR(32) not null,"
"NUMBER_OF_BYTES BIGINT,"
- "FLAGS INTEGER unsigned)") }
+ "FLAGS INTEGER unsigned)") },
+ false /* perpetual */
};
THR_LOCK table_events_waits_history::m_table_lock;
@@ -78,11 +80,10 @@ table_events_waits_history::m_share=
{
{ C_STRING_WITH_LEN("events_waits_history") },
&pfs_truncatable_acl,
- &table_events_waits_history::create,
+ table_events_waits_history::create,
NULL, /* write_row */
- &table_events_waits_history::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ table_events_waits_history::delete_all_rows,
+ table_events_waits_history::get_row_count,
sizeof(pos_events_waits_history), /* ref length */
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE events_waits_history("
@@ -101,10 +102,11 @@ table_events_waits_history::m_share=
"OBJECT_TYPE VARCHAR(64),"
"OBJECT_INSTANCE_BEGIN BIGINT unsigned not null,"
"NESTING_EVENT_ID BIGINT unsigned,"
- "NESTING_EVENT_TYPE ENUM('STATEMENT', 'STAGE', 'WAIT'),"
+ "NESTING_EVENT_TYPE ENUM('TRANSACTION', 'STATEMENT', 'STAGE', 'WAIT'),"
"OPERATION VARCHAR(32) not null,"
"NUMBER_OF_BYTES BIGINT,"
- "FLAGS INTEGER unsigned)") }
+ "FLAGS INTEGER unsigned)") },
+ false /* perpetual */
};
THR_LOCK table_events_waits_history_long::m_table_lock;
@@ -114,11 +116,10 @@ table_events_waits_history_long::m_share=
{
{ C_STRING_WITH_LEN("events_waits_history_long") },
&pfs_truncatable_acl,
- &table_events_waits_history_long::create,
+ table_events_waits_history_long::create,
NULL, /* write_row */
- &table_events_waits_history_long::delete_all_rows,
- NULL, /* get_row_count */
- 10000, /* records */
+ table_events_waits_history_long::delete_all_rows,
+ table_events_waits_history_long::get_row_count,
sizeof(PFS_simple_index), /* ref length */
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE events_waits_history_long("
@@ -137,10 +138,11 @@ table_events_waits_history_long::m_share=
"OBJECT_TYPE VARCHAR(64),"
"OBJECT_INSTANCE_BEGIN BIGINT unsigned not null,"
"NESTING_EVENT_ID BIGINT unsigned,"
- "NESTING_EVENT_TYPE ENUM('STATEMENT', 'STAGE', 'WAIT'),"
+ "NESTING_EVENT_TYPE ENUM('TRANSACTION', 'STATEMENT', 'STAGE', 'WAIT'),"
"OPERATION VARCHAR(32) not null,"
"NUMBER_OF_BYTES BIGINT,"
- "FLAGS INTEGER unsigned)") }
+ "FLAGS INTEGER unsigned)") },
+ false /* perpetual */
};
table_events_waits_common::table_events_waits_common
@@ -151,15 +153,13 @@ table_events_waits_common::table_events_waits_common
void table_events_waits_common::clear_object_columns()
{
- m_row.m_object_type= NULL;
m_row.m_object_type_length= 0;
m_row.m_object_schema_length= 0;
m_row.m_object_name_length= 0;
m_row.m_index_name_length= 0;
- m_row.m_object_instance_addr= 0;
}
-int table_events_waits_common::make_table_object_columns(volatile PFS_events_waits *wait)
+int table_events_waits_common::make_table_object_columns(PFS_events_waits *wait)
{
uint safe_index;
PFS_table_share *safe_table_share;
@@ -200,15 +200,28 @@ int table_events_waits_common::make_table_object_columns(volatile PFS_events_wai
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;
- if (unlikely((m_row.m_index_name_length == 0) ||
- (m_row.m_index_name_length > sizeof(m_row.m_index_name))))
- return 1;
- memcpy(m_row.m_index_name, key->m_name, m_row.m_index_name_length);
+ PFS_table_share_index *index_stat;
+ index_stat= safe_table_share->find_index_stat(safe_index);
+
+ if (index_stat != NULL)
+ {
+ m_row.m_index_name_length= index_stat->m_key.m_name_length;
+
+ if (unlikely((m_row.m_index_name_length == 0) ||
+ (m_row.m_index_name_length > sizeof(m_row.m_index_name))))
+ return 1;
+
+ memcpy(m_row.m_index_name, index_stat->m_key.m_name, m_row.m_index_name_length);
+ }
+ else
+ {
+ m_row.m_index_name_length= 0;
+ }
}
else
+ {
m_row.m_index_name_length= 0;
+ }
}
else
{
@@ -221,7 +234,7 @@ int table_events_waits_common::make_table_object_columns(volatile PFS_events_wai
return 0;
}
-int table_events_waits_common::make_file_object_columns(volatile PFS_events_waits *wait)
+int table_events_waits_common::make_file_object_columns(PFS_events_waits *wait)
{
PFS_file *safe_file;
@@ -253,7 +266,7 @@ int table_events_waits_common::make_file_object_columns(volatile PFS_events_wait
return 0;
}
-int table_events_waits_common::make_socket_object_columns(volatile PFS_events_waits *wait)
+int table_events_waits_common::make_socket_object_columns(PFS_events_waits *wait)
{
PFS_socket *safe_socket;
@@ -286,7 +299,7 @@ int table_events_waits_common::make_socket_object_columns(volatile PFS_events_wa
safe_socket->m_addr_len);
/* Convert port number to a string (length includes ':') */
- int port_len= (int)(int10_to_str(port, (port_str+1), 10) - port_str + 1);
+ size_t port_len= int10_to_str(port, (port_str+1), 10) - port_str + 1;
/* OBJECT NAME */
m_row.m_object_name_length= ip_length + port_len;
@@ -309,33 +322,133 @@ int table_events_waits_common::make_socket_object_columns(volatile PFS_events_wa
return 0;
}
+int table_events_waits_common::make_metadata_lock_object_columns(PFS_events_waits *wait)
+{
+ PFS_metadata_lock *safe_metadata_lock;
+
+ safe_metadata_lock= sanitize_metadata_lock(wait->m_weak_metadata_lock);
+ if (unlikely(safe_metadata_lock == NULL))
+ return 1;
+
+ if (safe_metadata_lock->get_version() == wait->m_weak_version)
+ {
+ MDL_key *mdl= & safe_metadata_lock->m_mdl_key;
+
+ switch(mdl->mdl_namespace())
+ {
+ case MDL_key::GLOBAL:
+ m_row.m_object_type= "GLOBAL";
+ m_row.m_object_type_length= 6;
+ m_row.m_object_schema_length= 0;
+ m_row.m_object_name_length= 0;
+ break;
+ case MDL_key::SCHEMA:
+ m_row.m_object_type= "SCHEMA";
+ m_row.m_object_type_length= 6;
+ m_row.m_object_schema_length= mdl->db_name_length();
+ m_row.m_object_name_length= 0;
+ break;
+ case MDL_key::TABLE:
+ m_row.m_object_type= "TABLE";
+ m_row.m_object_type_length= 5;
+ m_row.m_object_schema_length= mdl->db_name_length();
+ m_row.m_object_name_length= mdl->name_length();
+ break;
+ case MDL_key::FUNCTION:
+ m_row.m_object_type= "FUNCTION";
+ m_row.m_object_type_length= 8;
+ m_row.m_object_schema_length= mdl->db_name_length();
+ m_row.m_object_name_length= mdl->name_length();
+ break;
+ case MDL_key::PROCEDURE:
+ m_row.m_object_type= "PROCEDURE";
+ m_row.m_object_type_length= 9;
+ m_row.m_object_schema_length= mdl->db_name_length();
+ m_row.m_object_name_length= mdl->name_length();
+ break;
+ case MDL_key::TRIGGER:
+ m_row.m_object_type= "TRIGGER";
+ m_row.m_object_type_length= 7;
+ m_row.m_object_schema_length= mdl->db_name_length();
+ m_row.m_object_name_length= mdl->name_length();
+ break;
+ case MDL_key::EVENT:
+ m_row.m_object_type= "EVENT";
+ m_row.m_object_type_length= 5;
+ m_row.m_object_schema_length= mdl->db_name_length();
+ m_row.m_object_name_length= mdl->name_length();
+ break;
+ case MDL_key::COMMIT:
+ m_row.m_object_type= "COMMIT";
+ m_row.m_object_type_length= 6;
+ m_row.m_object_schema_length= 0;
+ m_row.m_object_name_length= 0;
+ break;
+ case MDL_key::USER_LOCK:
+ m_row.m_object_type= "USER LEVEL LOCK";
+ m_row.m_object_type_length= 15;
+ m_row.m_object_schema_length= 0;
+ m_row.m_object_name_length= mdl->name_length();
+ break;
+#if 0
+ case MDL_key::TABLESPACE:
+ m_row.m_object_type= "TABLESPACE";
+ m_row.m_object_type_length= 10;
+ m_row.m_object_schema_length= 0;
+ m_row.m_object_name_length= mdl->name_length();
+ break;
+ case MDL_key::LOCKING_SERVICE:
+ m_row.m_object_type= "LOCKING SERVICE";
+ m_row.m_object_type_length= 15;
+ m_row.m_object_schema_length= mdl->db_name_length();
+ m_row.m_object_name_length= mdl->name_length();
+ break;
+#endif
+ case MDL_key::NAMESPACE_END:
+ default:
+ m_row.m_object_type_length= 0;
+ m_row.m_object_schema_length= 0;
+ m_row.m_object_name_length= 0;
+ break;
+ }
+
+ if (m_row.m_object_schema_length > sizeof(m_row.m_object_schema))
+ return 1;
+ if (m_row.m_object_schema_length > 0)
+ memcpy(m_row.m_object_schema, mdl->db_name(), m_row.m_object_schema_length);
+
+ if (m_row.m_object_name_length > sizeof(m_row.m_object_name))
+ return 1;
+ if (m_row.m_object_name_length > 0)
+ memcpy(m_row.m_object_name, mdl->name(), m_row.m_object_name_length);
+
+ m_row.m_object_instance_addr= (intptr) wait->m_object_instance_addr;
+ }
+ else
+ {
+ m_row.m_object_type_length= 0;
+ m_row.m_object_schema_length= 0;
+ m_row.m_object_name_length= 0;
+ m_row.m_object_instance_addr= 0;
+ }
+
+ /* INDEX NAME */
+ m_row.m_index_name_length= 0;
+
+ return 0;
+}
+
/**
Build a row.
- @param thread_own_wait True if the memory for the wait
- is owned by pfs_thread
- @param pfs_thread the thread the cursor is reading
@param wait the wait the cursor is reading
*/
-void table_events_waits_common::make_row(bool thread_own_wait,
- PFS_thread *pfs_thread,
- volatile PFS_events_waits *wait)
+void table_events_waits_common::make_row(PFS_events_waits *wait)
{
- pfs_lock lock;
- PFS_thread *safe_thread;
PFS_instr_class *safe_class;
- const char *base;
- const char *safe_source_file;
enum_timer_name timer_name= wait_timer;
ulonglong timer_end;
m_row_exists= false;
- safe_thread= sanitize_thread(pfs_thread);
- if (unlikely(safe_thread == NULL))
- return;
-
- /* Protect this reader against a thread termination */
- if (thread_own_wait)
- safe_thread->m_lock.begin_optimistic_lock(&lock);
/*
Design choice:
@@ -362,21 +475,30 @@ void table_events_waits_common::make_row(bool thread_own_wait,
*/
switch (wait->m_wait_class)
{
+ case WAIT_CLASS_METADATA:
+ if (make_metadata_lock_object_columns(wait))
+ return;
+ safe_class= sanitize_metadata_class(wait->m_class);
+ break;
case WAIT_CLASS_IDLE:
clear_object_columns();
+ m_row.m_object_instance_addr= 0;
safe_class= sanitize_idle_class(wait->m_class);
timer_name= idle_timer;
break;
case WAIT_CLASS_MUTEX:
clear_object_columns();
+ m_row.m_object_instance_addr= (intptr) wait->m_object_instance_addr;
safe_class= sanitize_mutex_class((PFS_mutex_class*) wait->m_class);
break;
case WAIT_CLASS_RWLOCK:
clear_object_columns();
+ m_row.m_object_instance_addr= (intptr) wait->m_object_instance_addr;
safe_class= sanitize_rwlock_class((PFS_rwlock_class*) wait->m_class);
break;
case WAIT_CLASS_COND:
clear_object_columns();
+ m_row.m_object_instance_addr= (intptr) wait->m_object_instance_addr;
safe_class= sanitize_cond_class((PFS_cond_class*) wait->m_class);
break;
case WAIT_CLASS_TABLE:
@@ -402,7 +524,7 @@ void table_events_waits_common::make_row(bool thread_own_wait,
if (unlikely(safe_class == NULL))
return;
- m_row.m_thread_internal_id= safe_thread->m_thread_internal_id;
+ m_row.m_thread_internal_id= wait->m_thread_internal_id;
m_row.m_event_id= wait->m_event_id;
m_row.m_end_event_id= wait->m_end_event_id;
m_row.m_nesting_event_id= wait->m_nesting_event_id;
@@ -425,39 +547,14 @@ void table_events_waits_common::make_row(bool thread_own_wait,
m_row.m_name= safe_class->m_name;
m_row.m_name_length= safe_class->m_name_length;
- /*
- We are assuming this pointer is sane,
- since it comes from __FILE__.
- */
- safe_source_file= wait->m_source_file;
- if (unlikely(safe_source_file == NULL))
- return;
+ /* Disable source file and line to avoid stale __FILE__ pointers. */
+ m_row.m_source_length= 0;
- base= base_name(wait->m_source_file);
- m_row.m_source_length= (uint)my_snprintf(m_row.m_source, sizeof(m_row.m_source),
- "%s:%d", base, wait->m_source_line);
- if (m_row.m_source_length > sizeof(m_row.m_source))
- m_row.m_source_length= sizeof(m_row.m_source);
m_row.m_operation= wait->m_operation;
m_row.m_number_of_bytes= wait->m_number_of_bytes;
m_row.m_flags= wait->m_flags;
- if (thread_own_wait)
- {
- if (safe_thread->m_lock.end_optimistic_lock(&lock))
- m_row_exists= true;
- }
- else
- {
- /*
- For EVENTS_WAITS_HISTORY_LONG (thread_own_wait is false),
- the wait record is always valid, because it is not stored
- in memory owned by pfs_thread.
- Even when the thread terminated, the record is mostly readable,
- so this record is displayed.
- */
- m_row_exists= true;
- }
+ m_row_exists= true;
}
/**
@@ -474,12 +571,20 @@ static const LEX_STRING operation_names_map[]=
{ C_STRING_WITH_LEN("lock") },
{ C_STRING_WITH_LEN("try_lock") },
- /* RWLock operations */
+ /* RWLock operations (RW-lock) */
{ C_STRING_WITH_LEN("read_lock") },
{ C_STRING_WITH_LEN("write_lock") },
{ C_STRING_WITH_LEN("try_read_lock") },
{ C_STRING_WITH_LEN("try_write_lock") },
+ /* RWLock operations (SX-lock) */
+ { C_STRING_WITH_LEN("shared_lock") },
+ { C_STRING_WITH_LEN("shared_exclusive_lock") },
+ { C_STRING_WITH_LEN("exclusive_lock") },
+ { C_STRING_WITH_LEN("try_shared_lock") },
+ { C_STRING_WITH_LEN("try_shared_exclusive_lock") },
+ { C_STRING_WITH_LEN("try_exclusive_lock") },
+
/* Condition operations */
{ C_STRING_WITH_LEN("wait") },
{ C_STRING_WITH_LEN("timed_wait") },
@@ -516,7 +621,6 @@ static const LEX_STRING operation_names_map[]=
{ C_STRING_WITH_LEN("read no inserts") },
{ C_STRING_WITH_LEN("write allow write") },
{ C_STRING_WITH_LEN("write concurrent insert") },
- { C_STRING_WITH_LEN("write delayed") },
{ C_STRING_WITH_LEN("write low priority") },
{ C_STRING_WITH_LEN("write normal") },
{ C_STRING_WITH_LEN("read external") },
@@ -540,7 +644,10 @@ static const LEX_STRING operation_names_map[]=
{ C_STRING_WITH_LEN("select") },
/* Idle operations */
- { C_STRING_WITH_LEN("idle") }
+ { C_STRING_WITH_LEN("idle") },
+
+ /* Medatada lock operations */
+ { C_STRING_WITH_LEN("metadata lock") }
};
@@ -644,7 +751,7 @@ int table_events_waits_common::read_row_values(TABLE *table,
f->set_null();
break;
case 12: /* OBJECT_TYPE */
- if (m_row.m_object_type)
+ if (m_row.m_object_type_length > 0)
{
set_field_varchar_utf8(f, m_row.m_object_type,
m_row.m_object_type_length);
@@ -671,14 +778,18 @@ int table_events_waits_common::read_row_values(TABLE *table,
operation= &operation_names_map[(int) m_row.m_operation - 1];
set_field_varchar_utf8(f, operation->str, (uint)operation->length);
break;
- case 17: /* NUMBER_OF_BYTES */
+ case 17: /* NUMBER_OF_BYTES (also used for ROWS) */
if ((m_row.m_operation == OPERATION_TYPE_FILEREAD) ||
(m_row.m_operation == OPERATION_TYPE_FILEWRITE) ||
(m_row.m_operation == OPERATION_TYPE_FILECHSIZE) ||
(m_row.m_operation == OPERATION_TYPE_SOCKETSEND) ||
(m_row.m_operation == OPERATION_TYPE_SOCKETRECV) ||
(m_row.m_operation == OPERATION_TYPE_SOCKETSENDTO) ||
- (m_row.m_operation == OPERATION_TYPE_SOCKETRECVFROM))
+ (m_row.m_operation == OPERATION_TYPE_SOCKETRECVFROM) ||
+ (m_row.m_operation == OPERATION_TYPE_TABLE_FETCH) ||
+ (m_row.m_operation == OPERATION_TYPE_TABLE_WRITE_ROW) ||
+ (m_row.m_operation == OPERATION_TYPE_TABLE_UPDATE_ROW) ||
+ (m_row.m_operation == OPERATION_TYPE_TABLE_DELETE_ROW))
set_field_ulonglong(f, m_row.m_number_of_bytes);
else
f->set_null();
@@ -714,28 +825,77 @@ int table_events_waits_current::rnd_next(void)
{
PFS_thread *pfs_thread;
PFS_events_waits *wait;
+ bool has_more_thread= true;
for (m_pos.set_at(&m_next_pos);
- m_pos.m_index_1 < thread_max;
+ has_more_thread;
m_pos.next_thread())
{
- pfs_thread= &thread_array[m_pos.m_index_1];
-
- if (! pfs_thread->m_lock.is_populated())
+ pfs_thread= global_thread_container.get(m_pos.m_index_1, & has_more_thread);
+ if (pfs_thread != NULL)
{
- /* This thread does not exist */
- continue;
+ /*
+ We do not show nested events for now,
+ this will be revised with TABLE io
+ */
+// #define ONLY_SHOW_ONE_WAIT
+
+#ifdef ONLY_SHOW_ONE_WAIT
+ if (m_pos.m_index_2 >= 1)
+ continue;
+#else
+ /* m_events_waits_stack[0] is a dummy record */
+ PFS_events_waits *top_wait = &pfs_thread->m_events_waits_stack[WAIT_STACK_BOTTOM];
+ wait= &pfs_thread->m_events_waits_stack[m_pos.m_index_2 + WAIT_STACK_BOTTOM];
+
+ PFS_events_waits *safe_current = pfs_thread->m_events_waits_current;
+
+ if (safe_current == top_wait)
+ {
+ /* Display the last top level wait, when completed */
+ if (m_pos.m_index_2 >= 1)
+ continue;
+ }
+ else
+ {
+ /* Display all pending waits, when in progress */
+ if (wait >= safe_current)
+ continue;
+ }
+#endif
+
+ if (wait->m_wait_class == NO_WAIT_CLASS)
+ {
+ /*
+ This locker does not exist.
+ There can not be more lockers in the stack, skip to the next thread
+ */
+ continue;
+ }
+
+ make_row(pfs_thread, wait);
+ /* Next iteration, look for the next locker in this thread */
+ m_next_pos.set_after(&m_pos);
+ return 0;
}
+ }
- /*
- We do not show nested events for now,
- this will be revised with TABLE io
- */
-// #define ONLY_SHOW_ONE_WAIT
+ return HA_ERR_END_OF_FILE;
+}
+int table_events_waits_current::rnd_pos(const void *pos)
+{
+ PFS_thread *pfs_thread;
+ PFS_events_waits *wait;
+
+ set_position(pos);
+
+ pfs_thread= global_thread_container.get(m_pos.m_index_1);
+ if (pfs_thread != NULL)
+ {
#ifdef ONLY_SHOW_ONE_WAIT
if (m_pos.m_index_2 >= 1)
- continue;
+ return HA_ERR_RECORD_DELETED;
#else
/* m_events_waits_stack[0] is a dummy record */
PFS_events_waits *top_wait = &pfs_thread->m_events_waits_stack[WAIT_STACK_BOTTOM];
@@ -747,77 +907,39 @@ int table_events_waits_current::rnd_next(void)
{
/* Display the last top level wait, when completed */
if (m_pos.m_index_2 >= 1)
- continue;
+ return HA_ERR_RECORD_DELETED;
}
else
{
/* Display all pending waits, when in progress */
if (wait >= safe_current)
- continue;
+ return HA_ERR_RECORD_DELETED;
}
#endif
- if (wait->m_wait_class == NO_WAIT_CLASS)
+ DBUG_ASSERT(m_pos.m_index_2 < WAIT_STACK_LOGICAL_SIZE);
+
+ if (wait->m_wait_class != NO_WAIT_CLASS)
{
- /*
- This locker does not exist.
- There can not be more lockers in the stack, skip to the next thread
- */
- continue;
+ make_row(pfs_thread, wait);
+ return 0;
}
-
- make_row(true, pfs_thread, wait);
- /* Next iteration, look for the next locker in this thread */
- m_next_pos.set_after(&m_pos);
- return 0;
}
- return HA_ERR_END_OF_FILE;
+ return HA_ERR_RECORD_DELETED;
}
-int table_events_waits_current::rnd_pos(const void *pos)
+void table_events_waits_current::make_row(PFS_thread *thread, PFS_events_waits *wait)
{
- PFS_thread *pfs_thread;
- PFS_events_waits *wait;
-
- set_position(pos);
- DBUG_ASSERT(m_pos.m_index_1 < thread_max);
- pfs_thread= &thread_array[m_pos.m_index_1];
+ pfs_optimistic_state lock;
- if (! pfs_thread->m_lock.is_populated())
- return HA_ERR_RECORD_DELETED;
-
-#ifdef ONLY_SHOW_ONE_WAIT
- if (m_pos.m_index_2 >= 1)
- return HA_ERR_RECORD_DELETED;
-#else
- /* m_events_waits_stack[0] is a dummy record */
- PFS_events_waits *top_wait = &pfs_thread->m_events_waits_stack[WAIT_STACK_BOTTOM];
- wait= &pfs_thread->m_events_waits_stack[m_pos.m_index_2 + WAIT_STACK_BOTTOM];
-
- PFS_events_waits *safe_current = pfs_thread->m_events_waits_current;
-
- if (safe_current == top_wait)
- {
- /* Display the last top level wait, when completed */
- if (m_pos.m_index_2 >= 1)
- return HA_ERR_RECORD_DELETED;
- }
- else
- {
- /* Display all pending waits, when in progress */
- if (wait >= safe_current)
- return HA_ERR_RECORD_DELETED;
- }
-#endif
-
- DBUG_ASSERT(m_pos.m_index_2 < WAIT_STACK_LOGICAL_SIZE);
+ /* Protect this reader against a thread termination */
+ thread->m_lock.begin_optimistic_lock(&lock);
- if (wait->m_wait_class == NO_WAIT_CLASS)
- return HA_ERR_RECORD_DELETED;
+ table_events_waits_common::make_row(wait);
- make_row(true, pfs_thread, wait);
- return 0;
+ if (! thread->m_lock.end_optimistic_lock(&lock))
+ m_row_exists= false;
}
int table_events_waits_current::delete_all_rows(void)
@@ -826,6 +948,12 @@ int table_events_waits_current::delete_all_rows(void)
return 0;
}
+ha_rows
+table_events_waits_current::get_row_count(void)
+{
+ return WAIT_STACK_SIZE * global_thread_container.get_row_count();
+}
+
PFS_engine_table* table_events_waits_history::create(void)
{
return new table_events_waits_history();
@@ -846,51 +974,40 @@ int table_events_waits_history::rnd_next(void)
{
PFS_thread *pfs_thread;
PFS_events_waits *wait;
+ bool has_more_thread= true;
if (events_waits_history_per_thread == 0)
return HA_ERR_END_OF_FILE;
for (m_pos.set_at(&m_next_pos);
- m_pos.m_index_1 < thread_max;
+ has_more_thread;
m_pos.next_thread())
{
- pfs_thread= &thread_array[m_pos.m_index_1];
-
- if (! pfs_thread->m_lock.is_populated())
+ pfs_thread= global_thread_container.get(m_pos.m_index_1, & has_more_thread);
+ if (pfs_thread != NULL)
{
- /* This thread does not exist */
- continue;
- }
-
- if (m_pos.m_index_2 >= events_waits_history_per_thread)
- {
- /* This thread does not have more (full) history */
- continue;
- }
+ if (m_pos.m_index_2 >= events_waits_history_per_thread)
+ {
+ /* This thread does not have more (full) history */
+ continue;
+ }
- if ( ! pfs_thread->m_waits_history_full &&
- (m_pos.m_index_2 >= pfs_thread->m_waits_history_index))
- {
- /* This thread does not have more (not full) history */
- continue;
- }
+ if ( ! pfs_thread->m_waits_history_full &&
+ (m_pos.m_index_2 >= pfs_thread->m_waits_history_index))
+ {
+ /* This thread does not have more (not full) history */
+ continue;
+ }
- if (pfs_thread->m_waits_history[m_pos.m_index_2].m_wait_class
- == NO_WAIT_CLASS)
- {
- /*
- This locker does not exist.
- There can not be more lockers in the stack, skip to the next thread
- */
- continue;
+ wait= &pfs_thread->m_waits_history[m_pos.m_index_2];
+ if (wait->m_wait_class != NO_WAIT_CLASS)
+ {
+ make_row(pfs_thread, wait);
+ /* Next iteration, look for the next history in this thread */
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
}
-
- wait= &pfs_thread->m_waits_history[m_pos.m_index_2];
-
- make_row(true, pfs_thread, wait);
- /* Next iteration, look for the next history in this thread */
- m_next_pos.set_after(&m_pos);
- return 0;
}
return HA_ERR_END_OF_FILE;
@@ -903,25 +1020,39 @@ int table_events_waits_history::rnd_pos(const void *pos)
DBUG_ASSERT(events_waits_history_per_thread != 0);
set_position(pos);
- DBUG_ASSERT(m_pos.m_index_1 < thread_max);
- pfs_thread= &thread_array[m_pos.m_index_1];
- if (! pfs_thread->m_lock.is_populated())
- return HA_ERR_RECORD_DELETED;
+ pfs_thread= global_thread_container.get(m_pos.m_index_1);
+ if (pfs_thread != NULL)
+ {
+ DBUG_ASSERT(m_pos.m_index_2 < events_waits_history_per_thread);
+
+ if ( ! pfs_thread->m_waits_history_full &&
+ (m_pos.m_index_2 >= pfs_thread->m_waits_history_index))
+ return HA_ERR_RECORD_DELETED;
- DBUG_ASSERT(m_pos.m_index_2 < events_waits_history_per_thread);
+ wait= &pfs_thread->m_waits_history[m_pos.m_index_2];
- if ( ! pfs_thread->m_waits_history_full &&
- (m_pos.m_index_2 >= pfs_thread->m_waits_history_index))
- return HA_ERR_RECORD_DELETED;
+ if (wait->m_wait_class != NO_WAIT_CLASS)
+ {
+ make_row(pfs_thread, wait);
+ return 0;
+ }
+ }
- wait= &pfs_thread->m_waits_history[m_pos.m_index_2];
+ return HA_ERR_RECORD_DELETED;
+}
- if (wait->m_wait_class == NO_WAIT_CLASS)
- return HA_ERR_RECORD_DELETED;
+void table_events_waits_history::make_row(PFS_thread *thread, PFS_events_waits *wait)
+{
+ pfs_optimistic_state lock;
- make_row(true, pfs_thread, wait);
- return 0;
+ /* Protect this reader against a thread termination */
+ thread->m_lock.begin_optimistic_lock(&lock);
+
+ table_events_waits_common::make_row(wait);
+
+ if (! thread->m_lock.end_optimistic_lock(&lock))
+ m_row_exists= false;
}
int table_events_waits_history::delete_all_rows(void)
@@ -930,6 +1061,12 @@ int table_events_waits_history::delete_all_rows(void)
return 0;
}
+ha_rows
+table_events_waits_history::get_row_count(void)
+{
+ return events_waits_history_per_thread * global_thread_container.get_row_count();
+}
+
PFS_engine_table* table_events_waits_history_long::create(void)
{
return new table_events_waits_history_long();
@@ -957,7 +1094,7 @@ int table_events_waits_history_long::rnd_next(void)
if (events_waits_history_long_full)
limit= events_waits_history_long_size;
else
- limit= events_waits_history_long_index % events_waits_history_long_size;
+ limit= events_waits_history_long_index.m_u32 % events_waits_history_long_size;
for (m_pos.set_at(&m_next_pos); m_pos.m_index < limit; m_pos.next())
{
@@ -965,7 +1102,7 @@ int table_events_waits_history_long::rnd_next(void)
if (wait->m_wait_class != NO_WAIT_CLASS)
{
- make_row(false, wait->m_thread, wait);
+ make_row(wait);
/* Next iteration, look for the next entry */
m_next_pos.set_after(&m_pos);
return 0;
@@ -988,7 +1125,7 @@ int table_events_waits_history_long::rnd_pos(const void *pos)
if (events_waits_history_long_full)
limit= events_waits_history_long_size;
else
- limit= events_waits_history_long_index % events_waits_history_long_size;
+ limit= events_waits_history_long_index.m_u32 % events_waits_history_long_size;
if (m_pos.m_index >= limit)
return HA_ERR_RECORD_DELETED;
@@ -998,7 +1135,7 @@ int table_events_waits_history_long::rnd_pos(const void *pos)
if (wait->m_wait_class == NO_WAIT_CLASS)
return HA_ERR_RECORD_DELETED;
- make_row(false, wait->m_thread, wait);
+ make_row(wait);
return 0;
}
@@ -1008,3 +1145,9 @@ int table_events_waits_history_long::delete_all_rows(void)
return 0;
}
+ha_rows
+table_events_waits_history_long::get_row_count(void)
+{
+ return events_waits_history_long_size;
+}
+
diff --git a/storage/perfschema/table_events_waits.h b/storage/perfschema/table_events_waits.h
index 90c1d341e5d..9173ec30594 100644
--- a/storage/perfschema/table_events_waits.h
+++ b/storage/perfschema/table_events_waits.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -150,12 +150,12 @@ protected:
{}
void clear_object_columns();
- int make_table_object_columns(volatile PFS_events_waits *wait);
- int make_file_object_columns(volatile PFS_events_waits *wait);
- int make_socket_object_columns(volatile PFS_events_waits *wait);
+ int make_table_object_columns(PFS_events_waits *wait);
+ int make_file_object_columns(PFS_events_waits *wait);
+ int make_socket_object_columns(PFS_events_waits *wait);
+ int make_metadata_lock_object_columns(PFS_events_waits *wait);
- void make_row(bool thread_own_wait, PFS_thread *pfs_thread,
- volatile PFS_events_waits *wait);
+ void make_row(PFS_events_waits *wait);
/** Current row. */
row_events_waits m_row;
@@ -171,6 +171,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_next();
virtual int rnd_pos(const void *pos);
@@ -190,6 +191,8 @@ private:
/** Table share lock. */
static THR_LOCK m_table_lock;
+ void make_row(PFS_thread *thread, PFS_events_waits *wait);
+
/** Current position. */
pos_events_waits_current m_pos;
/** Next position. */
@@ -204,6 +207,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_next();
virtual int rnd_pos(const void *pos);
@@ -220,6 +224,8 @@ private:
/** Table share lock. */
static THR_LOCK m_table_lock;
+ void make_row(PFS_thread *thread, PFS_events_waits *wait);
+
/** Current position. */
pos_events_waits_history m_pos;
/** Next position. */
@@ -234,6 +240,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_next();
virtual int rnd_pos(const void *pos);
diff --git a/storage/perfschema/table_events_waits_summary.cc b/storage/perfschema/table_events_waits_summary.cc
index 03477f6d542..71ae6eae685 100644
--- a/storage/perfschema/table_events_waits_summary.cc
+++ b/storage/perfschema/table_events_waits_summary.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -26,12 +26,13 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_instr_class.h"
#include "pfs_column_types.h"
#include "pfs_column_values.h"
#include "table_events_waits_summary.h"
#include "pfs_global.h"
+#include "field.h"
THR_LOCK table_events_waits_summary_by_instance::m_table_lock;
@@ -40,11 +41,10 @@ table_events_waits_summary_by_instance::m_share=
{
{ C_STRING_WITH_LEN("events_waits_summary_by_instance") },
&pfs_truncatable_acl,
- &table_events_waits_summary_by_instance::create,
+ table_events_waits_summary_by_instance::create,
NULL, /* write_row */
- &table_events_waits_summary_by_instance::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ table_events_waits_summary_by_instance::delete_all_rows,
+ table_all_instr::get_row_count,
sizeof(pos_all_instr),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE events_waits_summary_by_instance("
@@ -54,7 +54,8 @@ table_events_waits_summary_by_instance::m_share=
"SUM_TIMER_WAIT BIGINT unsigned not null,"
"MIN_TIMER_WAIT BIGINT unsigned not null,"
"AVG_TIMER_WAIT BIGINT unsigned not null,"
- "MAX_TIMER_WAIT BIGINT unsigned not null)") }
+ "MAX_TIMER_WAIT BIGINT unsigned not null)") },
+ false /* perpetual */
};
PFS_engine_table* table_events_waits_summary_by_instance::create(void)
@@ -78,7 +79,7 @@ void table_events_waits_summary_by_instance
const void *object_instance_begin,
PFS_single_stat *pfs_stat)
{
- pfs_lock lock;
+ pfs_optimistic_state lock;
m_row_exists= false;
/*
diff --git a/storage/perfschema/table_events_waits_summary.h b/storage/perfschema/table_events_waits_summary.h
index 53f1bed7987..51d8a62e02d 100644
--- a/storage/perfschema/table_events_waits_summary.h
+++ b/storage/perfschema/table_events_waits_summary.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
diff --git a/storage/perfschema/table_ews_by_account_by_event_name.cc b/storage/perfschema/table_ews_by_account_by_event_name.cc
index fa6258ec9ac..062450f3dbf 100644
--- a/storage/perfschema/table_ews_by_account_by_event_name.cc
+++ b/storage/perfschema/table_ews_by_account_by_event_name.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -26,13 +26,15 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_instr_class.h"
#include "pfs_column_types.h"
#include "pfs_column_values.h"
#include "table_ews_by_account_by_event_name.h"
#include "pfs_global.h"
#include "pfs_visitor.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
THR_LOCK table_ews_by_account_by_event_name::m_table_lock;
@@ -44,19 +46,19 @@ table_ews_by_account_by_event_name::m_share=
table_ews_by_account_by_event_name::create,
NULL, /* write_row */
table_ews_by_account_by_event_name::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ table_ews_by_account_by_event_name::get_row_count,
sizeof(pos_ews_by_account_by_event_name),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE events_waits_summary_by_account_by_event_name("
- "USER CHAR(16) collate utf8_bin default null,"
+ "USER CHAR(" USERNAME_CHAR_LENGTH_STR ") collate utf8_bin default null,"
"HOST CHAR(60) collate utf8_bin default null,"
"EVENT_NAME VARCHAR(128) not null,"
"COUNT_STAR BIGINT unsigned not null,"
"SUM_TIMER_WAIT BIGINT unsigned not null,"
"MIN_TIMER_WAIT BIGINT unsigned not null,"
"AVG_TIMER_WAIT BIGINT unsigned not null,"
- "MAX_TIMER_WAIT BIGINT unsigned not null)") }
+ "MAX_TIMER_WAIT BIGINT unsigned not null)") },
+ false /* perpetual */
};
PFS_engine_table*
@@ -73,6 +75,12 @@ table_ews_by_account_by_event_name::delete_all_rows(void)
return 0;
}
+ha_rows
+table_ews_by_account_by_event_name::get_row_count(void)
+{
+ return global_account_container.get_row_count() * wait_class_max;
+}
+
table_ews_by_account_by_event_name::table_ews_by_account_by_event_name()
: PFS_engine_table(&m_share, &m_pos),
m_row_exists(false), m_pos(), m_next_pos()
@@ -88,13 +96,14 @@ int table_ews_by_account_by_event_name::rnd_next(void)
{
PFS_account *account;
PFS_instr_class *instr_class;
+ bool has_more_account= true;
for (m_pos.set_at(&m_next_pos);
- m_pos.has_more_account();
+ has_more_account;
m_pos.next_account())
{
- account= &account_array[m_pos.m_index_1];
- if (account->m_lock.is_populated())
+ account= global_account_container.get(m_pos.m_index_1, & has_more_account);
+ if (account != NULL)
{
for ( ;
m_pos.has_more_view();
@@ -123,6 +132,9 @@ int table_ews_by_account_by_event_name::rnd_next(void)
case pos_ews_by_account_by_event_name::VIEW_IDLE:
instr_class= find_idle_class(m_pos.m_index_3);
break;
+ case pos_ews_by_account_by_event_name::VIEW_METADATA:
+ instr_class= find_metadata_class(m_pos.m_index_3);
+ break;
default:
instr_class= NULL;
DBUG_ASSERT(false);
@@ -149,10 +161,9 @@ table_ews_by_account_by_event_name::rnd_pos(const void *pos)
PFS_instr_class *instr_class;
set_position(pos);
- DBUG_ASSERT(m_pos.m_index_1 < account_max);
- account= &account_array[m_pos.m_index_1];
- if (! account->m_lock.is_populated())
+ account= global_account_container.get(m_pos.m_index_1);
+ if (account == NULL)
return HA_ERR_RECORD_DELETED;
switch (m_pos.m_index_2)
@@ -178,6 +189,9 @@ table_ews_by_account_by_event_name::rnd_pos(const void *pos)
case pos_ews_by_account_by_event_name::VIEW_IDLE:
instr_class= find_idle_class(m_pos.m_index_3);
break;
+ case pos_ews_by_account_by_event_name::VIEW_METADATA:
+ instr_class= find_metadata_class(m_pos.m_index_3);
+ break;
default:
instr_class= NULL;
DBUG_ASSERT(false);
@@ -194,7 +208,7 @@ table_ews_by_account_by_event_name::rnd_pos(const void *pos)
void table_ews_by_account_by_event_name
::make_row(PFS_account *account, PFS_instr_class *klass)
{
- pfs_lock lock;
+ pfs_optimistic_state lock;
m_row_exists= false;
account->m_lock.begin_optimistic_lock(&lock);
@@ -205,7 +219,10 @@ void table_ews_by_account_by_event_name
m_row.m_event_name.make_row(klass);
PFS_connection_wait_visitor visitor(klass);
- PFS_connection_iterator::visit_account(account, true, & visitor);
+ PFS_connection_iterator::visit_account(account,
+ true, /* threads */
+ false, /* THDs */
+ & visitor);
if (! account->m_lock.end_optimistic_lock(&lock))
return;
diff --git a/storage/perfschema/table_ews_by_account_by_event_name.h b/storage/perfschema/table_ews_by_account_by_event_name.h
index 7cde09183e3..e64a61b229c 100644
--- a/storage/perfschema/table_ews_by_account_by_event_name.h
+++ b/storage/perfschema/table_ews_by_account_by_event_name.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -57,7 +57,7 @@ struct row_ews_by_account_by_event_name
/**
Position of a cursor on
PERFORMANCE_SCHEMA.EVENTS_WAITS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME.
- Index 1 on user@host (0 based)
+ Index 1 on account (0 based)
Index 2 on instrument view
Index 3 on instrument class (1 based)
*/
@@ -75,9 +75,6 @@ struct pos_ews_by_account_by_event_name
m_index_3= 1;
}
- inline bool has_more_account(void)
- { return (m_index_1 < account_max); }
-
inline void next_account(void)
{
m_index_1++;
@@ -103,6 +100,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_next();
virtual int rnd_pos(const void *pos);
diff --git a/storage/perfschema/table_ews_by_host_by_event_name.cc b/storage/perfschema/table_ews_by_host_by_event_name.cc
index e3ef7ca3720..25f0edc900c 100644
--- a/storage/perfschema/table_ews_by_host_by_event_name.cc
+++ b/storage/perfschema/table_ews_by_host_by_event_name.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -26,7 +26,7 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_instr_class.h"
#include "pfs_column_types.h"
#include "pfs_column_values.h"
@@ -34,6 +34,8 @@
#include "pfs_global.h"
#include "pfs_account.h"
#include "pfs_visitor.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
THR_LOCK table_ews_by_host_by_event_name::m_table_lock;
@@ -45,8 +47,7 @@ table_ews_by_host_by_event_name::m_share=
table_ews_by_host_by_event_name::create,
NULL, /* write_row */
table_ews_by_host_by_event_name::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ table_ews_by_host_by_event_name::get_row_count,
sizeof(pos_ews_by_host_by_event_name),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE events_waits_summary_by_host_by_event_name("
@@ -56,7 +57,8 @@ table_ews_by_host_by_event_name::m_share=
"SUM_TIMER_WAIT BIGINT unsigned not null,"
"MIN_TIMER_WAIT BIGINT unsigned not null,"
"AVG_TIMER_WAIT BIGINT unsigned not null,"
- "MAX_TIMER_WAIT BIGINT unsigned not null)") }
+ "MAX_TIMER_WAIT BIGINT unsigned not null)") },
+ false /* perpetual */
};
PFS_engine_table*
@@ -74,6 +76,12 @@ table_ews_by_host_by_event_name::delete_all_rows(void)
return 0;
}
+ha_rows
+table_ews_by_host_by_event_name::get_row_count(void)
+{
+ return global_host_container.get_row_count() * wait_class_max;
+}
+
table_ews_by_host_by_event_name::table_ews_by_host_by_event_name()
: PFS_engine_table(&m_share, &m_pos),
m_row_exists(false), m_pos(), m_next_pos()
@@ -89,13 +97,14 @@ int table_ews_by_host_by_event_name::rnd_next(void)
{
PFS_host *host;
PFS_instr_class *instr_class;
+ bool has_more_host= true;
for (m_pos.set_at(&m_next_pos);
- m_pos.has_more_host();
+ has_more_host;
m_pos.next_host())
{
- host= &host_array[m_pos.m_index_1];
- if (host->m_lock.is_populated())
+ host= global_host_container.get(m_pos.m_index_1, & has_more_host);
+ if (host != NULL)
{
for ( ;
m_pos.has_more_view();
@@ -124,6 +133,9 @@ int table_ews_by_host_by_event_name::rnd_next(void)
case pos_ews_by_host_by_event_name::VIEW_IDLE:
instr_class= find_idle_class(m_pos.m_index_3);
break;
+ case pos_ews_by_host_by_event_name::VIEW_METADATA:
+ instr_class= find_metadata_class(m_pos.m_index_3);
+ break;
default:
instr_class= NULL;
DBUG_ASSERT(false);
@@ -150,10 +162,9 @@ table_ews_by_host_by_event_name::rnd_pos(const void *pos)
PFS_instr_class *instr_class;
set_position(pos);
- DBUG_ASSERT(m_pos.m_index_1 < host_max);
- host= &host_array[m_pos.m_index_1];
- if (! host->m_lock.is_populated())
+ host= global_host_container.get(m_pos.m_index_1);
+ if (host == NULL)
return HA_ERR_RECORD_DELETED;
switch (m_pos.m_index_2)
@@ -179,6 +190,9 @@ table_ews_by_host_by_event_name::rnd_pos(const void *pos)
case pos_ews_by_host_by_event_name::VIEW_IDLE:
instr_class= find_idle_class(m_pos.m_index_3);
break;
+ case pos_ews_by_host_by_event_name::VIEW_METADATA:
+ instr_class= find_metadata_class(m_pos.m_index_3);
+ break;
default:
instr_class= NULL;
DBUG_ASSERT(false);
@@ -196,7 +210,7 @@ table_ews_by_host_by_event_name::rnd_pos(const void *pos)
void table_ews_by_host_by_event_name
::make_row(PFS_host *host, PFS_instr_class *klass)
{
- pfs_lock lock;
+ pfs_optimistic_state lock;
m_row_exists= false;
host->m_lock.begin_optimistic_lock(&lock);
@@ -207,7 +221,11 @@ void table_ews_by_host_by_event_name
m_row.m_event_name.make_row(klass);
PFS_connection_wait_visitor visitor(klass);
- PFS_connection_iterator::visit_host(host, true, true, & visitor);
+ PFS_connection_iterator::visit_host(host,
+ true, /* accounts */
+ true, /* threads */
+ false, /* THDs */
+ & visitor);
if (! host->m_lock.end_optimistic_lock(&lock))
return;
diff --git a/storage/perfschema/table_ews_by_host_by_event_name.h b/storage/perfschema/table_ews_by_host_by_event_name.h
index 8ce44a96617..074ec0be822 100644
--- a/storage/perfschema/table_ews_by_host_by_event_name.h
+++ b/storage/perfschema/table_ews_by_host_by_event_name.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -75,9 +75,6 @@ struct pos_ews_by_host_by_event_name
m_index_3= 1;
}
- inline bool has_more_host(void)
- { return (m_index_1 < host_max); }
-
inline void next_host(void)
{
m_index_1++;
@@ -103,6 +100,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_next();
virtual int rnd_pos(const void *pos);
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 33f9765310b..11b8a84dd46 100644
--- a/storage/perfschema/table_ews_by_thread_by_event_name.cc
+++ b/storage/perfschema/table_ews_by_thread_by_event_name.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -26,13 +26,15 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_instr_class.h"
#include "pfs_column_types.h"
#include "pfs_column_values.h"
#include "table_ews_by_thread_by_event_name.h"
#include "pfs_global.h"
#include "pfs_visitor.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
THR_LOCK table_ews_by_thread_by_event_name::m_table_lock;
@@ -44,8 +46,7 @@ table_ews_by_thread_by_event_name::m_share=
table_ews_by_thread_by_event_name::create,
NULL, /* write_row */
table_ews_by_thread_by_event_name::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ table_ews_by_thread_by_event_name::get_row_count,
sizeof(pos_ews_by_thread_by_event_name),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE events_waits_summary_by_thread_by_event_name("
@@ -55,7 +56,8 @@ table_ews_by_thread_by_event_name::m_share=
"SUM_TIMER_WAIT BIGINT unsigned not null,"
"MIN_TIMER_WAIT BIGINT unsigned not null,"
"AVG_TIMER_WAIT BIGINT unsigned not null,"
- "MAX_TIMER_WAIT BIGINT unsigned not null)") }
+ "MAX_TIMER_WAIT BIGINT unsigned not null)") },
+ false /* perpetual */
};
PFS_engine_table*
@@ -71,6 +73,12 @@ table_ews_by_thread_by_event_name::delete_all_rows(void)
return 0;
}
+ha_rows
+table_ews_by_thread_by_event_name::get_row_count(void)
+{
+ return global_thread_container.get_row_count() * wait_class_max;
+}
+
table_ews_by_thread_by_event_name::table_ews_by_thread_by_event_name()
: PFS_engine_table(&m_share, &m_pos),
m_row_exists(false), m_pos(), m_next_pos()
@@ -86,18 +94,14 @@ int table_ews_by_thread_by_event_name::rnd_next(void)
{
PFS_thread *thread;
PFS_instr_class *instr_class;
+ bool has_more_thread= true;
for (m_pos.set_at(&m_next_pos);
- m_pos.has_more_thread();
+ has_more_thread;
m_pos.next_thread())
{
- thread= &thread_array[m_pos.m_index_1];
-
- /*
- Important note: the thread scan is the outer loop (index 1),
- to minimize the number of calls to atomic operations.
- */
- if (thread->m_lock.is_populated())
+ thread= global_thread_container.get(m_pos.m_index_1, & has_more_thread);
+ if (thread != NULL)
{
for ( ;
m_pos.has_more_view();
@@ -126,6 +130,9 @@ int table_ews_by_thread_by_event_name::rnd_next(void)
case pos_ews_by_thread_by_event_name::VIEW_IDLE:
instr_class= find_idle_class(m_pos.m_index_3);
break;
+ case pos_ews_by_thread_by_event_name::VIEW_METADATA:
+ instr_class= find_metadata_class(m_pos.m_index_3);
+ break;
default:
DBUG_ASSERT(false);
instr_class= NULL;
@@ -152,52 +159,55 @@ table_ews_by_thread_by_event_name::rnd_pos(const void *pos)
PFS_instr_class *instr_class;
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;
- switch (m_pos.m_index_2)
+ thread= global_thread_container.get(m_pos.m_index_1);
+ if (thread != NULL)
{
- case pos_ews_by_thread_by_event_name::VIEW_MUTEX:
- instr_class= find_mutex_class(m_pos.m_index_3);
- break;
- case pos_ews_by_thread_by_event_name::VIEW_RWLOCK:
- instr_class= find_rwlock_class(m_pos.m_index_3);
- break;
- case pos_ews_by_thread_by_event_name::VIEW_COND:
- instr_class= find_cond_class(m_pos.m_index_3);
- break;
- case pos_ews_by_thread_by_event_name::VIEW_FILE:
- instr_class= find_file_class(m_pos.m_index_3);
- break;
- case pos_ews_by_thread_by_event_name::VIEW_TABLE:
- instr_class= find_table_class(m_pos.m_index_3);
- break;
- case pos_ews_by_thread_by_event_name::VIEW_SOCKET:
- instr_class= find_socket_class(m_pos.m_index_3);
- break;
- case pos_ews_by_thread_by_event_name::VIEW_IDLE:
- instr_class= find_idle_class(m_pos.m_index_3);
- break;
- default:
- DBUG_ASSERT(false);
- instr_class= NULL;
- }
+ switch (m_pos.m_index_2)
+ {
+ case pos_ews_by_thread_by_event_name::VIEW_MUTEX:
+ instr_class= find_mutex_class(m_pos.m_index_3);
+ break;
+ case pos_ews_by_thread_by_event_name::VIEW_RWLOCK:
+ instr_class= find_rwlock_class(m_pos.m_index_3);
+ break;
+ case pos_ews_by_thread_by_event_name::VIEW_COND:
+ instr_class= find_cond_class(m_pos.m_index_3);
+ break;
+ case pos_ews_by_thread_by_event_name::VIEW_FILE:
+ instr_class= find_file_class(m_pos.m_index_3);
+ break;
+ case pos_ews_by_thread_by_event_name::VIEW_TABLE:
+ instr_class= find_table_class(m_pos.m_index_3);
+ break;
+ case pos_ews_by_thread_by_event_name::VIEW_SOCKET:
+ instr_class= find_socket_class(m_pos.m_index_3);
+ break;
+ case pos_ews_by_thread_by_event_name::VIEW_IDLE:
+ instr_class= find_idle_class(m_pos.m_index_3);
+ break;
+ case pos_ews_by_thread_by_event_name::VIEW_METADATA:
+ instr_class= find_metadata_class(m_pos.m_index_3);
+ break;
+ default:
+ DBUG_ASSERT(false);
+ instr_class= NULL;
+ }
- if (instr_class)
- {
- make_row(thread, instr_class);
- return 0;
+ if (instr_class)
+ {
+ make_row(thread, instr_class);
+ return 0;
+ }
}
+
return HA_ERR_RECORD_DELETED;
}
void table_ews_by_thread_by_event_name
::make_row(PFS_thread *thread, PFS_instr_class *klass)
{
- pfs_lock lock;
+ pfs_optimistic_state lock;
m_row_exists= false;
/* Protect this reader against a thread termination */
@@ -211,9 +221,9 @@ void table_ews_by_thread_by_event_name
PFS_connection_iterator::visit_thread(thread, &visitor);
/*
- If the aggregation for this class is deferred, then we must pull the
- current wait stats from the instances associated with this thread.
- */
+ If the aggregation for this class is deferred, then we must pull the
+ current wait stats from the instances associated with this thread.
+ */
if (klass->is_deferred())
{
/* Visit instances owned by this thread. Do not visit the class. */
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 b67664bfced..d3850e93c0a 100644
--- a/storage/perfschema/table_ews_by_thread_by_event_name.h
+++ b/storage/perfschema/table_ews_by_thread_by_event_name.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -74,9 +74,6 @@ struct pos_ews_by_thread_by_event_name
m_index_3= 1;
}
- inline bool has_more_thread(void)
- { return (m_index_1 < thread_max); }
-
inline void next_thread(void)
{
m_index_1++;
@@ -102,6 +99,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_next();
virtual int rnd_pos(const void *pos);
diff --git a/storage/perfschema/table_ews_by_user_by_event_name.cc b/storage/perfschema/table_ews_by_user_by_event_name.cc
index cb99f749a9c..5425d773f85 100644
--- a/storage/perfschema/table_ews_by_user_by_event_name.cc
+++ b/storage/perfschema/table_ews_by_user_by_event_name.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -26,14 +26,15 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_instr_class.h"
#include "pfs_column_types.h"
#include "pfs_column_values.h"
#include "table_ews_by_user_by_event_name.h"
#include "pfs_global.h"
-#include "pfs_account.h"
#include "pfs_visitor.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
THR_LOCK table_ews_by_user_by_event_name::m_table_lock;
@@ -45,18 +46,18 @@ table_ews_by_user_by_event_name::m_share=
table_ews_by_user_by_event_name::create,
NULL, /* write_row */
table_ews_by_user_by_event_name::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ table_ews_by_user_by_event_name::get_row_count,
sizeof(pos_ews_by_user_by_event_name),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE events_waits_summary_by_user_by_event_name("
- "USER CHAR(16) collate utf8_bin default null,"
+ "USER CHAR(" USERNAME_CHAR_LENGTH_STR ") collate utf8_bin default null,"
"EVENT_NAME VARCHAR(128) not null,"
"COUNT_STAR BIGINT unsigned not null,"
"SUM_TIMER_WAIT BIGINT unsigned not null,"
"MIN_TIMER_WAIT BIGINT unsigned not null,"
"AVG_TIMER_WAIT BIGINT unsigned not null,"
- "MAX_TIMER_WAIT BIGINT unsigned not null)") }
+ "MAX_TIMER_WAIT BIGINT unsigned not null)") },
+ false /* perpetual */
};
PFS_engine_table*
@@ -74,6 +75,12 @@ table_ews_by_user_by_event_name::delete_all_rows(void)
return 0;
}
+ha_rows
+table_ews_by_user_by_event_name::get_row_count(void)
+{
+ return global_user_container.get_row_count() * wait_class_max;
+}
+
table_ews_by_user_by_event_name::table_ews_by_user_by_event_name()
: PFS_engine_table(&m_share, &m_pos),
m_row_exists(false), m_pos(), m_next_pos()
@@ -89,13 +96,14 @@ int table_ews_by_user_by_event_name::rnd_next(void)
{
PFS_user *user;
PFS_instr_class *instr_class;
+ bool has_more_user= true;
for (m_pos.set_at(&m_next_pos);
- m_pos.has_more_user();
+ has_more_user;
m_pos.next_user())
{
- user= &user_array[m_pos.m_index_1];
- if (user->m_lock.is_populated())
+ user= global_user_container.get(m_pos.m_index_1, & has_more_user);
+ if (user != NULL)
{
for ( ;
m_pos.has_more_view();
@@ -124,6 +132,9 @@ int table_ews_by_user_by_event_name::rnd_next(void)
case pos_ews_by_user_by_event_name::VIEW_IDLE:
instr_class= find_idle_class(m_pos.m_index_3);
break;
+ case pos_ews_by_user_by_event_name::VIEW_METADATA:
+ instr_class= find_metadata_class(m_pos.m_index_3);
+ break;
default:
instr_class= NULL;
DBUG_ASSERT(false);
@@ -150,10 +161,9 @@ table_ews_by_user_by_event_name::rnd_pos(const void *pos)
PFS_instr_class *instr_class;
set_position(pos);
- DBUG_ASSERT(m_pos.m_index_1 < user_max);
- user= &user_array[m_pos.m_index_1];
- if (! user->m_lock.is_populated())
+ user= global_user_container.get(m_pos.m_index_1);
+ if (user == NULL)
return HA_ERR_RECORD_DELETED;
switch (m_pos.m_index_2)
@@ -179,6 +189,9 @@ table_ews_by_user_by_event_name::rnd_pos(const void *pos)
case pos_ews_by_user_by_event_name::VIEW_IDLE:
instr_class= find_idle_class(m_pos.m_index_3);
break;
+ case pos_ews_by_user_by_event_name::VIEW_METADATA:
+ instr_class= find_metadata_class(m_pos.m_index_3);
+ break;
default:
instr_class= NULL;
DBUG_ASSERT(false);
@@ -196,7 +209,7 @@ table_ews_by_user_by_event_name::rnd_pos(const void *pos)
void table_ews_by_user_by_event_name
::make_row(PFS_user *user, PFS_instr_class *klass)
{
- pfs_lock lock;
+ pfs_optimistic_state lock;
m_row_exists= false;
user->m_lock.begin_optimistic_lock(&lock);
@@ -207,7 +220,11 @@ void table_ews_by_user_by_event_name
m_row.m_event_name.make_row(klass);
PFS_connection_wait_visitor visitor(klass);
- PFS_connection_iterator::visit_user(user, true, true, & visitor);
+ PFS_connection_iterator::visit_user(user,
+ true, /* accounts */
+ true, /* threads */
+ false, /* THDs */
+ & visitor);
if (! user->m_lock.end_optimistic_lock(&lock))
return;
diff --git a/storage/perfschema/table_ews_by_user_by_event_name.h b/storage/perfschema/table_ews_by_user_by_event_name.h
index f4f29534be4..b088c8e2015 100644
--- a/storage/perfschema/table_ews_by_user_by_event_name.h
+++ b/storage/perfschema/table_ews_by_user_by_event_name.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -75,9 +75,6 @@ struct pos_ews_by_user_by_event_name
m_index_3= 1;
}
- inline bool has_more_user(void)
- { return (m_index_1 < user_max); }
-
inline void next_user(void)
{
m_index_1++;
@@ -103,6 +100,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_next();
virtual int rnd_pos(const void *pos);
diff --git a/storage/perfschema/table_ews_global_by_event_name.cc b/storage/perfschema/table_ews_global_by_event_name.cc
index 7420c6351fd..13839ddba2b 100644
--- a/storage/perfschema/table_ews_global_by_event_name.cc
+++ b/storage/perfschema/table_ews_global_by_event_name.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -26,7 +26,7 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_instr_class.h"
#include "pfs_column_types.h"
#include "pfs_column_values.h"
@@ -35,6 +35,7 @@
#include "pfs_instr.h"
#include "pfs_timer.h"
#include "pfs_visitor.h"
+#include "field.h"
THR_LOCK table_ews_global_by_event_name::m_table_lock;
@@ -46,8 +47,7 @@ table_ews_global_by_event_name::m_share=
table_ews_global_by_event_name::create,
NULL, /* write_row */
table_ews_global_by_event_name::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ table_ews_global_by_event_name::get_row_count,
sizeof(pos_ews_global_by_event_name),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE events_waits_summary_global_by_event_name("
@@ -56,7 +56,8 @@ table_ews_global_by_event_name::m_share=
"SUM_TIMER_WAIT BIGINT unsigned not null,"
"MIN_TIMER_WAIT BIGINT unsigned not null,"
"AVG_TIMER_WAIT BIGINT unsigned not null,"
- "MAX_TIMER_WAIT BIGINT unsigned not null)") }
+ "MAX_TIMER_WAIT BIGINT unsigned not null)") },
+ false /* perpetual */
};
PFS_engine_table*
@@ -75,6 +76,12 @@ table_ews_global_by_event_name::delete_all_rows(void)
return 0;
}
+ha_rows
+table_ews_global_by_event_name::get_row_count(void)
+{
+ return wait_class_max;
+}
+
table_ews_global_by_event_name::table_ews_global_by_event_name()
: PFS_engine_table(&m_share, &m_pos),
m_row_exists(false), m_pos(), m_next_pos()
@@ -169,6 +176,15 @@ int table_ews_global_by_event_name::rnd_next(void)
return 0;
}
break;
+ case pos_ews_global_by_event_name::VIEW_METADATA:
+ instr_class= find_metadata_class(m_pos.m_index_2);
+ if (instr_class)
+ {
+ make_metadata_row(instr_class);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+ break;
default:
break;
}
@@ -247,6 +263,17 @@ table_ews_global_by_event_name::rnd_pos(const void *pos)
return 0;
}
break;
+ case pos_ews_global_by_event_name::VIEW_METADATA:
+ instr_class= find_metadata_class(m_pos.m_index_2);
+ if (instr_class)
+ {
+ make_metadata_row(instr_class);
+ return 0;
+ }
+ break;
+ default:
+ DBUG_ASSERT(false);
+ break;
}
return HA_ERR_RECORD_DELETED;
@@ -324,7 +351,7 @@ void table_ews_global_by_event_name
PFS_table_lock_wait_visitor visitor;
PFS_object_iterator::visit_all_tables(& visitor);
-
+
get_normalizer(klass);
m_row.m_stat.set(m_normalizer, & visitor.m_stat);
m_row_exists= true;
@@ -351,8 +378,27 @@ void table_ews_global_by_event_name
PFS_connection_wait_visitor visitor(klass);
PFS_connection_iterator::visit_global(false, /* hosts */
false, /* users */
- false, /* accts */
- true, /* threads */ &visitor);
+ false, /* accounts */
+ true, /* threads */
+ false, /* THDs */
+ &visitor);
+ get_normalizer(klass);
+ m_row.m_stat.set(m_normalizer, &visitor.m_stat);
+ m_row_exists= true;
+}
+
+void table_ews_global_by_event_name
+::make_metadata_row(PFS_instr_class *klass)
+{
+ m_row.m_event_name.make_row(klass);
+
+ PFS_connection_wait_visitor visitor(klass);
+ PFS_connection_iterator::visit_global(false, /* hosts */
+ true, /* users */
+ true, /* accounts */
+ true, /* threads */
+ false, /* THDs */
+ &visitor);
get_normalizer(klass);
m_row.m_stat.set(m_normalizer, &visitor.m_stat);
m_row_exists= true;
diff --git a/storage/perfschema/table_ews_global_by_event_name.h b/storage/perfschema/table_ews_global_by_event_name.h
index 8157d274112..a9deb97a52d 100644
--- a/storage/perfschema/table_ews_global_by_event_name.h
+++ b/storage/perfschema/table_ews_global_by_event_name.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -88,6 +88,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_next();
virtual int rnd_pos(const void *pos);
@@ -114,6 +115,7 @@ protected:
void make_table_lock_row(PFS_instr_class *klass);
void make_socket_row(PFS_socket_class *klass);
void make_idle_row(PFS_instr_class *klass);
+ void make_metadata_row(PFS_instr_class *klass);
private:
/** Table share lock. */
diff --git a/storage/perfschema/table_file_instances.cc b/storage/perfschema/table_file_instances.cc
index b323df83ad2..ca77b606200 100644
--- a/storage/perfschema/table_file_instances.cc
+++ b/storage/perfschema/table_file_instances.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -26,12 +26,14 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_instr.h"
#include "pfs_column_types.h"
#include "pfs_column_values.h"
#include "table_file_instances.h"
#include "pfs_global.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
THR_LOCK table_file_instances::m_table_lock;
@@ -40,17 +42,17 @@ table_file_instances::m_share=
{
{ C_STRING_WITH_LEN("file_instances") },
&pfs_readonly_acl,
- &table_file_instances::create,
+ table_file_instances::create,
NULL, /* write_row */
NULL, /* delete_all_rows */
- NULL, /* get_row_count */
- 1000, /* records */
+ table_file_instances::get_row_count,
sizeof(PFS_simple_index),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE file_instances("
"FILE_NAME VARCHAR(512) not null,"
"EVENT_NAME VARCHAR(128) not null,"
- "OPEN_COUNT INTEGER unsigned not null)") }
+ "OPEN_COUNT INTEGER unsigned not null)") },
+ false /* perpetual */
};
PFS_engine_table* table_file_instances::create(void)
@@ -58,6 +60,12 @@ PFS_engine_table* table_file_instances::create(void)
return new table_file_instances();
}
+ha_rows
+table_file_instances::get_row_count(void)
+{
+ return global_file_container.get_row_count();
+}
+
table_file_instances::table_file_instances()
: PFS_engine_table(&m_share, &m_pos),
m_row_exists(false), m_pos(0), m_next_pos(0)
@@ -73,17 +81,14 @@ int table_file_instances::rnd_next(void)
{
PFS_file *pfs;
- for (m_pos.set_at(&m_next_pos);
- m_pos.m_index < file_max;
- m_pos.next())
+ m_pos.set_at(&m_next_pos);
+ PFS_file_iterator it= global_file_container.iterate(m_pos.m_index);
+ pfs= it.scan_next(& m_pos.m_index);
+ if (pfs != NULL)
{
- pfs= &file_array[m_pos.m_index];
- if (pfs->m_lock.is_populated())
- {
- make_row(pfs);
- m_next_pos.set_after(&m_pos);
- return 0;
- }
+ make_row(pfs);
+ m_next_pos.set_after(&m_pos);
+ return 0;
}
return HA_ERR_END_OF_FILE;
@@ -94,19 +99,20 @@ int table_file_instances::rnd_pos(const void *pos)
PFS_file *pfs;
set_position(pos);
- DBUG_ASSERT(m_pos.m_index < file_max);
- pfs= &file_array[m_pos.m_index];
- if (! pfs->m_lock.is_populated())
- return HA_ERR_RECORD_DELETED;
+ pfs= global_file_container.get(m_pos.m_index);
+ if (pfs != NULL)
+ {
+ make_row(pfs);
+ return 0;
+ }
- make_row(pfs);
- return 0;
+ return HA_ERR_RECORD_DELETED;
}
void table_file_instances::make_row(PFS_file *pfs)
{
- pfs_lock lock;
+ pfs_optimistic_state lock;
PFS_file_class *safe_class;
m_row_exists= false;
diff --git a/storage/perfschema/table_file_instances.h b/storage/perfschema/table_file_instances.h
index 5b44e63028e..cb3d39d46fb 100644
--- a/storage/perfschema/table_file_instances.h
+++ b/storage/perfschema/table_file_instances.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -58,6 +58,7 @@ public:
/** Table share */
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
+ static ha_rows get_row_count();
virtual int rnd_next();
virtual int rnd_pos(const void *pos);
diff --git a/storage/perfschema/table_file_summary_by_event_name.cc b/storage/perfschema/table_file_summary_by_event_name.cc
index 459b2bf99a6..404b58187ff 100644
--- a/storage/perfschema/table_file_summary_by_event_name.cc
+++ b/storage/perfschema/table_file_summary_by_event_name.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -21,18 +21,19 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
/**
- @file storage/perfschema/table_file_summary.cc
+ @file storage/perfschema/table_file_summary_by_event_name.cc
Table FILE_SUMMARY_BY_EVENT_NAME(implementation).
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_instr_class.h"
#include "pfs_column_types.h"
#include "pfs_column_values.h"
#include "table_file_summary_by_event_name.h"
#include "pfs_global.h"
#include "pfs_visitor.h"
+#include "field.h"
THR_LOCK table_file_summary_by_event_name::m_table_lock;
@@ -41,11 +42,10 @@ table_file_summary_by_event_name::m_share=
{
{ C_STRING_WITH_LEN("file_summary_by_event_name") },
&pfs_truncatable_acl,
- &table_file_summary_by_event_name::create,
+ table_file_summary_by_event_name::create,
NULL, /* write_row */
table_file_summary_by_event_name::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ table_file_summary_by_event_name::get_row_count,
sizeof(PFS_simple_index),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE file_summary_by_event_name("
@@ -71,7 +71,8 @@ table_file_summary_by_event_name::m_share=
"SUM_TIMER_MISC BIGINT unsigned not null,"
"MIN_TIMER_MISC BIGINT unsigned not null,"
"AVG_TIMER_MISC BIGINT unsigned not null,"
- "MAX_TIMER_MISC BIGINT unsigned not null)") }
+ "MAX_TIMER_MISC BIGINT unsigned not null)") },
+ false /* perpetual */
};
PFS_engine_table* table_file_summary_by_event_name::create(void)
@@ -86,6 +87,12 @@ int table_file_summary_by_event_name::delete_all_rows(void)
return 0;
}
+ha_rows
+table_file_summary_by_event_name::get_row_count(void)
+{
+ return file_class_max;
+}
+
table_file_summary_by_event_name::table_file_summary_by_event_name()
: PFS_engine_table(&m_share, &m_pos),
m_pos(1), m_next_pos(1)
@@ -132,7 +139,7 @@ int table_file_summary_by_event_name::rnd_pos(const void *pos)
/**
Build a row.
- @param klass the file class the cursor is reading
+ @param file_class the file class the cursor is reading
*/
void table_file_summary_by_event_name::make_row(PFS_file_class *file_class)
{
@@ -142,7 +149,7 @@ void table_file_summary_by_event_name::make_row(PFS_file_class *file_class)
PFS_instance_iterator::visit_file_instances(file_class, &visitor);
time_normalizer *normalizer= time_normalizer::get(wait_timer);
-
+
/* Collect timer and byte count stats */
m_row.m_io_stat.set(normalizer, &visitor.m_file_io_stat);
m_row_exists= true;
diff --git a/storage/perfschema/table_file_summary_by_event_name.h b/storage/perfschema/table_file_summary_by_event_name.h
index b8cb293cb07..ae2124fe763 100644
--- a/storage/perfschema/table_file_summary_by_event_name.h
+++ b/storage/perfschema/table_file_summary_by_event_name.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -59,6 +59,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_next();
virtual int rnd_pos(const void *pos);
diff --git a/storage/perfschema/table_file_summary_by_instance.cc b/storage/perfschema/table_file_summary_by_instance.cc
index 3a30984405c..b05d1f24b60 100644
--- a/storage/perfschema/table_file_summary_by_instance.cc
+++ b/storage/perfschema/table_file_summary_by_instance.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -21,17 +21,19 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
/**
- @file storage/perfschema/table_file_summary.cc
+ @file storage/perfschema/table_file_summary_by_instance.cc
Table FILE_SUMMARY_BY_INSTANCE (implementation).
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_instr_class.h"
#include "pfs_column_types.h"
#include "pfs_column_values.h"
#include "table_file_summary_by_instance.h"
#include "pfs_global.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
THR_LOCK table_file_summary_by_instance::m_table_lock;
@@ -40,11 +42,10 @@ table_file_summary_by_instance::m_share=
{
{ C_STRING_WITH_LEN("file_summary_by_instance") },
&pfs_truncatable_acl,
- &table_file_summary_by_instance::create,
+ table_file_summary_by_instance::create,
NULL, /* write_row */
table_file_summary_by_instance::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ table_file_summary_by_instance::get_row_count,
sizeof(PFS_simple_index),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE file_summary_by_instance("
@@ -72,7 +73,8 @@ table_file_summary_by_instance::m_share=
"SUM_TIMER_MISC BIGINT unsigned not null,"
"MIN_TIMER_MISC BIGINT unsigned not null,"
"AVG_TIMER_MISC BIGINT unsigned not null,"
- "MAX_TIMER_MISC BIGINT unsigned not null)") }
+ "MAX_TIMER_MISC BIGINT unsigned not null)") },
+ false /* perpetual */
};
PFS_engine_table* table_file_summary_by_instance::create(void)
@@ -86,6 +88,12 @@ int table_file_summary_by_instance::delete_all_rows(void)
return 0;
}
+ha_rows
+table_file_summary_by_instance::get_row_count(void)
+{
+ return global_file_container.get_row_count();
+}
+
table_file_summary_by_instance::table_file_summary_by_instance()
: PFS_engine_table(&m_share, &m_pos),
m_row_exists(false), m_pos(0), m_next_pos(0)
@@ -101,17 +109,14 @@ int table_file_summary_by_instance::rnd_next(void)
{
PFS_file *pfs;
- for (m_pos.set_at(&m_next_pos);
- m_pos.m_index < file_max;
- m_pos.next())
+ m_pos.set_at(&m_next_pos);
+ PFS_file_iterator it= global_file_container.iterate(m_pos.m_index);
+ pfs= it.scan_next(& m_pos.m_index);
+ if (pfs != NULL)
{
- pfs= &file_array[m_pos.m_index];
- if (pfs->m_lock.is_populated())
- {
- make_row(pfs);
- m_next_pos.set_after(&m_pos);
- return 0;
- }
+ make_row(pfs);
+ m_next_pos.set_after(&m_pos);
+ return 0;
}
return HA_ERR_END_OF_FILE;
@@ -122,14 +127,15 @@ int table_file_summary_by_instance::rnd_pos(const void *pos)
PFS_file *pfs;
set_position(pos);
- DBUG_ASSERT(m_pos.m_index < file_max);
- pfs= &file_array[m_pos.m_index];
- if (! pfs->m_lock.is_populated())
- return HA_ERR_RECORD_DELETED;
+ pfs= global_file_container.get(m_pos.m_index);
+ if (pfs != NULL)
+ {
+ make_row(pfs);
+ return 0;
+ }
- make_row(pfs);
- return 0;
+ return HA_ERR_RECORD_DELETED;
}
/**
@@ -138,7 +144,7 @@ int table_file_summary_by_instance::rnd_pos(const void *pos)
*/
void table_file_summary_by_instance::make_row(PFS_file *pfs)
{
- pfs_lock lock;
+ pfs_optimistic_state lock;
PFS_file_class *safe_class;
m_row_exists= false;
diff --git a/storage/perfschema/table_file_summary_by_instance.h b/storage/perfschema/table_file_summary_by_instance.h
index 0e7ce6958b2..7ea90bac056 100644
--- a/storage/perfschema/table_file_summary_by_instance.h
+++ b/storage/perfschema/table_file_summary_by_instance.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2011 Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -67,6 +67,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_next();
virtual int rnd_pos(const void *pos);
diff --git a/storage/perfschema/table_global_status.cc b/storage/perfschema/table_global_status.cc
new file mode 100644
index 00000000000..a8d5bacf2f3
--- /dev/null
+++ b/storage/perfschema/table_global_status.cc
@@ -0,0 +1,190 @@
+/* Copyright (c) 2015, 2016, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/**
+ @file storage/perfschema/table_global_status.cc
+ Table global_status (implementation).
+*/
+
+#include "my_global.h"
+#include "table_global_status.h"
+#include "my_thread.h"
+#include "pfs_instr_class.h"
+#include "pfs_column_types.h"
+#include "pfs_column_values.h"
+#include "pfs_global.h"
+
+THR_LOCK table_global_status::m_table_lock;
+
+PFS_engine_table_share
+table_global_status::m_share=
+{
+ { C_STRING_WITH_LEN("global_status") },
+ &pfs_truncatable_world_acl,
+ table_global_status::create,
+ NULL, /* write_row */
+ table_global_status::delete_all_rows,
+ table_global_status::get_row_count,
+ sizeof(pos_t),
+ &m_table_lock,
+ { C_STRING_WITH_LEN("CREATE TABLE global_status("
+ "VARIABLE_NAME VARCHAR(64) not null,"
+ "VARIABLE_VALUE VARCHAR(1024))") },
+ true /* perpetual */
+};
+
+PFS_engine_table*
+table_global_status::create(void)
+{
+ return new table_global_status();
+}
+
+int table_global_status::delete_all_rows(void)
+{
+ mysql_mutex_lock(&LOCK_status);
+ reset_status_by_thread();
+ reset_status_by_account();
+ reset_status_by_user();
+ reset_status_by_host();
+ reset_global_status();
+ mysql_mutex_unlock(&LOCK_status);
+ return 0;
+}
+
+ha_rows table_global_status::get_row_count(void)
+{
+ mysql_mutex_lock(&LOCK_status);
+ ha_rows status_var_count= all_status_vars.elements;
+ mysql_mutex_unlock(&LOCK_status);
+ return status_var_count;
+}
+
+table_global_status::table_global_status()
+ : PFS_engine_table(&m_share, &m_pos),
+ m_status_cache(false), m_row_exists(false), m_pos(0), m_next_pos(0)
+{}
+
+void table_global_status::reset_position(void)
+{
+ m_pos.m_index= 0;
+ m_next_pos.m_index= 0;
+}
+
+int table_global_status::rnd_init(bool scan)
+{
+ /* Build a cache of all global status variables. Sum across threads. */
+ m_status_cache.materialize_global();
+
+ /* Record the current number of status variables to detect subsequent changes. */
+ ulonglong status_version= m_status_cache.get_status_array_version();
+
+ /*
+ The table context holds the current version of the global status array.
+ If scan == true, then allocate a new context from mem_root and store in TLS.
+ If scan == false, then restore from TLS.
+ */
+ m_context= (table_global_status_context *)current_thd->alloc(sizeof(table_global_status_context));
+ new(m_context) table_global_status_context(status_version, !scan);
+ return 0;
+}
+
+int table_global_status::rnd_next(void)
+{
+ for (m_pos.set_at(&m_next_pos);
+ m_pos.m_index < m_status_cache.size();
+ m_pos.next())
+ {
+ const Status_variable *status_var= m_status_cache.get(m_pos.m_index);
+ if (status_var != NULL)
+ {
+ make_row(status_var);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+ }
+ return HA_ERR_END_OF_FILE;
+}
+
+int table_global_status::rnd_pos(const void *pos)
+{
+ /* If global status array has changed, do nothing. */ // TODO: Issue warning
+ if (!m_context->versions_match())
+ return HA_ERR_RECORD_DELETED;
+
+ set_position(pos);
+ const Status_variable *status_var= m_status_cache.get(m_pos.m_index);
+ if (status_var != NULL)
+ {
+ make_row(status_var);
+ return 0;
+ }
+
+ return HA_ERR_RECORD_DELETED;
+}
+
+void table_global_status
+::make_row(const Status_variable *status_var)
+{
+ m_row_exists= false;
+ if (status_var->is_null())
+ return;
+ m_row.m_variable_name.make_row(status_var->m_name, status_var->m_name_length);
+ m_row.m_variable_value.make_row(status_var);
+ m_row_exists= true;
+}
+
+int table_global_status
+::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 0: /* VARIABLE_NAME */
+ set_field_varchar_utf8(f, m_row.m_variable_name.m_str, m_row.m_variable_name.m_length);
+ break;
+ case 1: /* VARIABLE_VALUE */
+ m_row.m_variable_value.set_field(f);
+ break;
+ default:
+ DBUG_ASSERT(false);
+ }
+ }
+ }
+
+ return 0;
+}
+
diff --git a/storage/perfschema/table_global_status.h b/storage/perfschema/table_global_status.h
new file mode 100644
index 00000000000..a97ea9d0041
--- /dev/null
+++ b/storage/perfschema/table_global_status.h
@@ -0,0 +1,118 @@
+/* Copyright (c) 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#ifndef TABLE_GLOBAL_STATUS_H
+#define TABLE_GLOBAL_STATUS_H
+
+/**
+ @file storage/perfschema/table_global_status.h
+ Table global_status (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "pfs_instr_class.h"
+#include "pfs_instr.h"
+#include "pfs_variable.h"
+#include "table_helper.h"
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+/**
+ A row of table
+ PERFORMANCE_SCHEMA.GLOBAL_STATUS.
+*/
+struct row_global_status
+{
+ /** Column VARIABLE_NAME. */
+ PFS_variable_name_row m_variable_name;
+ /** Column VARIABLE_VALUE. */
+ PFS_variable_value_row m_variable_value;
+};
+
+/**
+ Store and retrieve table state information for queries that reinstantiate
+ the table object.
+*/
+class table_global_status_context : public PFS_table_context
+{
+public:
+ table_global_status_context(ulonglong current_version, bool restore) :
+ PFS_table_context(current_version, restore, THR_PFS_SG) { }
+};
+
+/** Table PERFORMANCE_SCHEMA.GLOBAL_STATUS. */
+class table_global_status : public PFS_engine_table
+{
+ typedef PFS_simple_index pos_t;
+
+public:
+ /** Table share */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static int delete_all_rows();
+ static ha_rows get_row_count();
+
+ virtual int rnd_init(bool scan);
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+protected:
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+ table_global_status();
+
+public:
+ ~table_global_status()
+ {}
+
+protected:
+ void make_row(const Status_variable *system_var);
+
+private:
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /** Fields definition. */
+ static TABLE_FIELD_DEF m_field_def;
+
+ /** Current THD variables. */
+ PFS_status_variable_cache m_status_cache;
+ /** Current row. */
+ row_global_status m_row;
+ /** True if the current row exists. */
+ bool m_row_exists;
+ /** Current position. */
+ pos_t m_pos;
+ /** Next position. */
+ pos_t m_next_pos;
+
+ /** Table context with global status array version. */
+ table_global_status_context *m_context;
+};
+
+/** @} */
+#endif
diff --git a/storage/perfschema/table_global_variables.cc b/storage/perfschema/table_global_variables.cc
new file mode 100644
index 00000000000..9e8c1af2ece
--- /dev/null
+++ b/storage/perfschema/table_global_variables.cc
@@ -0,0 +1,184 @@
+/* Copyright (c) 2015, 2018, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/**
+ @file storage/perfschema/table_global_variables.cc
+ Table GLOBAL_VARIABLES (implementation).
+*/
+
+#include "my_global.h"
+#include "table_global_variables.h"
+#include "my_thread.h"
+#include "pfs_instr_class.h"
+#include "pfs_column_types.h"
+#include "pfs_column_values.h"
+#include "pfs_global.h"
+
+THR_LOCK table_global_variables::m_table_lock;
+
+PFS_engine_table_share
+table_global_variables::m_share=
+{
+ { C_STRING_WITH_LEN("global_variables") },
+ &pfs_readonly_world_acl,
+ table_global_variables::create,
+ NULL, /* write_row */
+ NULL, /* delete_all_rows */
+ table_global_variables::get_row_count,
+ sizeof(pos_t),
+ &m_table_lock,
+ { C_STRING_WITH_LEN("CREATE TABLE global_variables("
+ "VARIABLE_NAME VARCHAR(64) not null,"
+ "VARIABLE_VALUE VARCHAR(1024))") },
+ true /* perpetual */
+};
+
+PFS_engine_table*
+table_global_variables::create(void)
+{
+ return new table_global_variables();
+}
+
+ha_rows table_global_variables::get_row_count(void)
+{
+ mysql_mutex_lock(&LOCK_plugin_delete);
+ mysql_rwlock_rdlock(&LOCK_system_variables_hash);
+ ha_rows system_var_count= get_system_variable_hash_records();
+ mysql_rwlock_unlock(&LOCK_system_variables_hash);
+ mysql_mutex_unlock(&LOCK_plugin_delete);
+ return system_var_count;
+}
+
+table_global_variables::table_global_variables()
+ : PFS_engine_table(&m_share, &m_pos),
+ m_sysvar_cache(false), m_row_exists(false), m_pos(0), m_next_pos(0)
+{}
+
+void table_global_variables::reset_position(void)
+{
+ m_pos.m_index= 0;
+ m_next_pos.m_index= 0;
+}
+
+int table_global_variables::rnd_init(bool scan)
+{
+ /*
+ Build a list of system variables from the global system variable hash.
+ Filter by scope.
+ */
+ m_sysvar_cache.materialize_global();
+
+ /* Record the version of the system variable hash. */
+ ulonglong hash_version= m_sysvar_cache.get_sysvar_hash_version();
+
+ /*
+ The table context holds the current version of the system variable hash.
+ If scan == true, then allocate a new context from mem_root and store in TLS.
+ If scan == false, then restore from TLS.
+ */
+ m_context= (table_global_variables_context *)current_thd->alloc(sizeof(table_global_variables_context));
+ new(m_context) table_global_variables_context(hash_version, !scan);
+ return 0;
+}
+
+int table_global_variables::rnd_next(void)
+{
+ for (m_pos.set_at(&m_next_pos);
+ m_pos.m_index < m_sysvar_cache.size();
+ m_pos.next())
+ {
+ const System_variable *system_var= m_sysvar_cache.get(m_pos.m_index);
+ if (system_var != NULL)
+ {
+ make_row(system_var);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+ }
+ return HA_ERR_END_OF_FILE;
+}
+
+int table_global_variables::rnd_pos(const void *pos)
+{
+ /* If system variable hash changes, do nothing. */ // TODO: Issue warning
+ if (!m_context->versions_match())
+ return HA_ERR_RECORD_DELETED;
+
+ set_position(pos);
+ DBUG_ASSERT(m_pos.m_index < m_sysvar_cache.size());
+
+ const System_variable *system_var= m_sysvar_cache.get(m_pos.m_index);
+ if (system_var != NULL)
+ {
+ make_row(system_var);
+ return 0;
+ }
+ return HA_ERR_RECORD_DELETED;
+}
+
+void table_global_variables
+::make_row(const System_variable *system_var)
+{
+ m_row_exists= false;
+ if (system_var->is_null() || system_var->is_ignored())
+ return;
+ m_row.m_variable_name.make_row(system_var->m_name, system_var->m_name_length);
+ m_row.m_variable_value.make_row(system_var);
+ m_row_exists= true;
+}
+
+int table_global_variables
+::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 0: /* VARIABLE_NAME */
+ set_field_varchar_utf8(f, m_row.m_variable_name.m_str, m_row.m_variable_name.m_length);
+ break;
+ case 1: /* VARIABLE_VALUE */
+ m_row.m_variable_value.set_field(f);
+ break;
+ default:
+ DBUG_ASSERT(false);
+ }
+ }
+ }
+
+ return 0;
+}
+
diff --git a/storage/perfschema/table_global_variables.h b/storage/perfschema/table_global_variables.h
new file mode 100644
index 00000000000..b9124e76f65
--- /dev/null
+++ b/storage/perfschema/table_global_variables.h
@@ -0,0 +1,117 @@
+/* Copyright (c) 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#ifndef TABLE_GLOBAL_VARIABLES_H
+#define TABLE_GLOBAL_VARIABLES_H
+
+/**
+ @file storage/perfschema/table_global_variables.h
+ Table GLOBAL_VARIABLES (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "pfs_instr_class.h"
+#include "pfs_instr.h"
+#include "pfs_variable.h"
+#include "table_helper.h"
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+/**
+ Store and retrieve table state information during queries that reinstantiate
+ the table object.
+*/
+class table_global_variables_context : public PFS_table_context
+{
+public:
+ table_global_variables_context(ulonglong hash_version, bool restore) :
+ PFS_table_context(hash_version, restore, THR_PFS_VG) {}
+};
+
+/**
+ A row of table
+ PERFORMANCE_SCHEMA.GLOBAL_VARIABLES.
+*/
+struct row_global_variables
+{
+ /** Column VARIABLE_NAME. */
+ PFS_variable_name_row m_variable_name;
+ /** Column VARIABLE_VALUE. */
+ PFS_variable_value_row m_variable_value;
+};
+
+/** Table PERFORMANCE_SCHEMA.GLOBAL_VARIABLES. */
+class table_global_variables : public PFS_engine_table
+{
+ typedef PFS_simple_index pos_t;
+
+public:
+ /** Table share */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static ha_rows get_row_count();
+
+ virtual int rnd_init(bool scan);
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+protected:
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+ table_global_variables();
+
+public:
+ ~table_global_variables()
+ {}
+
+protected:
+ void make_row(const System_variable *system_var);
+
+private:
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /** Fields definition. */
+ static TABLE_FIELD_DEF m_field_def;
+
+ /** Current THD variables. */
+ PFS_system_variable_cache m_sysvar_cache;
+ /** Current row. */
+ row_global_variables m_row;
+ /** True if the current row exists. */
+ bool m_row_exists;
+ /** Current position. */
+ pos_t m_pos;
+ /** Next position. */
+ pos_t m_next_pos;
+
+ /** Table context with system variable hash version. */
+ table_global_variables_context *m_context;
+};
+
+/** @} */
+#endif
diff --git a/storage/perfschema/table_helper.cc b/storage/perfschema/table_helper.cc
index d6bdd894483..749e15a7113 100644
--- a/storage/perfschema/table_helper.cc
+++ b/storage/perfschema/table_helper.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2016, 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, version 2.0,
@@ -26,13 +26,16 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_engine_table.h"
#include "table_helper.h"
#include "pfs_host.h"
#include "pfs_user.h"
#include "pfs_account.h"
#include "pfs_instr.h"
+#include "pfs_program.h"
+#include "field.h"
+#include "pfs_variable.h"
int PFS_host_row::make_row(PFS_host *pfs)
{
@@ -147,7 +150,6 @@ int PFS_digest_row::make_row(PFS_statements_digest_stat* pfs)
else
{
m_digest_length= 0;
- m_digest_text.length(0);
}
return 0;
@@ -203,6 +205,107 @@ int PFS_object_row::make_row(PFS_table_share *pfs)
return 0;
}
+int PFS_object_row::make_row(PFS_program *pfs)
+{
+ m_object_type= pfs->m_type;
+
+ m_schema_name_length= pfs->m_schema_name_length;
+ if (m_schema_name_length > sizeof(m_schema_name))
+ return 1;
+ if (m_schema_name_length > 0)
+ memcpy(m_schema_name, pfs->m_schema_name, sizeof(m_schema_name));
+
+ m_object_name_length= pfs->m_object_name_length;
+ if (m_object_name_length > sizeof(m_object_name))
+ return 1;
+ if (m_object_name_length > 0)
+ memcpy(m_object_name, pfs->m_object_name, sizeof(m_object_name));
+
+ return 0;
+}
+
+int PFS_object_row::make_row(const MDL_key *mdl)
+{
+ switch(mdl->mdl_namespace())
+ {
+ case MDL_key::GLOBAL:
+ m_object_type= OBJECT_TYPE_GLOBAL;
+ m_schema_name_length= 0;
+ m_object_name_length= 0;
+ break;
+ case MDL_key::SCHEMA:
+ m_object_type= OBJECT_TYPE_SCHEMA;
+ m_schema_name_length= mdl->db_name_length();
+ m_object_name_length= 0;
+ break;
+ case MDL_key::TABLE:
+ m_object_type= OBJECT_TYPE_TABLE;
+ m_schema_name_length= mdl->db_name_length();
+ m_object_name_length= mdl->name_length();
+ break;
+ case MDL_key::FUNCTION:
+ m_object_type= OBJECT_TYPE_FUNCTION;
+ m_schema_name_length= mdl->db_name_length();
+ m_object_name_length= mdl->name_length();
+ break;
+ case MDL_key::PROCEDURE:
+ m_object_type= OBJECT_TYPE_PROCEDURE;
+ m_schema_name_length= mdl->db_name_length();
+ m_object_name_length= mdl->name_length();
+ break;
+ case MDL_key::TRIGGER:
+ m_object_type= OBJECT_TYPE_TRIGGER;
+ m_schema_name_length= mdl->db_name_length();
+ m_object_name_length= mdl->name_length();
+ break;
+ case MDL_key::EVENT:
+ m_object_type= OBJECT_TYPE_EVENT;
+ m_schema_name_length= mdl->db_name_length();
+ m_object_name_length= mdl->name_length();
+ break;
+ case MDL_key::COMMIT:
+ m_object_type= OBJECT_TYPE_COMMIT;
+ m_schema_name_length= 0;
+ m_object_name_length= 0;
+ break;
+ case MDL_key::USER_LOCK:
+ m_object_type= OBJECT_TYPE_USER_LEVEL_LOCK;
+ m_schema_name_length= 0;
+ m_object_name_length= mdl->name_length();
+ break;
+#if 0
+ case MDL_key::TABLESPACE:
+ m_object_type= OBJECT_TYPE_TABLESPACE;
+ m_schema_name_length= 0;
+ m_object_name_length= mdl->name_length();
+ break;
+ case MDL_key::LOCKING_SERVICE:
+ m_object_type= OBJECT_TYPE_LOCKING_SERVICE;
+ m_schema_name_length= mdl->db_name_length();
+ m_object_name_length= mdl->name_length();
+ break;
+#endif
+ case MDL_key::NAMESPACE_END:
+ default:
+ m_object_type= NO_OBJECT_TYPE;
+ m_schema_name_length= 0;
+ m_object_name_length= 0;
+ break;
+ }
+
+ if (m_schema_name_length > sizeof(m_schema_name))
+ return 1;
+ if (m_schema_name_length > 0)
+ memcpy(m_schema_name, mdl->db_name(), m_schema_name_length);
+
+ if (m_object_name_length > sizeof(m_object_name))
+ return 1;
+ if (m_object_name_length > 0)
+ memcpy(m_object_name, mdl->name(), m_object_name_length);
+
+ return 0;
+}
+
void PFS_object_row::set_field(uint index, Field *f)
{
switch(index)
@@ -221,21 +324,65 @@ void PFS_object_row::set_field(uint index, Field *f)
}
}
-int PFS_index_row::make_row(PFS_table_share *pfs, uint table_index)
+void PFS_object_row::set_nullable_field(uint index, Field *f)
+{
+ switch(index)
+ {
+ case 0: /* OBJECT_TYPE */
+ if (m_object_type != NO_OBJECT_TYPE)
+ set_field_object_type(f, m_object_type);
+ else
+ f->set_null();
+ break;
+ case 1: /* 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 2: /* OBJECT_NAME */
+ if (m_object_name_length > 0)
+ PFS_engine_table::set_field_varchar_utf8(f, m_object_name, m_object_name_length);
+ else
+ f->set_null();
+ break;
+ default:
+ DBUG_ASSERT(false);
+ }
+}
+
+int PFS_index_row::make_row(PFS_table_share *pfs,
+ PFS_table_share_index *pfs_index,
+ uint table_index)
{
if (m_object_row.make_row(pfs))
return 1;
+ if (pfs_index == NULL)
+ {
+ if (table_index < MAX_INDEXES)
+ {
+ m_index_name_length= sprintf(m_index_name, "(index %d)", table_index);
+ }
+ else
+ {
+ m_index_name_length= 0;
+ }
+ return 0;
+ }
+
if (table_index < MAX_INDEXES)
{
- PFS_table_key *key= &pfs->m_keys[table_index];
- m_index_name_length= key->m_name_length;
+ m_index_name_length= pfs_index->m_key.m_name_length;
if (m_index_name_length > sizeof(m_index_name))
return 1;
- memcpy(m_index_name, key->m_name, sizeof(m_index_name));
+
+ memcpy(m_index_name, pfs_index->m_key.m_name, sizeof(m_index_name));
}
else
+ {
m_index_name_length= 0;
+ }
return 0;
}
@@ -334,6 +481,37 @@ void PFS_statement_stat_row::set_field(uint index, Field *f)
}
}
+void PFS_transaction_stat_row::set_field(uint index, Field *f)
+{
+ switch (index)
+ {
+ case 0: /* COUNT_STAR */
+ case 1: /* SUM_TIMER_WAIT */
+ case 2: /* MIN_TIMER_WAIT */
+ case 3: /* AVG_TIMER_WAIT */
+ case 4: /* MAX_TIMER_WAIT */
+ m_timer1_row.set_field(index, f);
+ break;
+ case 5: /* COUNT_READ_WRITE */
+ case 6: /* SUM_TIMER_READ_WRITE */
+ case 7: /* MIN_TIMER_READ_WRITE */
+ case 8: /* AVG_TIMER_READ_WRITE */
+ case 9: /* MAX_TIMER_READ_WRITE */
+ m_read_write_row.set_field(index-5, f);
+ break;
+ case 10: /* COUNT_READ_ONLY */
+ case 11: /* SUM_TIMER_READ_ONLY */
+ case 12: /* MIN_TIMER_READ_ONLY */
+ case 13: /* AVG_TIMER_READ_ONLY */
+ case 14: /* MAX_TIMER_READ_ONLY */
+ m_read_only_row.set_field(index-10, f);
+ break;
+ default:
+ DBUG_ASSERT(false);
+ break;
+ }
+}
+
void PFS_connection_stat_row::set_field(uint index, Field *f)
{
switch (index)
@@ -354,14 +532,324 @@ void set_field_object_type(Field *f, enum_object_type object_type)
{
switch (object_type)
{
+ case OBJECT_TYPE_EVENT:
+ PFS_engine_table::set_field_varchar_utf8(f, "EVENT", 5);
+ break;
+ case OBJECT_TYPE_FUNCTION:
+ PFS_engine_table::set_field_varchar_utf8(f, "FUNCTION", 8);
+ break;
+ case OBJECT_TYPE_PROCEDURE:
+ PFS_engine_table::set_field_varchar_utf8(f, "PROCEDURE", 9);
+ break;
case OBJECT_TYPE_TABLE:
PFS_engine_table::set_field_varchar_utf8(f, "TABLE", 5);
break;
case OBJECT_TYPE_TEMPORARY_TABLE:
PFS_engine_table::set_field_varchar_utf8(f, "TEMPORARY TABLE", 15);
break;
+ case OBJECT_TYPE_TRIGGER:
+ PFS_engine_table::set_field_varchar_utf8(f, "TRIGGER", 7);
+ break;
+ case OBJECT_TYPE_GLOBAL:
+ PFS_engine_table::set_field_varchar_utf8(f, "GLOBAL", 6);
+ break;
+ case OBJECT_TYPE_SCHEMA:
+ PFS_engine_table::set_field_varchar_utf8(f, "SCHEMA", 6);
+ break;
+ case OBJECT_TYPE_COMMIT:
+ PFS_engine_table::set_field_varchar_utf8(f, "COMMIT", 6);
+ break;
+ case OBJECT_TYPE_USER_LEVEL_LOCK:
+ PFS_engine_table::set_field_varchar_utf8(f, "USER LEVEL LOCK", 15);
+ break;
+ case OBJECT_TYPE_TABLESPACE:
+ PFS_engine_table::set_field_varchar_utf8(f, "TABLESPACE", 10);
+ break;
+ case OBJECT_TYPE_LOCKING_SERVICE:
+ PFS_engine_table::set_field_varchar_utf8(f, "LOCKING SERVICE", 15);
+ break;
+ case NO_OBJECT_TYPE:
default:
DBUG_ASSERT(false);
+ PFS_engine_table::set_field_varchar_utf8(f, "", 0);
+ break;
+ }
+}
+
+void set_field_lock_type(Field *f, PFS_TL_LOCK_TYPE lock_type)
+{
+ switch (lock_type)
+ {
+ case PFS_TL_READ:
+ PFS_engine_table::set_field_varchar_utf8(f, "READ", 4);
+ break;
+ case PFS_TL_READ_WITH_SHARED_LOCKS:
+ PFS_engine_table::set_field_varchar_utf8(f, "READ WITH SHARED LOCKS", 22);
+ break;
+ case PFS_TL_READ_HIGH_PRIORITY:
+ PFS_engine_table::set_field_varchar_utf8(f, "READ HIGH PRIORITY", 18);
+ break;
+ case PFS_TL_READ_NO_INSERT:
+ PFS_engine_table::set_field_varchar_utf8(f, "READ NO INSERT", 14);
+ break;
+ case PFS_TL_WRITE_ALLOW_WRITE:
+ PFS_engine_table::set_field_varchar_utf8(f, "WRITE ALLOW WRITE", 17);
+ break;
+ case PFS_TL_WRITE_CONCURRENT_INSERT:
+ PFS_engine_table::set_field_varchar_utf8(f, "WRITE CONCURRENT INSERT", 23);
+ break;
+ case PFS_TL_WRITE_LOW_PRIORITY:
+ PFS_engine_table::set_field_varchar_utf8(f, "WRITE LOW PRIORITY", 18);
+ break;
+ case PFS_TL_WRITE:
+ PFS_engine_table::set_field_varchar_utf8(f, "WRITE", 5);
+ break;
+ case PFS_TL_READ_EXTERNAL:
+ PFS_engine_table::set_field_varchar_utf8(f, "READ EXTERNAL", 13);
+ break;
+ case PFS_TL_WRITE_EXTERNAL:
+ PFS_engine_table::set_field_varchar_utf8(f, "WRITE EXTERNAL", 14);
+ break;
+ case PFS_TL_NONE:
+ f->set_null();
+ break;
+ default:
+ DBUG_ASSERT(false);
+ }
+}
+
+void set_field_mdl_type(Field *f, opaque_mdl_type mdl_type)
+{
+ enum_mdl_type e= (enum_mdl_type) mdl_type;
+ switch (e)
+ {
+ case MDL_INTENTION_EXCLUSIVE:
+ PFS_engine_table::set_field_varchar_utf8(f, "INTENTION_EXCLUSIVE", 19);
+ break;
+ case MDL_SHARED:
+ PFS_engine_table::set_field_varchar_utf8(f, "SHARED", 6);
+ break;
+ case MDL_SHARED_HIGH_PRIO:
+ PFS_engine_table::set_field_varchar_utf8(f, "SHARED_HIGH_PRIO", 16);
+ break;
+ case MDL_SHARED_READ:
+ PFS_engine_table::set_field_varchar_utf8(f, "SHARED_READ", 11);
+ break;
+ case MDL_SHARED_WRITE:
+ PFS_engine_table::set_field_varchar_utf8(f, "SHARED_WRITE", 12);
+ break;
+ case MDL_SHARED_UPGRADABLE:
+ PFS_engine_table::set_field_varchar_utf8(f, "SHARED_UPGRADABLE", 17);
+ break;
+ case MDL_SHARED_NO_WRITE:
+ PFS_engine_table::set_field_varchar_utf8(f, "SHARED_NO_WRITE", 15);
+ break;
+ case MDL_SHARED_NO_READ_WRITE:
+ PFS_engine_table::set_field_varchar_utf8(f, "SHARED_NO_READ_WRITE", 20);
+ break;
+ case MDL_EXCLUSIVE:
+ PFS_engine_table::set_field_varchar_utf8(f, "EXCLUSIVE", 9);
+ break;
+ default:
+ DBUG_ASSERT(false);
+ }
+}
+
+void set_field_mdl_duration(Field *f, opaque_mdl_duration mdl_duration)
+{
+ enum_mdl_duration e= (enum_mdl_duration) mdl_duration;
+ switch (e)
+ {
+ case MDL_STATEMENT:
+ PFS_engine_table::set_field_varchar_utf8(f, "STATEMENT", 9);
+ break;
+ case MDL_TRANSACTION:
+ PFS_engine_table::set_field_varchar_utf8(f, "TRANSACTION", 11);
+ break;
+ case MDL_EXPLICIT:
+ PFS_engine_table::set_field_varchar_utf8(f, "EXPLICIT", 8);
+ break;
+ case MDL_DURATION_END:
+ default:
+ DBUG_ASSERT(false);
+ }
+}
+
+void set_field_mdl_status(Field *f, opaque_mdl_status mdl_status)
+{
+ enum_psi_status e= static_cast<enum_psi_status>(mdl_status);
+ switch (e)
+ {
+ case PENDING:
+ PFS_engine_table::set_field_varchar_utf8(f, "PENDING", 7);
+ break;
+ case GRANTED:
+ PFS_engine_table::set_field_varchar_utf8(f, "GRANTED", 7);
+ break;
+ case PRE_ACQUIRE_NOTIFY:
+ PFS_engine_table::set_field_varchar_utf8(f, "PRE_ACQUIRE_NOTIFY", 18);
+ break;
+ case POST_RELEASE_NOTIFY:
+ PFS_engine_table::set_field_varchar_utf8(f, "POST_RELEASE_NOTIFY", 19);
+ break;
+ default:
+ DBUG_ASSERT(false);
+ }
+}
+
+void PFS_memory_stat_row::set_field(uint index, Field *f)
+{
+ ssize_t val;
+
+ switch (index)
+ {
+ case 0: /* COUNT_ALLOC */
+ PFS_engine_table::set_field_ulonglong(f, m_stat.m_alloc_count);
+ break;
+ case 1: /* COUNT_FREE */
+ PFS_engine_table::set_field_ulonglong(f, m_stat.m_free_count);
+ break;
+ case 2: /* SUM_NUMBER_OF_BYTES_ALLOC */
+ PFS_engine_table::set_field_ulonglong(f, m_stat.m_alloc_size);
+ break;
+ case 3: /* SUM_NUMBER_OF_BYTES_FREE */
+ PFS_engine_table::set_field_ulonglong(f, m_stat.m_free_size);
+ break;
+ case 4: /* LOW_COUNT_USED */
+ val= m_stat.m_alloc_count - m_stat.m_free_count - m_stat.m_free_count_capacity;
+ PFS_engine_table::set_field_longlong(f, val);
+ break;
+ case 5: /* CURRENT_COUNT_USED */
+ val= m_stat.m_alloc_count - m_stat.m_free_count;
+ PFS_engine_table::set_field_longlong(f, val);
+ break;
+ case 6: /* HIGH_COUNT_USED */
+ val= m_stat.m_alloc_count - m_stat.m_free_count + m_stat.m_alloc_count_capacity;
+ PFS_engine_table::set_field_longlong(f, val);
+ break;
+ case 7: /* LOW_NUMBER_OF_BYTES_USED */
+ val= m_stat.m_alloc_size - m_stat.m_free_size - m_stat.m_free_size_capacity;
+ PFS_engine_table::set_field_longlong(f, val);
+ break;
+ case 8: /* CURRENT_NUMBER_OF_BYTES_USED */
+ val= m_stat.m_alloc_size - m_stat.m_free_size;
+ PFS_engine_table::set_field_longlong(f, val);
+ break;
+ case 9: /* HIGH_NUMBER_OF_BYTES_USED */
+ val= m_stat.m_alloc_size - m_stat.m_free_size + m_stat.m_alloc_size_capacity;
+ PFS_engine_table::set_field_longlong(f, val);
+ break;
+ default:
+ DBUG_ASSERT(false);
+ break;
+ }
+}
+
+void set_field_isolation_level(Field *f, enum_isolation_level iso_level)
+{
+ switch (iso_level)
+ {
+ case TRANS_LEVEL_READ_UNCOMMITTED:
+ PFS_engine_table::set_field_varchar_utf8(f, "READ UNCOMMITTED", 16);
+ break;
+ case TRANS_LEVEL_READ_COMMITTED:
+ PFS_engine_table::set_field_varchar_utf8(f, "READ COMMITTED", 14);
+ break;
+ case TRANS_LEVEL_REPEATABLE_READ:
+ PFS_engine_table::set_field_varchar_utf8(f, "REPEATABLE READ", 15);
+ break;
+ case TRANS_LEVEL_SERIALIZABLE:
+ PFS_engine_table::set_field_varchar_utf8(f, "SERIALIZABLE", 12);
+ break;
+ default:
+ DBUG_ASSERT(false);
+ }
+}
+
+void set_field_xa_state(Field *f, enum_xa_transaction_state xa_state)
+{
+ switch (xa_state)
+ {
+ case TRANS_STATE_XA_NOTR:
+ PFS_engine_table::set_field_varchar_utf8(f, "NOTR", 4);
+ break;
+ case TRANS_STATE_XA_ACTIVE:
+ PFS_engine_table::set_field_varchar_utf8(f, "ACTIVE", 6);
+ break;
+ case TRANS_STATE_XA_IDLE:
+ PFS_engine_table::set_field_varchar_utf8(f, "IDLE", 4);
+ break;
+ case TRANS_STATE_XA_PREPARED:
+ PFS_engine_table::set_field_varchar_utf8(f, "PREPARED", 8);
+ break;
+ case TRANS_STATE_XA_ROLLBACK_ONLY:
+ PFS_engine_table::set_field_varchar_utf8(f, "ROLLBACK ONLY", 13);
+ break;
+ case TRANS_STATE_XA_COMMITTED:
+ PFS_engine_table::set_field_varchar_utf8(f, "COMMITTED", 9);
+ break;
+ default:
+ DBUG_ASSERT(false);
+ }
+}
+
+void PFS_variable_name_row::make_row(const char* str, size_t length)
+{
+ DBUG_ASSERT(length <= sizeof(m_str));
+ DBUG_ASSERT(length <= NAME_CHAR_LEN);
+
+ m_length= MY_MIN(length, NAME_CHAR_LEN); /* enforce max name length */
+ if (m_length > 0)
+ memcpy(m_str, str, length);
+ m_str[m_length]= '\0';
+}
+
+void PFS_variable_value_row::make_row(const Status_variable *var)
+{
+ make_row(var->m_charset, var->m_value_str, var->m_value_length);
+}
+
+void PFS_variable_value_row::make_row(const System_variable *var)
+{
+ make_row(var->m_charset, var->m_value_str, var->m_value_length);
+}
+
+void PFS_variable_value_row::make_row(const CHARSET_INFO *cs, const char* str, size_t length)
+{
+ DBUG_ASSERT(cs != NULL);
+ DBUG_ASSERT(length <= sizeof(m_str));
+ if (length > 0)
+ {
+ memcpy(m_str, str, length);
+ }
+ m_length= length;
+ m_charset= cs;
+}
+
+void PFS_variable_value_row::set_field(Field *f)
+{
+ PFS_engine_table::set_field_varchar(f, m_charset, m_str, m_length);
+}
+
+void PFS_user_variable_value_row::clear()
+{
+ my_free(m_value);
+ m_value= NULL;
+ m_value_length= 0;
+}
+
+void PFS_user_variable_value_row::make_row(const char* val, size_t length)
+{
+ if (length > 0)
+ {
+ m_value= (char*) my_malloc(PSI_NOT_INSTRUMENTED, length, MYF(0));
+ m_value_length= length;
+ memcpy(m_value, val, length);
+ }
+ else
+ {
+ m_value= NULL;
+ m_value_length= 0;
}
}
diff --git a/storage/perfschema/table_helper.h b/storage/perfschema/table_helper.h
index 62f94826754..bf431802900 100644
--- a/storage/perfschema/table_helper.h
+++ b/storage/perfschema/table_helper.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2016, 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, version 2.0,
@@ -31,7 +31,7 @@
#include "pfs_digest.h"
/*
- Write MD5 hash value in a string to be used
+ Write MD5 hash value in a string to be used
as DIGEST for the statement.
*/
#define MD5_HASH_TO_STRING(_hash, _str) \
@@ -47,6 +47,10 @@
struct PFS_host;
struct PFS_user;
struct PFS_account;
+struct PFS_object_name;
+struct PFS_program;
+class System_variable;
+class Status_variable;
/**
@file storage/perfschema/table_helper.h
@@ -69,7 +73,8 @@ struct PFS_instrument_view_constants
static const uint VIEW_TABLE= 5;
static const uint VIEW_SOCKET= 6;
static const uint VIEW_IDLE= 7;
- static const uint LAST_VIEW= 7;
+ static const uint VIEW_METADATA= 8;
+ static const uint LAST_VIEW= 8;
};
/** Namespace, internal views used within object summaries. */
@@ -77,12 +82,8 @@ struct PFS_object_view_constants
{
static const uint FIRST_VIEW= 1;
static const uint VIEW_TABLE= 1;
- static const uint LAST_VIEW= 1;
-
- /* Future use */
- static const uint VIEW_EVENT= 2;
- static const uint VIEW_PROCEDURE= 3;
- static const uint VIEW_FUNCTION= 4;
+ static const uint VIEW_PROGRAM= 2;
+ static const uint LAST_VIEW= 2;
};
/** Row fragment for column HOST. */
@@ -189,8 +190,11 @@ struct PFS_object_row
/** Build a row from a memory buffer. */
int make_row(PFS_table_share *pfs);
+ int make_row(PFS_program *pfs);
+ int make_row(const MDL_key *pfs);
/** Set a table field from the row. */
void set_field(uint index, Field *f);
+ void set_nullable_field(uint index, Field *f);
};
/** Row fragment for columns OBJECT_TYPE, SCHEMA_NAME, OBJECT_NAME, INDEX_NAME. */
@@ -203,7 +207,8 @@ struct PFS_index_row
uint m_index_name_length;
/** Build a row from a memory buffer. */
- int make_row(PFS_table_share *pfs, uint table_index);
+ int make_row(PFS_table_share *pfs, PFS_table_share_index *pfs_index,
+ uint table_index);
/** Set a table field from the row. */
void set_field(uint index, Field *f);
};
@@ -222,6 +227,15 @@ struct PFS_stat_row
/** Column MAX_TIMER_WAIT. */
ulonglong m_max;
+ inline void reset()
+ {
+ m_count= 0;
+ m_sum= 0;
+ m_min= 0;
+ m_avg= 0;
+ m_max= 0;
+ }
+
/** Build a row with timer fields from a memory buffer. */
inline void set(time_normalizer *normalizer, const PFS_single_stat *stat)
{
@@ -335,7 +349,6 @@ struct PFS_table_lock_stat_row
PFS_stat_row m_read_external;
PFS_stat_row m_write_allow_write;
PFS_stat_row m_write_concurrent_insert;
- PFS_stat_row m_write_delayed;
PFS_stat_row m_write_low_priority;
PFS_stat_row m_write_normal;
PFS_stat_row m_write_external;
@@ -361,14 +374,12 @@ struct PFS_table_lock_stat_row
m_write_allow_write.set(normalizer, & stat->m_stat[PFS_TL_WRITE_ALLOW_WRITE]);
m_write_concurrent_insert.set(normalizer, & stat->m_stat[PFS_TL_WRITE_CONCURRENT_INSERT]);
- m_write_delayed.set(normalizer, & stat->m_stat[PFS_TL_WRITE_DELAYED]);
m_write_low_priority.set(normalizer, & stat->m_stat[PFS_TL_WRITE_LOW_PRIORITY]);
m_write_normal.set(normalizer, & stat->m_stat[PFS_TL_WRITE]);
m_write_external.set(normalizer, & stat->m_stat[PFS_TL_WRITE_EXTERNAL]);
all_write.aggregate(& stat->m_stat[PFS_TL_WRITE_ALLOW_WRITE]);
all_write.aggregate(& stat->m_stat[PFS_TL_WRITE_CONCURRENT_INSERT]);
- all_write.aggregate(& stat->m_stat[PFS_TL_WRITE_DELAYED]);
all_write.aggregate(& stat->m_stat[PFS_TL_WRITE_LOW_PRIORITY]);
all_write.aggregate(& stat->m_stat[PFS_TL_WRITE]);
all_write.aggregate(& stat->m_stat[PFS_TL_WRITE_EXTERNAL]);
@@ -427,33 +438,106 @@ struct PFS_statement_stat_row
/** Build a row from a memory buffer. */
inline void set(time_normalizer *normalizer, const PFS_statement_stat *stat)
{
+ if (stat->m_timer1_stat.m_count != 0)
+ {
+ m_timer1_row.set(normalizer, & stat->m_timer1_stat);
+
+ m_error_count= stat->m_error_count;
+ m_warning_count= stat->m_warning_count;
+ m_lock_time= stat->m_lock_time * MICROSEC_TO_PICOSEC;
+ m_rows_affected= stat->m_rows_affected;
+ m_rows_sent= stat->m_rows_sent;
+ m_rows_examined= stat->m_rows_examined;
+ m_created_tmp_disk_tables= stat->m_created_tmp_disk_tables;
+ m_created_tmp_tables= stat->m_created_tmp_tables;
+ m_select_full_join= stat->m_select_full_join;
+ m_select_full_range_join= stat->m_select_full_range_join;
+ m_select_range= stat->m_select_range;
+ m_select_range_check= stat->m_select_range_check;
+ m_select_scan= stat->m_select_scan;
+ m_sort_merge_passes= stat->m_sort_merge_passes;
+ m_sort_range= stat->m_sort_range;
+ m_sort_rows= stat->m_sort_rows;
+ m_sort_scan= stat->m_sort_scan;
+ m_no_index_used= stat->m_no_index_used;
+ m_no_good_index_used= stat->m_no_good_index_used;
+ }
+ else
+ {
+ m_timer1_row.reset();
+
+ m_error_count= 0;
+ m_warning_count= 0;
+ m_lock_time= 0;
+ m_rows_affected= 0;
+ m_rows_sent= 0;
+ m_rows_examined= 0;
+ m_created_tmp_disk_tables= 0;
+ m_created_tmp_tables= 0;
+ m_select_full_join= 0;
+ m_select_full_range_join= 0;
+ m_select_range= 0;
+ m_select_range_check= 0;
+ m_select_scan= 0;
+ m_sort_merge_passes= 0;
+ m_sort_range= 0;
+ m_sort_rows= 0;
+ m_sort_scan= 0;
+ m_no_index_used= 0;
+ m_no_good_index_used= 0;
+ }
+ }
+
+ /** Set a table field from the row. */
+ void set_field(uint index, Field *f);
+};
+
+/** Row fragment for stored program statistics. */
+struct PFS_sp_stat_row
+{
+ PFS_stat_row m_timer1_row;
+
+ /** Build a row from a memory buffer. */
+ inline void set(time_normalizer *normalizer, const PFS_sp_stat *stat)
+ {
m_timer1_row.set(normalizer, & stat->m_timer1_stat);
+ }
- m_error_count= stat->m_error_count;
- m_warning_count= stat->m_warning_count;
- m_lock_time= stat->m_lock_time * MICROSEC_TO_PICOSEC;
- m_rows_affected= stat->m_rows_affected;
- m_rows_sent= stat->m_rows_sent;
- m_rows_examined= stat->m_rows_examined;
- m_created_tmp_disk_tables= stat->m_created_tmp_disk_tables;
- m_created_tmp_tables= stat->m_created_tmp_tables;
- m_select_full_join= stat->m_select_full_join;
- m_select_full_range_join= stat->m_select_full_range_join;
- m_select_range= stat->m_select_range;
- m_select_range_check= stat->m_select_range_check;
- m_select_scan= stat->m_select_scan;
- m_sort_merge_passes= stat->m_sort_merge_passes;
- m_sort_range= stat->m_sort_range;
- m_sort_rows= stat->m_sort_rows;
- m_sort_scan= stat->m_sort_scan;
- m_no_index_used= stat->m_no_index_used;
- m_no_good_index_used= stat->m_no_good_index_used;
+ /** Set a table field from the row. */
+ inline void set_field(uint index, Field *f)
+ {
+ m_timer1_row.set_field(index, f);
+ }
+};
+
+/** Row fragment for transaction statistics columns. */
+struct PFS_transaction_stat_row
+{
+ PFS_stat_row m_timer1_row;
+ PFS_stat_row m_read_write_row;
+ PFS_stat_row m_read_only_row;
+ ulonglong m_savepoint_count;
+ ulonglong m_rollback_to_savepoint_count;
+ ulonglong m_release_savepoint_count;
+
+ /** Build a row from a memory buffer. */
+ inline void set(time_normalizer *normalizer, const PFS_transaction_stat *stat)
+ {
+ /* Combine read write/read only stats */
+ PFS_single_stat all;
+ all.aggregate(&stat->m_read_only_stat);
+ all.aggregate(&stat->m_read_write_stat);
+
+ m_timer1_row.set(normalizer, &all);
+ m_read_write_row.set(normalizer, &stat->m_read_write_stat);
+ m_read_only_row.set(normalizer, &stat->m_read_only_stat);
}
/** Set a table field from the row. */
void set_field(uint index, Field *f);
};
+/** Row fragment for connection statistics. */
struct PFS_connection_stat_row
{
ulonglong m_current_connections;
@@ -470,6 +554,12 @@ struct PFS_connection_stat_row
};
void set_field_object_type(Field *f, enum_object_type object_type);
+void set_field_lock_type(Field *f, PFS_TL_LOCK_TYPE lock_type);
+void set_field_mdl_type(Field *f, opaque_mdl_type mdl_type);
+void set_field_mdl_duration(Field *f, opaque_mdl_duration mdl_duration);
+void set_field_mdl_status(Field *f, opaque_mdl_status mdl_status);
+void set_field_isolation_level(Field *f, enum_isolation_level iso_level);
+void set_field_xa_state(Field *f, enum_xa_transaction_state xa_state);
/** Row fragment for socket io statistics columns. */
struct PFS_socket_io_stat_row
@@ -478,7 +568,7 @@ struct PFS_socket_io_stat_row
PFS_byte_stat_row m_write;
PFS_byte_stat_row m_misc;
PFS_byte_stat_row m_all;
-
+
inline void set(time_normalizer *normalizer, const PFS_socket_io_stat *stat)
{
PFS_byte_stat all;
@@ -486,7 +576,7 @@ struct PFS_socket_io_stat_row
m_read.set(normalizer, &stat->m_read);
m_write.set(normalizer, &stat->m_write);
m_misc.set(normalizer, &stat->m_misc);
-
+
/* Combine stats for all operations */
all.aggregate(&stat->m_read);
all.aggregate(&stat->m_write);
@@ -503,7 +593,7 @@ struct PFS_file_io_stat_row
PFS_byte_stat_row m_write;
PFS_byte_stat_row m_misc;
PFS_byte_stat_row m_all;
-
+
inline void set(time_normalizer *normalizer, const PFS_file_io_stat *stat)
{
PFS_byte_stat all;
@@ -511,7 +601,7 @@ struct PFS_file_io_stat_row
m_read.set(normalizer, &stat->m_read);
m_write.set(normalizer, &stat->m_write);
m_misc.set(normalizer, &stat->m_misc);
-
+
/* Combine stats for all operations */
all.aggregate(&stat->m_read);
all.aggregate(&stat->m_write);
@@ -521,6 +611,88 @@ struct PFS_file_io_stat_row
}
};
+/** Row fragment for memory statistics columns. */
+struct PFS_memory_stat_row
+{
+ PFS_memory_stat m_stat;
+
+ /** Build a row from a memory buffer. */
+ inline void set(const PFS_memory_stat *stat)
+ {
+ m_stat= *stat;
+ }
+
+ /** Set a table field from the row. */
+ void set_field(uint index, Field *f);
+};
+
+struct PFS_variable_name_row
+{
+public:
+ PFS_variable_name_row()
+ {
+ m_str[0]= '\0';
+ m_length= 0;
+ }
+
+ void make_row(const char* str, size_t length);
+
+ char m_str[NAME_CHAR_LEN+1];
+ uint m_length;
+};
+
+struct PFS_variable_value_row
+{
+public:
+ /** Set the row from a status variable. */
+ void make_row(const Status_variable *var);
+
+ /** Set the row from a system variable. */
+ void make_row(const System_variable *var);
+
+ /** Set a table field from the row. */
+ void set_field(Field *f);
+
+private:
+ void make_row(const CHARSET_INFO *cs, const char* str, size_t length);
+
+ char m_str[1024];
+ uint m_length;
+ const CHARSET_INFO *m_charset;
+};
+
+struct PFS_user_variable_value_row
+{
+public:
+ PFS_user_variable_value_row()
+ : m_value(NULL), m_value_length(0)
+ {}
+
+ PFS_user_variable_value_row(const PFS_user_variable_value_row& rhs)
+ {
+ make_row(rhs.m_value, rhs.m_value_length);
+ }
+
+ ~PFS_user_variable_value_row()
+ {
+ clear();
+ }
+
+ void make_row(const char* val, size_t length);
+
+ const char *get_value() const
+ { return m_value; }
+
+ size_t get_value_length() const
+ { return m_value_length; }
+
+ void clear();
+
+private:
+ char *m_value;
+ size_t m_value_length;
+};
+
/** @} */
#endif
diff --git a/storage/perfschema/table_host_cache.cc b/storage/perfschema/table_host_cache.cc
index 501894df9b1..e482ead215c 100644
--- a/storage/perfschema/table_host_cache.cc
+++ b/storage/perfschema/table_host_cache.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, 2015, 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, version 2.0,
@@ -26,9 +26,11 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "table_host_cache.h"
#include "hostname.h"
+#include "field.h"
+#include "sql_class.h"
THR_LOCK table_host_cache::m_table_lock;
@@ -37,11 +39,10 @@ table_host_cache::m_share=
{
{ C_STRING_WITH_LEN("host_cache") },
&pfs_truncatable_acl,
- &table_host_cache::create,
+ table_host_cache::create,
NULL, /* write_row */
table_host_cache::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ table_host_cache::get_row_count,
sizeof(PFS_simple_index), /* ref length */
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE host_cache("
@@ -73,7 +74,8 @@ table_host_cache::m_share=
"FIRST_SEEN TIMESTAMP(0) NOT NULL default 0,"
"LAST_SEEN TIMESTAMP(0) NOT NULL default 0,"
"FIRST_ERROR_SEEN TIMESTAMP(0) null default 0,"
- "LAST_ERROR_SEEN TIMESTAMP(0) null default 0)") }
+ "LAST_ERROR_SEEN TIMESTAMP(0) null default 0)") },
+ false /* perpetual */
};
PFS_engine_table* table_host_cache::create(void)
@@ -100,6 +102,16 @@ table_host_cache::delete_all_rows(void)
return 0;
}
+ha_rows
+table_host_cache::get_row_count(void)
+{
+ ha_rows count;
+ hostname_cache_lock();
+ count= hostname_cache_size();
+ hostname_cache_unlock();
+ return count;
+}
+
table_host_cache::table_host_cache()
: PFS_engine_table(&m_share, &m_pos),
m_all_rows(NULL), m_row_count(0),
diff --git a/storage/perfschema/table_host_cache.h b/storage/perfschema/table_host_cache.h
index 8add0b5049c..57cd0fa02ad 100644
--- a/storage/perfschema/table_host_cache.h
+++ b/storage/perfschema/table_host_cache.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, 2015, 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, version 2.0,
@@ -111,6 +111,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_next();
virtual int rnd_pos(const void *pos);
diff --git a/storage/perfschema/table_hosts.cc b/storage/perfschema/table_hosts.cc
index 8bc5310817c..8d8b6201ec8 100644
--- a/storage/perfschema/table_hosts.cc
+++ b/storage/perfschema/table_hosts.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, 2015, 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, version 2.0,
@@ -21,13 +21,16 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "table_hosts.h"
#include "pfs_instr_class.h"
#include "pfs_instr.h"
#include "pfs_account.h"
#include "pfs_host.h"
#include "pfs_visitor.h"
+#include "pfs_memory.h"
+#include "pfs_status.h"
+#include "field.h"
THR_LOCK table_hosts::m_table_lock;
@@ -36,17 +39,17 @@ table_hosts::m_share=
{
{ C_STRING_WITH_LEN("hosts") },
&pfs_truncatable_acl,
- &table_hosts::create,
+ table_hosts::create,
NULL, /* write_row */
table_hosts::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ cursor_by_host::get_row_count,
sizeof(PFS_simple_index), /* ref length */
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE hosts("
"HOST CHAR(60) collate utf8_bin default null,"
"CURRENT_CONNECTIONS bigint not null,"
- "TOTAL_CONNECTIONS bigint not null)") }
+ "TOTAL_CONNECTIONS bigint not null)") },
+ false /* perpetual */
};
PFS_engine_table* table_hosts::create()
@@ -66,6 +69,15 @@ table_hosts::delete_all_rows(void)
reset_events_statements_by_thread();
reset_events_statements_by_account();
reset_events_statements_by_host();
+ reset_events_transactions_by_thread();
+ reset_events_transactions_by_account();
+ reset_events_transactions_by_host();
+ reset_memory_by_thread();
+ reset_memory_by_account();
+ reset_memory_by_host();
+ reset_status_by_thread();
+ reset_status_by_account();
+ reset_status_by_host();
purge_all_account();
purge_all_host();
return 0;
@@ -78,7 +90,7 @@ table_hosts::table_hosts()
void table_hosts::make_row(PFS_host *pfs)
{
- pfs_lock lock;
+ pfs_optimistic_state lock;
m_row_exists= false;
pfs->m_lock.begin_optimistic_lock(&lock);
@@ -87,7 +99,11 @@ void table_hosts::make_row(PFS_host *pfs)
return;
PFS_connection_stat_visitor visitor;
- PFS_connection_iterator::visit_host(pfs, true, true, & visitor);
+ PFS_connection_iterator::visit_host(pfs,
+ true, /* accounts */
+ true, /* threads */
+ false, /* THDs */
+ & visitor);
if (! pfs->m_lock.end_optimistic_lock(& lock))
return;
diff --git a/storage/perfschema/table_hosts.h b/storage/perfschema/table_hosts.h
index 422b6449b25..61c04d12179 100644
--- a/storage/perfschema/table_hosts.h
+++ b/storage/perfschema/table_hosts.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, 2015, 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, version 2.0,
diff --git a/storage/perfschema/table_md_locks.cc b/storage/perfschema/table_md_locks.cc
new file mode 100644
index 00000000000..1f771e105d6
--- /dev/null
+++ b/storage/perfschema/table_md_locks.cc
@@ -0,0 +1,207 @@
+/* Copyright (c) 2012, 2018, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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/table_md_locks.cc
+ Table METADATA_LOCKS (implementation).
+*/
+
+#include "my_global.h"
+#include "my_thread.h"
+#include "pfs_instr.h"
+#include "pfs_column_types.h"
+#include "pfs_column_values.h"
+#include "table_md_locks.h"
+#include "pfs_global.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
+
+THR_LOCK table_metadata_locks::m_table_lock;
+
+PFS_engine_table_share
+table_metadata_locks::m_share=
+{
+ { C_STRING_WITH_LEN("metadata_locks") },
+ &pfs_readonly_acl,
+ table_metadata_locks::create,
+ NULL, /* write_row */
+ NULL, /* delete_all_rows */
+ table_metadata_locks::get_row_count,
+ sizeof(PFS_simple_index),
+ &m_table_lock,
+ { C_STRING_WITH_LEN("CREATE TABLE metadata_locks("
+ "OBJECT_TYPE VARCHAR(64) not null,"
+ "OBJECT_SCHEMA VARCHAR(64),"
+ "OBJECT_NAME VARCHAR(64),"
+ "OBJECT_INSTANCE_BEGIN BIGINT unsigned not null,"
+ "LOCK_TYPE VARCHAR(32) not null,"
+ "LOCK_DURATION VARCHAR(32) not null,"
+ "LOCK_STATUS VARCHAR(32) not null,"
+ "SOURCE VARCHAR(64),"
+ "OWNER_THREAD_ID BIGINT unsigned,"
+ "OWNER_EVENT_ID BIGINT unsigned)")},
+ false /* perpetual */
+};
+
+PFS_engine_table* table_metadata_locks::create(void)
+{
+ return new table_metadata_locks();
+}
+
+ha_rows
+table_metadata_locks::get_row_count(void)
+{
+ return global_mdl_container.get_row_count();
+}
+
+table_metadata_locks::table_metadata_locks()
+ : PFS_engine_table(&m_share, &m_pos),
+ m_row_exists(false), m_pos(0), m_next_pos(0)
+{}
+
+void table_metadata_locks::reset_position(void)
+{
+ m_pos.m_index= 0;
+ m_next_pos.m_index= 0;
+}
+
+int table_metadata_locks::rnd_next(void)
+{
+ PFS_metadata_lock *pfs;
+
+ m_pos.set_at(&m_next_pos);
+ PFS_mdl_iterator it= global_mdl_container.iterate(m_pos.m_index);
+ pfs= it.scan_next(& m_pos.m_index);
+ if (pfs != NULL)
+ {
+ make_row(pfs);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+
+ return HA_ERR_END_OF_FILE;
+}
+
+int table_metadata_locks::rnd_pos(const void *pos)
+{
+ PFS_metadata_lock *pfs;
+
+ set_position(pos);
+
+ pfs= global_mdl_container.get(m_pos.m_index);
+ if (pfs != NULL)
+ {
+ make_row(pfs);
+ return 0;
+ }
+
+ return HA_ERR_RECORD_DELETED;
+}
+
+void table_metadata_locks::make_row(PFS_metadata_lock *pfs)
+{
+ pfs_optimistic_state lock;
+
+ m_row_exists= false;
+
+ /* Protect this reader against a metadata lock destroy */
+ pfs->m_lock.begin_optimistic_lock(&lock);
+
+ m_row.m_identity= pfs->m_identity;
+ m_row.m_mdl_type= pfs->m_mdl_type;
+ m_row.m_mdl_duration= pfs->m_mdl_duration;
+ m_row.m_mdl_status= pfs->m_mdl_status;
+
+ /* Disable source file and line to avoid stale __FILE__ pointers. */
+ m_row.m_source_length= 0;
+
+ m_row.m_owner_thread_id= static_cast<ulong>(pfs->m_owner_thread_id);
+ m_row.m_owner_event_id= static_cast<ulong>(pfs->m_owner_event_id);
+
+ if (m_row.m_object.make_row(& pfs->m_mdl_key))
+ return;
+
+ if (pfs->m_lock.end_optimistic_lock(&lock))
+ m_row_exists= true;
+}
+
+int table_metadata_locks::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 0: /* OBJECT_TYPE */
+ case 1: /* OBJECT_SCHEMA */
+ case 2: /* OBJECT_NAME */
+ m_row.m_object.set_nullable_field(f->field_index, f);
+ break;
+ case 3: /* OBJECT_INSTANCE */
+ set_field_ulonglong(f, (intptr) m_row.m_identity);
+ break;
+ case 4: /* LOCK_TYPE */
+ set_field_mdl_type(f, m_row.m_mdl_type);
+ break;
+ case 5: /* LOCK_DURATION */
+ set_field_mdl_duration(f, m_row.m_mdl_duration);
+ break;
+ case 6: /* LOCK_STATUS */
+ set_field_mdl_status(f, m_row.m_mdl_status);
+ break;
+ case 7: /* SOURCE */
+ set_field_varchar_utf8(f, m_row.m_source, m_row.m_source_length);
+ break;
+ case 8: /* OWNER_THREAD_ID */
+ if (m_row.m_owner_thread_id != 0)
+ set_field_ulonglong(f, m_row.m_owner_thread_id);
+ else
+ f->set_null();
+ break;
+ case 9: /* OWNER_EVENT_ID */
+ if (m_row.m_owner_event_id != 0)
+ set_field_ulonglong(f, m_row.m_owner_event_id);
+ else
+ f->set_null();
+ break;
+ default:
+ DBUG_ASSERT(false);
+ }
+ }
+ }
+
+ return 0;
+}
+
diff --git a/storage/perfschema/table_md_locks.h b/storage/perfschema/table_md_locks.h
new file mode 100644
index 00000000000..40b6d2f6efb
--- /dev/null
+++ b/storage/perfschema/table_md_locks.h
@@ -0,0 +1,106 @@
+/* Copyright (c) 2012, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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_METADATA_LOCK_H
+#define TABLE_METADATA_LOCK_H
+
+/**
+ @file storage/perfschema/table_md_locks.h
+ Table METADATA_LOCKS (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "table_helper.h"
+
+struct PFS_metadata_lock;
+
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+/** A row of table PERFORMANCE_SCHEMA.MUTEX_INSTANCES. */
+struct row_metadata_lock
+{
+ /** Column OBJECT_INSTANCE_BEGIN. */
+ const void *m_identity;
+ opaque_mdl_type m_mdl_type;
+ opaque_mdl_duration m_mdl_duration;
+ opaque_mdl_status m_mdl_status;
+ /** Column SOURCE. */
+ char m_source[COL_SOURCE_SIZE];
+ /** Length in bytes of @c m_source. */
+ uint m_source_length;
+ /** Column OWNER_THREAD_ID. */
+ ulong m_owner_thread_id;
+ /** Column OWNER_EVENT_ID. */
+ ulong m_owner_event_id;
+ /** Columns OBJECT_TYPE, OBJECT_SCHEMA, OBJECT_NAME. */
+ PFS_object_row m_object;
+};
+
+/** Table PERFORMANCE_SCHEMA.METADATA_LOCKS. */
+class table_metadata_locks : public PFS_engine_table
+{
+public:
+ /** Table share. */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static ha_rows get_row_count();
+
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+private:
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+
+ table_metadata_locks();
+
+public:
+ ~table_metadata_locks()
+ {}
+
+private:
+ void make_row(PFS_metadata_lock *pfs);
+
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /** Fields definition. */
+ static TABLE_FIELD_DEF m_field_def;
+
+ /** Current row. */
+ row_metadata_lock m_row;
+ /** True if the current row exists. */
+ bool m_row_exists;
+ /** Current position. */
+ PFS_simple_index m_pos;
+ /** Next position. */
+ PFS_simple_index m_next_pos;
+};
+
+/** @} */
+#endif
diff --git a/storage/perfschema/table_mems_by_account_by_event_name.cc b/storage/perfschema/table_mems_by_account_by_event_name.cc
new file mode 100644
index 00000000000..5c83c225d11
--- /dev/null
+++ b/storage/perfschema/table_mems_by_account_by_event_name.cc
@@ -0,0 +1,221 @@
+/* Copyright (c) 2011, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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/table_mems_by_account_by_event_name.cc
+ Table MEMORY_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME (implementation).
+*/
+
+#include "my_global.h"
+#include "my_thread.h"
+#include "pfs_instr_class.h"
+#include "pfs_column_types.h"
+#include "pfs_column_values.h"
+#include "table_mems_by_account_by_event_name.h"
+#include "pfs_global.h"
+#include "pfs_visitor.h"
+#include "pfs_memory.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
+
+THR_LOCK table_mems_by_account_by_event_name::m_table_lock;
+
+PFS_engine_table_share
+table_mems_by_account_by_event_name::m_share=
+{
+ { C_STRING_WITH_LEN("memory_summary_by_account_by_event_name") },
+ &pfs_readonly_acl,
+ table_mems_by_account_by_event_name::create,
+ NULL, /* write_row */
+ table_mems_by_account_by_event_name::delete_all_rows,
+ table_mems_by_account_by_event_name::get_row_count,
+ sizeof(pos_mems_by_account_by_event_name),
+ &m_table_lock,
+ { C_STRING_WITH_LEN("CREATE TABLE memory_summary_by_account_by_event_name("
+ "USER CHAR(32) collate utf8_bin default null,"
+ "HOST CHAR(60) collate utf8_bin default null,"
+ "EVENT_NAME VARCHAR(128) not null,"
+ "COUNT_ALLOC BIGINT unsigned not null,"
+ "COUNT_FREE BIGINT unsigned not null,"
+ "SUM_NUMBER_OF_BYTES_ALLOC BIGINT unsigned not null,"
+ "SUM_NUMBER_OF_BYTES_FREE BIGINT unsigned not null,"
+ "LOW_COUNT_USED BIGINT not null,"
+ "CURRENT_COUNT_USED BIGINT not null,"
+ "HIGH_COUNT_USED BIGINT not null,"
+ "LOW_NUMBER_OF_BYTES_USED BIGINT not null,"
+ "CURRENT_NUMBER_OF_BYTES_USED BIGINT not null,"
+ "HIGH_NUMBER_OF_BYTES_USED BIGINT not null)")},
+ false /* perpetual */
+};
+
+PFS_engine_table* table_mems_by_account_by_event_name::create(void)
+{
+ return new table_mems_by_account_by_event_name();
+}
+
+int
+table_mems_by_account_by_event_name::delete_all_rows(void)
+{
+ reset_memory_by_thread();
+ reset_memory_by_account();
+ return 0;
+}
+
+ha_rows
+table_mems_by_account_by_event_name::get_row_count(void)
+{
+ return global_account_container.get_row_count() * memory_class_max;
+}
+
+table_mems_by_account_by_event_name::table_mems_by_account_by_event_name()
+ : PFS_engine_table(&m_share, &m_pos),
+ m_row_exists(false), m_pos(), m_next_pos()
+{}
+
+void table_mems_by_account_by_event_name::reset_position(void)
+{
+ m_pos.reset();
+ m_next_pos.reset();
+}
+
+int table_mems_by_account_by_event_name::rnd_next(void)
+{
+ PFS_account *account;
+ PFS_memory_class *memory_class;
+ bool has_more_account= true;
+
+ for (m_pos.set_at(&m_next_pos);
+ has_more_account;
+ m_pos.next_account())
+ {
+ account= global_account_container.get(m_pos.m_index_1, & has_more_account);
+ if (account != NULL)
+ {
+ do
+ {
+ memory_class= find_memory_class(m_pos.m_index_2);
+ if (memory_class != NULL)
+ {
+ if (! memory_class->is_global())
+ {
+ make_row(account, memory_class);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+
+ m_pos.next_class();
+ }
+ }
+ while (memory_class != NULL);
+ }
+ }
+
+ return HA_ERR_END_OF_FILE;
+}
+
+int table_mems_by_account_by_event_name::rnd_pos(const void *pos)
+{
+ PFS_account *account;
+ PFS_memory_class *memory_class;
+
+ set_position(pos);
+
+ account= global_account_container.get(m_pos.m_index_1);
+ if (account != NULL)
+ {
+ memory_class= find_memory_class(m_pos.m_index_2);
+ if (memory_class != NULL)
+ {
+ if (! memory_class->is_global())
+ {
+ make_row(account, memory_class);
+ return 0;
+ }
+ }
+ }
+
+ return HA_ERR_RECORD_DELETED;
+}
+
+void table_mems_by_account_by_event_name
+::make_row(PFS_account *account, PFS_memory_class *klass)
+{
+ pfs_optimistic_state lock;
+ m_row_exists= false;
+
+ account->m_lock.begin_optimistic_lock(&lock);
+
+ if (m_row.m_account.make_row(account))
+ return;
+
+ m_row.m_event_name.make_row(klass);
+
+ PFS_connection_memory_visitor visitor(klass);
+ PFS_connection_iterator::visit_account(account,
+ true, /* threads */
+ false, /* THDs */
+ & visitor);
+
+ if (! account->m_lock.end_optimistic_lock(&lock))
+ return;
+
+ m_row_exists= true;
+ m_row.m_stat.set(& visitor.m_stat);
+}
+
+int table_mems_by_account_by_event_name::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 0: /* USER */
+ case 1: /* HOST */
+ m_row.m_account.set_field(f->field_index, f);
+ break;
+ case 2: /* EVENT_NAME */
+ m_row.m_event_name.set_field(f);
+ break;
+ default: /* 3, ... HIGH_NUMBER_OF_BYTES_USED */
+ m_row.m_stat.set_field(f->field_index - 3, f);
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
diff --git a/storage/perfschema/table_mems_by_account_by_event_name.h b/storage/perfschema/table_mems_by_account_by_event_name.h
new file mode 100644
index 00000000000..b6151246f34
--- /dev/null
+++ b/storage/perfschema/table_mems_by_account_by_event_name.h
@@ -0,0 +1,129 @@
+/* Copyright (c) 2011, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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_MEMORY_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME_H
+#define TABLE_MEMORY_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME_H
+
+/**
+ @file storage/perfschema/table_mems_by_account_by_event_name.h
+ Table MEMORY_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "pfs_instr_class.h"
+#include "pfs_account.h"
+#include "table_helper.h"
+
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+/** A row of PERFORMANCE_SCHEMA.MEMORY_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME. */
+struct row_mems_by_account_by_event_name
+{
+ /** Column USER, HOST. */
+ PFS_account_row m_account;
+ /** Column EVENT_NAME. */
+ PFS_event_name_row m_event_name;
+ /** Columns COUNT_ALLOC, ... */
+ PFS_memory_stat_row m_stat;
+};
+
+/**
+ Position of a cursor on
+ PERFORMANCE_SCHEMA.EVENTS_MEMORY_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME.
+ Index 1 on account (0 based)
+ Index 2 on memory class (1 based)
+*/
+struct pos_mems_by_account_by_event_name
+: public PFS_double_index
+{
+ pos_mems_by_account_by_event_name()
+ : PFS_double_index(0, 1)
+ {}
+
+ inline void reset(void)
+ {
+ m_index_1= 0;
+ m_index_2= 1;
+ }
+
+ inline void next_account(void)
+ {
+ m_index_1++;
+ m_index_2= 1;
+ }
+
+ inline void next_class(void)
+ {
+ m_index_2++;
+ }
+};
+
+/** Table PERFORMANCE_SCHEMA.MEMORY_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME. */
+class table_mems_by_account_by_event_name : public PFS_engine_table
+{
+public:
+ /** Table share */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static int delete_all_rows();
+ static ha_rows get_row_count();
+
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+private:
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+
+ table_mems_by_account_by_event_name();
+
+public:
+ ~table_mems_by_account_by_event_name()
+ {}
+
+private:
+ void make_row(PFS_account *account, PFS_memory_class *klass);
+
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /** Fields definition. */
+ static TABLE_FIELD_DEF m_field_def;
+
+ /** Current row. */
+ row_mems_by_account_by_event_name m_row;
+ /** True is the current row exists. */
+ bool m_row_exists;
+ /** Current position. */
+ pos_mems_by_account_by_event_name m_pos;
+ /** Next position. */
+ pos_mems_by_account_by_event_name m_next_pos;
+};
+
+/** @} */
+#endif
diff --git a/storage/perfschema/table_mems_by_host_by_event_name.cc b/storage/perfschema/table_mems_by_host_by_event_name.cc
new file mode 100644
index 00000000000..0921dfa49c8
--- /dev/null
+++ b/storage/perfschema/table_mems_by_host_by_event_name.cc
@@ -0,0 +1,221 @@
+/* Copyright (c) 2011, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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/table_mems_by_host_by_event_name.cc
+ Table MEMORY_SUMMARY_BY_HOST_BY_EVENT_NAME (implementation).
+*/
+
+#include "my_global.h"
+#include "my_thread.h"
+#include "pfs_instr_class.h"
+#include "pfs_column_types.h"
+#include "pfs_column_values.h"
+#include "table_mems_by_host_by_event_name.h"
+#include "pfs_global.h"
+#include "pfs_visitor.h"
+#include "pfs_memory.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
+
+THR_LOCK table_mems_by_host_by_event_name::m_table_lock;
+
+PFS_engine_table_share
+table_mems_by_host_by_event_name::m_share=
+{
+ { C_STRING_WITH_LEN("memory_summary_by_host_by_event_name") },
+ &pfs_readonly_acl,
+ table_mems_by_host_by_event_name::create,
+ NULL, /* write_row */
+ table_mems_by_host_by_event_name::delete_all_rows,
+ table_mems_by_host_by_event_name::get_row_count,
+ sizeof(PFS_simple_index),
+ &m_table_lock,
+ { C_STRING_WITH_LEN("CREATE TABLE memory_summary_by_host_by_event_name("
+ "HOST CHAR(60) collate utf8_bin default null,"
+ "EVENT_NAME VARCHAR(128) not null,"
+ "COUNT_ALLOC BIGINT unsigned not null,"
+ "COUNT_FREE BIGINT unsigned not null,"
+ "SUM_NUMBER_OF_BYTES_ALLOC BIGINT unsigned not null,"
+ "SUM_NUMBER_OF_BYTES_FREE BIGINT unsigned not null,"
+ "LOW_COUNT_USED BIGINT not null,"
+ "CURRENT_COUNT_USED BIGINT not null,"
+ "HIGH_COUNT_USED BIGINT not null,"
+ "LOW_NUMBER_OF_BYTES_USED BIGINT not null,"
+ "CURRENT_NUMBER_OF_BYTES_USED BIGINT not null,"
+ "HIGH_NUMBER_OF_BYTES_USED BIGINT not null)")},
+ false /* perpetual */
+};
+
+PFS_engine_table* table_mems_by_host_by_event_name::create(void)
+{
+ return new table_mems_by_host_by_event_name();
+}
+
+int
+table_mems_by_host_by_event_name::delete_all_rows(void)
+{
+ reset_memory_by_thread();
+ reset_memory_by_account();
+ reset_memory_by_host();
+ return 0;
+}
+
+ha_rows
+table_mems_by_host_by_event_name::get_row_count(void)
+{
+ return global_host_container.get_row_count() * memory_class_max;
+}
+
+table_mems_by_host_by_event_name::table_mems_by_host_by_event_name()
+ : PFS_engine_table(&m_share, &m_pos),
+ m_row_exists(false), m_pos(), m_next_pos()
+{}
+
+void table_mems_by_host_by_event_name::reset_position(void)
+{
+ m_pos.reset();
+ m_next_pos.reset();
+}
+
+int table_mems_by_host_by_event_name::rnd_next(void)
+{
+ PFS_host *host;
+ PFS_memory_class *memory_class;
+ bool has_more_host= true;
+
+ for (m_pos.set_at(&m_next_pos);
+ has_more_host;
+ m_pos.next_host())
+ {
+ host= global_host_container.get(m_pos.m_index_1, & has_more_host);
+ if (host != NULL)
+ {
+ do
+ {
+ memory_class= find_memory_class(m_pos.m_index_2);
+ if (memory_class != NULL)
+ {
+ if (! memory_class->is_global())
+ {
+ make_row(host, memory_class);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+
+ m_pos.next_class();
+ }
+ }
+ while (memory_class != NULL);
+ }
+ }
+
+ return HA_ERR_END_OF_FILE;
+}
+
+int table_mems_by_host_by_event_name::rnd_pos(const void *pos)
+{
+ PFS_host *host;
+ PFS_memory_class *memory_class;
+
+ set_position(pos);
+
+ host= global_host_container.get(m_pos.m_index_1);
+ if (host != NULL)
+ {
+ memory_class= find_memory_class(m_pos.m_index_2);
+ if (memory_class != NULL)
+ {
+ if (! memory_class->is_global())
+ {
+ make_row(host, memory_class);
+ return 0;
+ }
+ }
+ }
+
+ return HA_ERR_RECORD_DELETED;
+}
+
+void table_mems_by_host_by_event_name
+::make_row(PFS_host *host, PFS_memory_class *klass)
+{
+ pfs_optimistic_state lock;
+ m_row_exists= false;
+
+ host->m_lock.begin_optimistic_lock(&lock);
+
+ if (m_row.m_host.make_row(host))
+ return;
+
+ m_row.m_event_name.make_row(klass);
+
+ PFS_connection_memory_visitor visitor(klass);
+ PFS_connection_iterator::visit_host(host,
+ true, /* accounts */
+ true, /* threads */
+ false, /* THDs */
+ & visitor);
+
+ if (! host->m_lock.end_optimistic_lock(&lock))
+ return;
+
+ m_row_exists= true;
+ m_row.m_stat.set(& visitor.m_stat);
+}
+
+int table_mems_by_host_by_event_name::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 0: /* HOST */
+ m_row.m_host.set_field(f);
+ break;
+ case 1: /* EVENT_NAME */
+ m_row.m_event_name.set_field(f);
+ break;
+ default: /* 2, ... HIGH_NUMBER_OF_BYTES_USED */
+ m_row.m_stat.set_field(f->field_index - 2, f);
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
diff --git a/storage/perfschema/table_mems_by_host_by_event_name.h b/storage/perfschema/table_mems_by_host_by_event_name.h
new file mode 100644
index 00000000000..1a55db2c9b3
--- /dev/null
+++ b/storage/perfschema/table_mems_by_host_by_event_name.h
@@ -0,0 +1,129 @@
+/* Copyright (c) 2011, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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_MEMORY_SUMMARY_BY_HOST_BY_EVENT_NAME_H
+#define TABLE_MEMORY_SUMMARY_BY_HOST_BY_EVENT_NAME_H
+
+/**
+ @file storage/perfschema/table_mems_by_host_by_event_name.h
+ Table MEMORY_SUMMARY_BY_HOST_BY_EVENT_NAME (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "pfs_instr_class.h"
+#include "pfs_host.h"
+#include "table_helper.h"
+
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+/** A row of PERFORMANCE_SCHEMA.MEMORY_SUMMARY_BY_HOST_BY_EVENT_NAME. */
+struct row_mems_by_host_by_event_name
+{
+ /** Column HOST */
+ PFS_host_row m_host;
+ /** Column EVENT_NAME. */
+ PFS_event_name_row m_event_name;
+ /** Columns COUNT_ALLOC, ... */
+ PFS_memory_stat_row m_stat;
+};
+
+/**
+ Position of a cursor on
+ PERFORMANCE_SCHEMA.EVENTS_MEMORY_SUMMARY_BY_HOST_BY_EVENT_NAME.
+ Index 1 on host (0 based)
+ Index 2 on memory class (1 based)
+*/
+struct pos_mems_by_host_by_event_name
+: public PFS_double_index
+{
+ pos_mems_by_host_by_event_name()
+ : PFS_double_index(0, 1)
+ {}
+
+ inline void reset(void)
+ {
+ m_index_1= 0;
+ m_index_2= 1;
+ }
+
+ inline void next_host(void)
+ {
+ m_index_1++;
+ m_index_2= 1;
+ }
+
+ inline void next_class(void)
+ {
+ m_index_2++;
+ }
+};
+
+/** Table PERFORMANCE_SCHEMA.MEMORY_SUMMARY_BY_HOST_BY_EVENT_NAME. */
+class table_mems_by_host_by_event_name : public PFS_engine_table
+{
+public:
+ /** Table share */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static int delete_all_rows();
+ static ha_rows get_row_count();
+
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+private:
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+
+ table_mems_by_host_by_event_name();
+
+public:
+ ~table_mems_by_host_by_event_name()
+ {}
+
+private:
+ void make_row(PFS_host *host, PFS_memory_class *klass);
+
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /** Fields definition. */
+ static TABLE_FIELD_DEF m_field_def;
+
+ /** Current row. */
+ row_mems_by_host_by_event_name m_row;
+ /** True is the current row exists. */
+ bool m_row_exists;
+ /** Current position. */
+ pos_mems_by_host_by_event_name m_pos;
+ /** Next position. */
+ pos_mems_by_host_by_event_name m_next_pos;
+};
+
+/** @} */
+#endif
diff --git a/storage/perfschema/table_mems_by_thread_by_event_name.cc b/storage/perfschema/table_mems_by_thread_by_event_name.cc
new file mode 100644
index 00000000000..9e36cb76dd7
--- /dev/null
+++ b/storage/perfschema/table_mems_by_thread_by_event_name.cc
@@ -0,0 +1,214 @@
+/* Copyright (c) 2011, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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/table_mems_by_thread_by_event_name.cc
+ Table MEMORY_SUMMARY_BY_THREAD_BY_EVENT_NAME (implementation).
+*/
+
+#include "my_global.h"
+#include "my_thread.h"
+#include "pfs_instr_class.h"
+#include "pfs_column_types.h"
+#include "pfs_column_values.h"
+#include "table_mems_by_thread_by_event_name.h"
+#include "pfs_global.h"
+#include "pfs_visitor.h"
+#include "pfs_memory.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
+
+THR_LOCK table_mems_by_thread_by_event_name::m_table_lock;
+
+PFS_engine_table_share
+table_mems_by_thread_by_event_name::m_share=
+{
+ { C_STRING_WITH_LEN("memory_summary_by_thread_by_event_name") },
+ &pfs_readonly_acl,
+ table_mems_by_thread_by_event_name::create,
+ NULL, /* write_row */
+ table_mems_by_thread_by_event_name::delete_all_rows,
+ table_mems_by_thread_by_event_name::get_row_count,
+ sizeof(PFS_simple_index),
+ &m_table_lock,
+ { C_STRING_WITH_LEN("CREATE TABLE memory_summary_by_thread_by_event_name("
+ "THREAD_ID BIGINT unsigned not null,"
+ "EVENT_NAME VARCHAR(128) not null,"
+ "COUNT_ALLOC BIGINT unsigned not null,"
+ "COUNT_FREE BIGINT unsigned not null,"
+ "SUM_NUMBER_OF_BYTES_ALLOC BIGINT unsigned not null,"
+ "SUM_NUMBER_OF_BYTES_FREE BIGINT unsigned not null,"
+ "LOW_COUNT_USED BIGINT not null,"
+ "CURRENT_COUNT_USED BIGINT not null,"
+ "HIGH_COUNT_USED BIGINT not null,"
+ "LOW_NUMBER_OF_BYTES_USED BIGINT not null,"
+ "CURRENT_NUMBER_OF_BYTES_USED BIGINT not null,"
+ "HIGH_NUMBER_OF_BYTES_USED BIGINT not null)")},
+ false /* perpetual */
+};
+
+PFS_engine_table* table_mems_by_thread_by_event_name::create(void)
+{
+ return new table_mems_by_thread_by_event_name();
+}
+
+int
+table_mems_by_thread_by_event_name::delete_all_rows(void)
+{
+ reset_memory_by_thread();
+ return 0;
+}
+
+ha_rows
+table_mems_by_thread_by_event_name::get_row_count(void)
+{
+ return global_thread_container.get_row_count() * memory_class_max;
+}
+
+table_mems_by_thread_by_event_name::table_mems_by_thread_by_event_name()
+ : PFS_engine_table(&m_share, &m_pos),
+ m_row_exists(false), m_pos(), m_next_pos()
+{}
+
+void table_mems_by_thread_by_event_name::reset_position(void)
+{
+ m_pos.reset();
+ m_next_pos.reset();
+}
+
+int table_mems_by_thread_by_event_name::rnd_next(void)
+{
+ PFS_thread *thread;
+ PFS_memory_class *memory_class;
+ bool has_more_thread= true;
+
+ for (m_pos.set_at(&m_next_pos);
+ has_more_thread;
+ m_pos.next_thread())
+ {
+ thread= global_thread_container.get(m_pos.m_index_1, & has_more_thread);
+ if (thread != NULL)
+ {
+ do
+ {
+ memory_class= find_memory_class(m_pos.m_index_2);
+ if (memory_class != NULL)
+ {
+ if (! memory_class->is_global())
+ {
+ make_row(thread, memory_class);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+
+ m_pos.next_class();
+ }
+ }
+ while (memory_class != NULL);
+ }
+ }
+
+ return HA_ERR_END_OF_FILE;
+}
+
+int table_mems_by_thread_by_event_name::rnd_pos(const void *pos)
+{
+ PFS_thread *thread;
+ PFS_memory_class *memory_class;
+
+ set_position(pos);
+
+ thread= global_thread_container.get(m_pos.m_index_1);
+ if (thread != NULL)
+ {
+ memory_class= find_memory_class(m_pos.m_index_2);
+ if (memory_class != NULL)
+ {
+ if (! memory_class->is_global())
+ {
+ make_row(thread, memory_class);
+ return 0;
+ }
+ }
+ }
+
+ return HA_ERR_RECORD_DELETED;
+}
+
+void table_mems_by_thread_by_event_name
+::make_row(PFS_thread *thread, PFS_memory_class *klass)
+{
+ pfs_optimistic_state lock;
+ m_row_exists= false;
+
+ /* Protect this reader against a thread termination */
+ thread->m_lock.begin_optimistic_lock(&lock);
+
+ m_row.m_thread_internal_id= thread->m_thread_internal_id;
+
+ m_row.m_event_name.make_row(klass);
+
+ PFS_connection_memory_visitor visitor(klass);
+ PFS_connection_iterator::visit_thread(thread, & visitor);
+
+ if (! thread->m_lock.end_optimistic_lock(&lock))
+ return;
+
+ m_row_exists= true;
+ m_row.m_stat.set(& visitor.m_stat);
+}
+
+int table_mems_by_thread_by_event_name::read_row_values(TABLE *table,
+ unsigned char *,
+ 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 == 0);
+
+ for (; (f= *fields) ; fields++)
+ {
+ if (read_all || bitmap_is_set(table->read_set, f->field_index))
+ {
+ switch(f->field_index)
+ {
+ case 0: /* THREAD_ID */
+ set_field_ulonglong(f, m_row.m_thread_internal_id);
+ break;
+ case 1: /* EVENT_NAME */
+ m_row.m_event_name.set_field(f);
+ break;
+ default: /* 2, ... HIGH_NUMBER_OF_BYTES_USED */
+ m_row.m_stat.set_field(f->field_index - 2, f);
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
diff --git a/storage/perfschema/table_mems_by_thread_by_event_name.h b/storage/perfschema/table_mems_by_thread_by_event_name.h
new file mode 100644
index 00000000000..f8608198c2a
--- /dev/null
+++ b/storage/perfschema/table_mems_by_thread_by_event_name.h
@@ -0,0 +1,129 @@
+/* Copyright (c) 2011, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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_MEMORY_SUMMARY_BY_THREAD_BY_EVENT_NAME_H
+#define TABLE_MEMORY_SUMMARY_BY_THREAD_BY_EVENT_NAME_H
+
+/**
+ @file storage/perfschema/table_mems_by_thread_by_event_name.h
+ Table MEMORY_SUMMARY_BY_THREAD_BY_EVENT_NAME (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "pfs_instr_class.h"
+#include "pfs_instr.h"
+#include "table_helper.h"
+
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+/** A row of PERFORMANCE_SCHEMA.MEMORY_SUMMARY_BY_THREAD_BY_EVENT_NAME. */
+struct row_mems_by_thread_by_event_name
+{
+ /** Column THREAD_ID. */
+ ulonglong m_thread_internal_id;
+ /** Column EVENT_NAME. */
+ PFS_event_name_row m_event_name;
+ /** Columns COUNT_ALLOC, ... */
+ PFS_memory_stat_row m_stat;
+};
+
+/**
+ Position of a cursor on
+ PERFORMANCE_SCHEMA.EVENTS_MEMORY_SUMMARY_BY_THREAD_BY_EVENT_NAME.
+ Index 1 on thread (0 based).
+ Index 2 on memory class (1 based).
+*/
+struct pos_mems_by_thread_by_event_name
+: public PFS_double_index
+{
+ pos_mems_by_thread_by_event_name()
+ : PFS_double_index(0, 1)
+ {}
+
+ inline void reset(void)
+ {
+ m_index_1= 0;
+ m_index_2= 1;
+ }
+
+ inline void next_thread(void)
+ {
+ m_index_1++;
+ m_index_2= 1;
+ }
+
+ inline void next_class(void)
+ {
+ m_index_2++;
+ }
+};
+
+/** Table PERFORMANCE_SCHEMA.MEMORY_SUMMARY_BY_THREAD_BY_EVENT_NAME. */
+class table_mems_by_thread_by_event_name : public PFS_engine_table
+{
+public:
+ /** Table share */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static int delete_all_rows();
+ static ha_rows get_row_count();
+
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+private:
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+
+ table_mems_by_thread_by_event_name();
+
+public:
+ ~table_mems_by_thread_by_event_name()
+ {}
+
+private:
+ void make_row(PFS_thread *thread, PFS_memory_class *klass);
+
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /** Fields definition. */
+ static TABLE_FIELD_DEF m_field_def;
+
+ /** Current row. */
+ row_mems_by_thread_by_event_name m_row;
+ /** True is the current row exists. */
+ bool m_row_exists;
+ /** Current position. */
+ pos_mems_by_thread_by_event_name m_pos;
+ /** Next position. */
+ pos_mems_by_thread_by_event_name m_next_pos;
+};
+
+/** @} */
+#endif
diff --git a/storage/perfschema/table_mems_by_user_by_event_name.cc b/storage/perfschema/table_mems_by_user_by_event_name.cc
new file mode 100644
index 00000000000..5d5ee89d6bd
--- /dev/null
+++ b/storage/perfschema/table_mems_by_user_by_event_name.cc
@@ -0,0 +1,221 @@
+/* Copyright (c) 2011, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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/table_mems_by_user_by_event_name.cc
+ Table MEMORY_SUMMARY_BY_USER_BY_EVENT_NAME (implementation).
+*/
+
+#include "my_global.h"
+#include "my_thread.h"
+#include "pfs_instr_class.h"
+#include "pfs_column_types.h"
+#include "pfs_column_values.h"
+#include "table_mems_by_user_by_event_name.h"
+#include "pfs_global.h"
+#include "pfs_visitor.h"
+#include "pfs_memory.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
+
+THR_LOCK table_mems_by_user_by_event_name::m_table_lock;
+
+PFS_engine_table_share
+table_mems_by_user_by_event_name::m_share=
+{
+ { C_STRING_WITH_LEN("memory_summary_by_user_by_event_name") },
+ &pfs_readonly_acl,
+ table_mems_by_user_by_event_name::create,
+ NULL, /* write_row */
+ table_mems_by_user_by_event_name::delete_all_rows,
+ table_mems_by_user_by_event_name::get_row_count,
+ sizeof(PFS_simple_index),
+ &m_table_lock,
+ { C_STRING_WITH_LEN("CREATE TABLE memory_summary_by_user_by_event_name("
+ "USER CHAR(32) collate utf8_bin default null,"
+ "EVENT_NAME VARCHAR(128) not null,"
+ "COUNT_ALLOC BIGINT unsigned not null,"
+ "COUNT_FREE BIGINT unsigned not null,"
+ "SUM_NUMBER_OF_BYTES_ALLOC BIGINT unsigned not null,"
+ "SUM_NUMBER_OF_BYTES_FREE BIGINT unsigned not null,"
+ "LOW_COUNT_USED BIGINT not null,"
+ "CURRENT_COUNT_USED BIGINT not null,"
+ "HIGH_COUNT_USED BIGINT not null,"
+ "LOW_NUMBER_OF_BYTES_USED BIGINT not null,"
+ "CURRENT_NUMBER_OF_BYTES_USED BIGINT not null,"
+ "HIGH_NUMBER_OF_BYTES_USED BIGINT not null)")},
+ false /* perpetual */
+};
+
+PFS_engine_table* table_mems_by_user_by_event_name::create(void)
+{
+ return new table_mems_by_user_by_event_name();
+}
+
+int
+table_mems_by_user_by_event_name::delete_all_rows(void)
+{
+ reset_memory_by_thread();
+ reset_memory_by_account();
+ reset_memory_by_user();
+ return 0;
+}
+
+ha_rows
+table_mems_by_user_by_event_name::get_row_count(void)
+{
+ return global_user_container.get_row_count() * memory_class_max;
+}
+
+table_mems_by_user_by_event_name::table_mems_by_user_by_event_name()
+ : PFS_engine_table(&m_share, &m_pos),
+ m_row_exists(false), m_pos(), m_next_pos()
+{}
+
+void table_mems_by_user_by_event_name::reset_position(void)
+{
+ m_pos.reset();
+ m_next_pos.reset();
+}
+
+int table_mems_by_user_by_event_name::rnd_next(void)
+{
+ PFS_user *user;
+ PFS_memory_class *memory_class;
+ bool has_more_user= true;
+
+ for (m_pos.set_at(&m_next_pos);
+ has_more_user;
+ m_pos.next_user())
+ {
+ user= global_user_container.get(m_pos.m_index_1, & has_more_user);
+ if (user != NULL)
+ {
+ do
+ {
+ memory_class= find_memory_class(m_pos.m_index_2);
+ if (memory_class != NULL)
+ {
+ if (! memory_class->is_global())
+ {
+ make_row(user, memory_class);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+
+ m_pos.next_class();
+ }
+ }
+ while (memory_class != NULL);
+ }
+ }
+
+ return HA_ERR_END_OF_FILE;
+}
+
+int table_mems_by_user_by_event_name::rnd_pos(const void *pos)
+{
+ PFS_user *user;
+ PFS_memory_class *memory_class;
+
+ set_position(pos);
+
+ user= global_user_container.get(m_pos.m_index_1);
+ if (user != NULL)
+ {
+ memory_class= find_memory_class(m_pos.m_index_2);
+ if (memory_class != NULL)
+ {
+ if (! memory_class->is_global())
+ {
+ make_row(user, memory_class);
+ return 0;
+ }
+ }
+ }
+
+ return HA_ERR_RECORD_DELETED;
+}
+
+void table_mems_by_user_by_event_name
+::make_row(PFS_user *user, PFS_memory_class *klass)
+{
+ pfs_optimistic_state lock;
+ m_row_exists= false;
+
+ user->m_lock.begin_optimistic_lock(&lock);
+
+ if (m_row.m_user.make_row(user))
+ return;
+
+ m_row.m_event_name.make_row(klass);
+
+ PFS_connection_memory_visitor visitor(klass);
+ PFS_connection_iterator::visit_user(user,
+ true, /* accounts */
+ true, /* threads */
+ false, /* THDs */
+ & visitor);
+
+ if (! user->m_lock.end_optimistic_lock(&lock))
+ return;
+
+ m_row_exists= true;
+ m_row.m_stat.set(& visitor.m_stat);
+}
+
+int table_mems_by_user_by_event_name::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 0: /* USER */
+ m_row.m_user.set_field(f);
+ break;
+ case 1: /* EVENT_NAME */
+ m_row.m_event_name.set_field(f);
+ break;
+ default: /* 2, ... HIGH_NUMBER_OF_BYTES_USED */
+ m_row.m_stat.set_field(f->field_index - 2, f);
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
diff --git a/storage/perfschema/table_mems_by_user_by_event_name.h b/storage/perfschema/table_mems_by_user_by_event_name.h
new file mode 100644
index 00000000000..2791e1d3587
--- /dev/null
+++ b/storage/perfschema/table_mems_by_user_by_event_name.h
@@ -0,0 +1,129 @@
+/* Copyright (c) 2011, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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_MEMORY_SUMMARY_BY_USER_BY_EVENT_NAME_H
+#define TABLE_MEMORY_SUMMARY_BY_USER_BY_EVENT_NAME_H
+
+/**
+ @file storage/perfschema/table_mems_by_user_by_event_name.h
+ Table MEMORY_SUMMARY_BY_USER_BY_EVENT_NAME (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "pfs_instr_class.h"
+#include "pfs_user.h"
+#include "table_helper.h"
+
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+/** A row of PERFORMANCE_SCHEMA.MEMORY_SUMMARY_BY_USER_BY_EVENT_NAME. */
+struct row_mems_by_user_by_event_name
+{
+ /** Column USER. */
+ PFS_user_row m_user;
+ /** Column EVENT_NAME. */
+ PFS_event_name_row m_event_name;
+ /** Columns COUNT_ALLOC, ... */
+ PFS_memory_stat_row m_stat;
+};
+
+/**
+ Position of a cursor on
+ PERFORMANCE_SCHEMA.EVENTS_MEMORY_SUMMARY_BY_USER_BY_EVENT_NAME.
+ Index 1 on user (0 based)
+ Index 2 on memory class (1 based)
+*/
+struct pos_mems_by_user_by_event_name
+: public PFS_double_index
+{
+ pos_mems_by_user_by_event_name()
+ : PFS_double_index(0, 1)
+ {}
+
+ inline void reset(void)
+ {
+ m_index_1= 0;
+ m_index_2= 1;
+ }
+
+ inline void next_user(void)
+ {
+ m_index_1++;
+ m_index_2= 1;
+ }
+
+ inline void next_class(void)
+ {
+ m_index_2++;
+ }
+};
+
+/** Table PERFORMANCE_SCHEMA.MEMORY_SUMMARY_BY_USER_BY_EVENT_NAME. */
+class table_mems_by_user_by_event_name : public PFS_engine_table
+{
+public:
+ /** Table share */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static int delete_all_rows();
+ static ha_rows get_row_count();
+
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+private:
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+
+ table_mems_by_user_by_event_name();
+
+public:
+ ~table_mems_by_user_by_event_name()
+ {}
+
+private:
+ void make_row(PFS_user *user, PFS_memory_class *klass);
+
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /** Fields definition. */
+ static TABLE_FIELD_DEF m_field_def;
+
+ /** Current row. */
+ row_mems_by_user_by_event_name m_row;
+ /** True is the current row exists. */
+ bool m_row_exists;
+ /** Current position. */
+ pos_mems_by_user_by_event_name m_pos;
+ /** Next position. */
+ pos_mems_by_user_by_event_name m_next_pos;
+};
+
+/** @} */
+#endif
diff --git a/storage/perfschema/table_mems_global_by_event_name.cc b/storage/perfschema/table_mems_global_by_event_name.cc
new file mode 100644
index 00000000000..93496e38cf4
--- /dev/null
+++ b/storage/perfschema/table_mems_global_by_event_name.cc
@@ -0,0 +1,241 @@
+/* Copyright (c) 2011, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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/table_mems_global_by_event_name.cc
+ Table MEMORY_SUMMARY_GLOBAL_BY_EVENT_NAME (implementation).
+*/
+
+#include "my_global.h"
+#include "my_thread.h"
+#include "pfs_instr_class.h"
+#include "pfs_column_types.h"
+#include "pfs_column_values.h"
+#include "table_mems_global_by_event_name.h"
+#include "pfs_global.h"
+#include "pfs_visitor.h"
+#include "pfs_builtin_memory.h"
+#include "pfs_memory.h"
+#include "field.h"
+
+THR_LOCK table_mems_global_by_event_name::m_table_lock;
+
+PFS_engine_table_share
+table_mems_global_by_event_name::m_share=
+{
+ { C_STRING_WITH_LEN("memory_summary_global_by_event_name") },
+ &pfs_readonly_acl,
+ table_mems_global_by_event_name::create,
+ NULL, /* write_row */
+ table_mems_global_by_event_name::delete_all_rows,
+ table_mems_global_by_event_name::get_row_count,
+ sizeof(pos_t),
+ &m_table_lock,
+ { C_STRING_WITH_LEN("CREATE TABLE memory_summary_global_by_event_name("
+ "EVENT_NAME VARCHAR(128) not null,"
+ "COUNT_ALLOC BIGINT unsigned not null,"
+ "COUNT_FREE BIGINT unsigned not null,"
+ "SUM_NUMBER_OF_BYTES_ALLOC BIGINT unsigned not null,"
+ "SUM_NUMBER_OF_BYTES_FREE BIGINT unsigned not null,"
+ "LOW_COUNT_USED BIGINT not null,"
+ "CURRENT_COUNT_USED BIGINT not null,"
+ "HIGH_COUNT_USED BIGINT not null,"
+ "LOW_NUMBER_OF_BYTES_USED BIGINT not null,"
+ "CURRENT_NUMBER_OF_BYTES_USED BIGINT not null,"
+ "HIGH_NUMBER_OF_BYTES_USED BIGINT not null)")},
+ false /* perpetual */
+};
+
+PFS_engine_table* table_mems_global_by_event_name::create(void)
+{
+ return new table_mems_global_by_event_name();
+}
+
+int
+table_mems_global_by_event_name::delete_all_rows(void)
+{
+ reset_memory_by_thread();
+ reset_memory_by_account();
+ reset_memory_by_user();
+ reset_memory_by_host();
+ reset_memory_global();
+ return 0;
+}
+
+ha_rows
+table_mems_global_by_event_name::get_row_count(void)
+{
+ return memory_class_max;
+}
+
+table_mems_global_by_event_name::table_mems_global_by_event_name()
+ : PFS_engine_table(&m_share, &m_pos),
+ m_row_exists(false), m_pos(), m_next_pos()
+{}
+
+void table_mems_global_by_event_name::reset_position(void)
+{
+ m_pos.reset();
+ m_next_pos.reset();
+}
+
+int table_mems_global_by_event_name::rnd_next(void)
+{
+ PFS_memory_class *pfs;
+ PFS_builtin_memory_class *pfs_builtin;
+
+ /* Do not advertise hard coded instruments when disabled. */
+ if (! pfs_initialized)
+ return HA_ERR_END_OF_FILE;
+
+ for (m_pos.set_at(&m_next_pos);
+ m_pos.has_more_view();
+ m_pos.next_view())
+ {
+ switch (m_pos.m_index_1)
+ {
+ case pos_mems_global_by_event_name::VIEW_BUILTIN_MEMORY:
+ pfs_builtin= find_builtin_memory_class(m_pos.m_index_2);
+ if (pfs_builtin != NULL)
+ {
+ make_row(pfs_builtin);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+ break;
+ case pos_mems_global_by_event_name::VIEW_MEMORY:
+ pfs= find_memory_class(m_pos.m_index_2);
+ if (pfs != NULL)
+ {
+ make_row(pfs);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+ break;
+ }
+ }
+
+ return HA_ERR_END_OF_FILE;
+}
+
+int table_mems_global_by_event_name::rnd_pos(const void *pos)
+{
+ PFS_builtin_memory_class *pfs_builtin;
+ PFS_memory_class *pfs;
+
+ /* Do not advertise hard coded instruments when disabled. */
+ if (! pfs_initialized)
+ return HA_ERR_END_OF_FILE;
+
+ set_position(pos);
+
+ switch(m_pos.m_index_1)
+ {
+ case pos_mems_global_by_event_name::VIEW_BUILTIN_MEMORY:
+ pfs_builtin= find_builtin_memory_class(m_pos.m_index_2);
+ if (pfs_builtin != NULL)
+ {
+ make_row(pfs_builtin);
+ return 0;
+ }
+ break;
+ case pos_mems_global_by_event_name::VIEW_MEMORY:
+ pfs= find_memory_class(m_pos.m_index_2);
+ if (pfs != NULL)
+ {
+ make_row(pfs);
+ return 0;
+ }
+ break;
+ }
+
+ return HA_ERR_RECORD_DELETED;
+}
+
+void table_mems_global_by_event_name::make_row(PFS_memory_class *klass)
+{
+ m_row.m_event_name.make_row(klass);
+
+ PFS_connection_memory_visitor visitor(klass);
+
+ if (klass->is_global())
+ {
+ PFS_connection_iterator::visit_global(false, /* hosts */
+ false, /* users */
+ false, /* accounts */
+ false, /* threads */
+ false, /* THDs */
+ &visitor);
+ }
+ else
+ {
+ PFS_connection_iterator::visit_global(true, /* hosts */
+ false, /* users */
+ true, /* accounts */
+ true, /* threads */
+ false, /* THDs */
+ &visitor);
+ }
+
+ m_row.m_stat.set(& visitor.m_stat);
+ m_row_exists= true;
+}
+
+void table_mems_global_by_event_name::make_row(PFS_builtin_memory_class *klass)
+{
+ m_row.m_event_name.make_row(& klass->m_class);
+ m_row.m_stat.set(& klass->m_stat);
+ m_row_exists= true;
+}
+
+int table_mems_global_by_event_name::read_row_values(TABLE *table,
+ unsigned char *,
+ 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 == 0);
+
+ for (; (f= *fields) ; fields++)
+ {
+ if (read_all || bitmap_is_set(table->read_set, f->field_index))
+ {
+ switch(f->field_index)
+ {
+ case 0: /* EVENT_NAME */
+ m_row.m_event_name.set_field(f);
+ break;
+ default: /* 1, ... HIGH_NUMBER_OF_BYTES_USED */
+ m_row.m_stat.set_field(f->field_index - 1, f);
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
diff --git a/storage/perfschema/table_mems_global_by_event_name.h b/storage/perfschema/table_mems_global_by_event_name.h
new file mode 100644
index 00000000000..14a54142f4e
--- /dev/null
+++ b/storage/perfschema/table_mems_global_by_event_name.h
@@ -0,0 +1,132 @@
+/* Copyright (c) 2011, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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_MEMORY_SUMMARY_GLOBAL_BY_EVENT_NAME_H
+#define TABLE_MEMORY_SUMMARY_GLOBAL_BY_EVENT_NAME_H
+
+/**
+ @file storage/perfschema/table_mems_global_by_event_name.h
+ Table MEMORY_SUMMARY_GLOBAL_BY_EVENT_NAME (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "pfs_instr_class.h"
+#include "pfs_builtin_memory.h"
+#include "table_helper.h"
+
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+/** A row of PERFORMANCE_SCHEMA.MEMORY_SUMMARY_GLOBAL_BY_EVENT_NAME. */
+struct row_mems_global_by_event_name
+{
+ /** Column EVENT_NAME. */
+ PFS_event_name_row m_event_name;
+ /** Columns COUNT_ALLOC, ... */
+ PFS_memory_stat_row m_stat;
+};
+
+/**
+ Position of a cursor on
+ PERFORMANCE_SCHEMA.MEMORY_SUMMARY_GLOBAL_BY_EVENT_NAME.
+ Index 1 on view
+ Index 2 on instrument key (1 based)
+*/
+struct pos_mems_global_by_event_name : public PFS_double_index
+{
+ static const uint FIRST_VIEW= 1;
+ static const uint VIEW_BUILTIN_MEMORY= 1;
+ static const uint VIEW_MEMORY= 2;
+ static const uint LAST_VIEW= 2;
+
+ pos_mems_global_by_event_name()
+ : PFS_double_index(FIRST_VIEW, 1)
+ {}
+
+ inline void reset(void)
+ {
+ m_index_1= FIRST_VIEW;
+ m_index_2= 1;
+ }
+
+ inline bool has_more_view(void)
+ { return (m_index_1 <= LAST_VIEW); }
+
+ inline void next_view(void)
+ {
+ m_index_1++;
+ m_index_2= 1;
+ }
+};
+
+/** Table PERFORMANCE_SCHEMA.MEMORY_SUMMARY_GLOBAL_BY_EVENT_NAME. */
+class table_mems_global_by_event_name : public PFS_engine_table
+{
+ typedef pos_mems_global_by_event_name pos_t;
+
+public:
+ /** Table share */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static int delete_all_rows();
+ static ha_rows get_row_count();
+
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+private:
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+
+ table_mems_global_by_event_name();
+
+public:
+ ~table_mems_global_by_event_name()
+ {}
+
+private:
+ void make_row(PFS_builtin_memory_class *klass);
+ void make_row(PFS_memory_class *klass);
+
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /** Fields definition. */
+ static TABLE_FIELD_DEF m_field_def;
+
+ /** Current row. */
+ row_mems_global_by_event_name m_row;
+ /** True is the current row exists. */
+ bool m_row_exists;
+ /** Current position. */
+ pos_t m_pos;
+ /** Next position. */
+ pos_t m_next_pos;
+};
+
+/** @} */
+#endif
diff --git a/storage/perfschema/table_os_global_by_type.cc b/storage/perfschema/table_os_global_by_type.cc
index b549b0c22e7..f693a0f16da 100644
--- a/storage/perfschema/table_os_global_by_type.cc
+++ b/storage/perfschema/table_os_global_by_type.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -26,12 +26,14 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_instr_class.h"
#include "pfs_column_types.h"
#include "pfs_column_values.h"
#include "table_os_global_by_type.h"
#include "pfs_global.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
THR_LOCK table_os_global_by_type::m_table_lock;
@@ -43,8 +45,7 @@ table_os_global_by_type::m_share=
table_os_global_by_type::create,
NULL, /* write_row */
table_os_global_by_type::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ table_os_global_by_type::get_row_count,
sizeof(pos_os_global_by_type),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE objects_summary_global_by_type("
@@ -55,7 +56,8 @@ table_os_global_by_type::m_share=
"SUM_TIMER_WAIT BIGINT unsigned not null,"
"MIN_TIMER_WAIT BIGINT unsigned not null,"
"AVG_TIMER_WAIT BIGINT unsigned not null,"
- "MAX_TIMER_WAIT BIGINT unsigned not null)") }
+ "MAX_TIMER_WAIT BIGINT unsigned not null)") },
+ false /* perpetual */
};
PFS_engine_table*
@@ -72,6 +74,13 @@ table_os_global_by_type::delete_all_rows(void)
return 0;
}
+ha_rows
+table_os_global_by_type::get_row_count(void)
+{
+ return global_table_share_container.get_row_count() +
+ global_program_container.get_row_count();
+}
+
table_os_global_by_type::table_os_global_by_type()
: PFS_engine_table(&m_share, &m_pos),
m_row_exists(false), m_pos(), m_next_pos()
@@ -85,22 +94,46 @@ void table_os_global_by_type::reset_position(void)
int table_os_global_by_type::rnd_next(void)
{
- PFS_table_share *table_share;
-
for (m_pos.set_at(&m_next_pos);
m_pos.has_more_view();
m_pos.next_view())
{
switch (m_pos.m_index_1) {
case pos_os_global_by_type::VIEW_TABLE:
- for ( ; m_pos.m_index_2 < table_share_max; m_pos.m_index_2++)
{
- table_share= &table_share_array[m_pos.m_index_2];
- if (table_share->m_lock.is_populated())
+ PFS_table_share *table_share;
+ bool has_more_share= true;
+
+ for (;
+ has_more_share;
+ m_pos.m_index_2++)
{
- make_row(table_share);
- m_next_pos.set_after(&m_pos);
- return 0;
+ table_share= global_table_share_container.get(m_pos.m_index_2, & has_more_share);
+ if (table_share != NULL)
+ {
+ make_table_row(table_share);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+ }
+ }
+ break;
+ case pos_os_global_by_type::VIEW_PROGRAM:
+ {
+ PFS_program *pfs_program;
+ bool has_more_program= true;
+
+ for (;
+ has_more_program;
+ m_pos.m_index_2++)
+ {
+ pfs_program= global_program_container.get(m_pos.m_index_2, & has_more_program);
+ if (pfs_program != NULL)
+ {
+ make_program_row(pfs_program);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
}
}
break;
@@ -115,18 +148,29 @@ int table_os_global_by_type::rnd_next(void)
int
table_os_global_by_type::rnd_pos(const void *pos)
{
- PFS_table_share *table_share;
-
set_position(pos);
switch (m_pos.m_index_1) {
case pos_os_global_by_type::VIEW_TABLE:
- DBUG_ASSERT(m_pos.m_index_2 < table_share_max);
- table_share= &table_share_array[m_pos.m_index_2];
- if (table_share->m_lock.is_populated())
{
- make_row(table_share);
- return 0;
+ PFS_table_share *table_share;
+ table_share= global_table_share_container.get(m_pos.m_index_2);
+ if (table_share != NULL)
+ {
+ make_table_row(table_share);
+ return 0;
+ }
+ }
+ break;
+ case pos_os_global_by_type::VIEW_PROGRAM:
+ {
+ PFS_program *pfs_program;
+ pfs_program= global_program_container.get(m_pos.m_index_2);
+ if (pfs_program != NULL)
+ {
+ make_program_row(pfs_program);
+ return 0;
+ }
}
break;
default:
@@ -136,9 +180,29 @@ table_os_global_by_type::rnd_pos(const void *pos)
return HA_ERR_RECORD_DELETED;
}
-void table_os_global_by_type::make_row(PFS_table_share *share)
+void table_os_global_by_type::make_program_row(PFS_program *pfs_program)
{
- pfs_lock lock;
+ pfs_optimistic_state lock;
+ PFS_single_stat cumulated_stat;
+
+ m_row_exists= false;
+
+ pfs_program->m_lock.begin_optimistic_lock(&lock);
+
+ m_row.m_object.make_row(pfs_program);
+
+ time_normalizer *normalizer= time_normalizer::get(wait_timer);
+ m_row.m_stat.set(normalizer, &pfs_program->m_sp_stat.m_timer1_stat);
+
+ if (! pfs_program->m_lock.end_optimistic_lock(&lock))
+ return;
+
+ m_row_exists= true;
+}
+
+void table_os_global_by_type::make_table_row(PFS_table_share *share)
+{
+ pfs_optimistic_state lock;
PFS_single_stat cumulated_stat;
uint safe_key_count;
@@ -146,16 +210,12 @@ void table_os_global_by_type::make_row(PFS_table_share *share)
share->m_lock.begin_optimistic_lock(&lock);
- m_row.m_object_type= share->get_object_type();
- memcpy(m_row.m_schema_name, share->m_schema_name, share->m_schema_name_length);
- 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;
+ m_row.m_object.make_row(share);
/* 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);
+ share->sum(& cumulated_stat, safe_key_count);
if (! share->m_lock.end_optimistic_lock(&lock))
return;
@@ -165,11 +225,12 @@ void table_os_global_by_type::make_row(PFS_table_share *share)
if (share->get_refcount() > 0)
{
/* For all the table handles still opened ... */
- PFS_table *table= table_array;
- PFS_table *table_last= table_array + table_max;
- for ( ; table < table_last ; table++)
+ PFS_table_iterator it= global_table_container.iterate();
+ PFS_table *table= it.scan_next();
+
+ while (table != NULL)
{
- if ((table->m_share == share) && (table->m_lock.is_populated()))
+ if (table->m_share == share)
{
/*
If the opened table handle is for this table share,
@@ -177,6 +238,7 @@ void table_os_global_by_type::make_row(PFS_table_share *share)
*/
table->m_table_stat.sum(& cumulated_stat, safe_key_count);
}
+ table= it.scan_next();
}
}
@@ -205,15 +267,15 @@ int table_os_global_by_type::read_row_values(TABLE *table,
switch(f->field_index)
{
case 0: /* OBJECT_TYPE */
- set_field_object_type(f, m_row.m_object_type);
+ set_field_object_type(f, m_row.m_object.m_object_type);
break;
case 1: /* SCHEMA_NAME */
- set_field_varchar_utf8(f, m_row.m_schema_name,
- m_row.m_schema_name_length);
+ set_field_varchar_utf8(f, m_row.m_object.m_schema_name,
+ m_row.m_object.m_schema_name_length);
break;
case 2: /* OBJECT_NAME */
- set_field_varchar_utf8(f, m_row.m_object_name,
- m_row.m_object_name_length);
+ set_field_varchar_utf8(f, m_row.m_object.m_object_name,
+ m_row.m_object.m_object_name_length);
break;
case 3: /* COUNT */
set_field_ulonglong(f, m_row.m_stat.m_count);
diff --git a/storage/perfschema/table_os_global_by_type.h b/storage/perfschema/table_os_global_by_type.h
index 2b9293ece06..37e6db1ed94 100644
--- a/storage/perfschema/table_os_global_by_type.h
+++ b/storage/perfschema/table_os_global_by_type.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -32,6 +32,7 @@
#include "pfs_engine_table.h"
#include "pfs_instr_class.h"
#include "pfs_instr.h"
+#include "pfs_program.h"
#include "table_helper.h"
/**
@@ -45,16 +46,9 @@
*/
struct row_os_global_by_type
{
- /** Column OBJECT_TYPE. */
- enum_object_type m_object_type;
- /** Column SCHEMA_NAME. */
- char m_schema_name[NAME_LEN];
- /** Length in bytes of @c m_schema_name. */
- uint m_schema_name_length;
- /** Column OBJECT_NAME. */
- char m_object_name[NAME_LEN];
- /** Length in bytes of @c m_object_name. */
- uint m_object_name_length;
+ /** Column OBJECT_TYPE, SCHEMA_NAME, OBJECT_NAME. */
+ PFS_object_row m_object;
+
/** Columns COUNT_STAR, SUM/MIN/AVG/MAX TIMER_WAIT. */
PFS_stat_row m_stat;
};
@@ -96,6 +90,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_next();
virtual int rnd_pos(const void *pos);
@@ -114,7 +109,8 @@ public:
{}
protected:
- void make_row(PFS_table_share *table_share);
+ void make_table_row(PFS_table_share *table_share);
+ void make_program_row(PFS_program *pfs_program);
private:
/** Table share lock. */
diff --git a/storage/perfschema/table_performance_timers.cc b/storage/perfschema/table_performance_timers.cc
index a77f005ab62..1c1d9c5afef 100644
--- a/storage/perfschema/table_performance_timers.cc
+++ b/storage/perfschema/table_performance_timers.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -26,10 +26,11 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "table_performance_timers.h"
#include "pfs_timer.h"
#include "pfs_global.h"
+#include "field.h"
THR_LOCK table_performance_timers::m_table_lock;
@@ -38,18 +39,18 @@ table_performance_timers::m_share=
{
{ C_STRING_WITH_LEN("performance_timers") },
&pfs_readonly_acl,
- &table_performance_timers::create,
+ table_performance_timers::create,
NULL, /* write_row */
NULL, /* delete_all_rows */
- NULL, /* get_row_count */
- COUNT_TIMER_NAME, /* records */
+ table_performance_timers::get_row_count,
sizeof(PFS_simple_index), /* ref length */
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE performance_timers("
"TIMER_NAME ENUM ('CYCLE', 'NANOSECOND', 'MICROSECOND', 'MILLISECOND', 'TICK') not null,"
"TIMER_FREQUENCY BIGINT,"
"TIMER_RESOLUTION BIGINT,"
- "TIMER_OVERHEAD BIGINT)") }
+ "TIMER_OVERHEAD BIGINT)") },
+ false /* perpetual */
};
PFS_engine_table* table_performance_timers::create(void)
@@ -57,6 +58,12 @@ PFS_engine_table* table_performance_timers::create(void)
return new table_performance_timers();
}
+ha_rows
+table_performance_timers::get_row_count(void)
+{
+ return COUNT_TIMER_NAME;
+}
+
table_performance_timers::table_performance_timers()
: PFS_engine_table(&m_share, &m_pos),
m_row(NULL), m_pos(0), m_next_pos(0)
diff --git a/storage/perfschema/table_performance_timers.h b/storage/perfschema/table_performance_timers.h
index 93210ac9882..fe5f9cd5f4a 100644
--- a/storage/perfschema/table_performance_timers.h
+++ b/storage/perfschema/table_performance_timers.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -56,6 +56,7 @@ public:
/** Table share. */
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
+ static ha_rows get_row_count();
virtual int rnd_next();
virtual int rnd_pos(const void *pos);
diff --git a/storage/perfschema/table_prepared_stmt_instances.cc b/storage/perfschema/table_prepared_stmt_instances.cc
new file mode 100644
index 00000000000..6e93523deb4
--- /dev/null
+++ b/storage/perfschema/table_prepared_stmt_instances.cc
@@ -0,0 +1,294 @@
+/* Copyright (c) 2014, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+
+/**
+ @file storage/perfschema/table_prepared_stmt_instances.cc
+ Table PREPARED_STATEMENTS_INSTANCES (implementation).
+*/
+
+#include "my_global.h"
+#include "my_thread.h"
+#include "pfs_instr_class.h"
+#include "pfs_column_types.h"
+#include "pfs_column_values.h"
+#include "pfs_global.h"
+#include "pfs_instr.h"
+#include "pfs_timer.h"
+#include "pfs_visitor.h"
+#include "pfs_prepared_stmt.h"
+#include "table_prepared_stmt_instances.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
+
+THR_LOCK table_prepared_stmt_instances::m_table_lock;
+
+PFS_engine_table_share
+table_prepared_stmt_instances::m_share=
+{
+ { C_STRING_WITH_LEN("prepared_statements_instances") },
+ &pfs_truncatable_acl,
+ table_prepared_stmt_instances::create,
+ NULL, /* write_row */
+ table_prepared_stmt_instances::delete_all_rows,
+ table_prepared_stmt_instances::get_row_count,
+ sizeof(PFS_simple_index),
+ &m_table_lock,
+ { C_STRING_WITH_LEN("CREATE TABLE prepared_statements_instances("
+ "OBJECT_INSTANCE_BEGIN bigint(20) unsigned NOT NULL,"
+ "STATEMENT_ID bigint(20) unsigned NOT NULL,"
+ "STATEMENT_NAME varchar(64) default NULL,"
+ "SQL_TEXT longtext NOT NULL,"
+ "OWNER_THREAD_ID bigint(20) unsigned NOT NULL,"
+ "OWNER_EVENT_ID bigint(20) unsigned NOT NULL,"
+ "OWNER_OBJECT_TYPE enum('EVENT','FUNCTION','PROCEDURE','TABLE','TRIGGER') DEFAULT NULL,"
+ "OWNER_OBJECT_SCHEMA varchar(64) DEFAULT NULL,"
+ "OWNER_OBJECT_NAME varchar(64) DEFAULT NULL,"
+ "TIMER_PREPARE bigint(20) unsigned NOT NULL,"
+ "COUNT_REPREPARE bigint(20) unsigned NOT NULL,"
+ "COUNT_EXECUTE bigint(20) unsigned NOT NULL,"
+ "SUM_TIMER_EXECUTE bigint(20) unsigned NOT NULL,"
+ "MIN_TIMER_EXECUTE bigint(20) unsigned NOT NULL,"
+ "AVG_TIMER_EXECUTE bigint(20) unsigned NOT NULL,"
+ "MAX_TIMER_EXECUTE bigint(20) unsigned NOT NULL,"
+ "SUM_LOCK_TIME bigint(20) unsigned NOT NULL,"
+ "SUM_ERRORS bigint(20) unsigned NOT NULL,"
+ "SUM_WARNINGS bigint(20) unsigned NOT NULL,"
+ "SUM_ROWS_AFFECTED bigint(20) unsigned NOT NULL,"
+ "SUM_ROWS_SENT bigint(20) unsigned NOT NULL,"
+ "SUM_ROWS_EXAMINED bigint(20) unsigned NOT NULL,"
+ "SUM_CREATED_TMP_DISK_TABLES bigint(20) unsigned NOT NULL,"
+ "SUM_CREATED_TMP_TABLES bigint(20) unsigned NOT NULL,"
+ "SUM_SELECT_FULL_JOIN bigint(20) unsigned NOT NULL,"
+ "SUM_SELECT_FULL_RANGE_JOIN bigint(20) unsigned NOT NULL,"
+ "SUM_SELECT_RANGE bigint(20) unsigned NOT NULL,"
+ "SUM_SELECT_RANGE_CHECK bigint(20) unsigned NOT NULL,"
+ "SUM_SELECT_SCAN bigint(20) unsigned NOT NULL,"
+ "SUM_SORT_MERGE_PASSES bigint(20) unsigned NOT NULL,"
+ "SUM_SORT_RANGE bigint(20) unsigned NOT NULL,"
+ "SUM_SORT_ROWS bigint(20) unsigned NOT NULL,"
+ "SUM_SORT_SCAN bigint(20) unsigned NOT NULL,"
+ "SUM_NO_INDEX_USED bigint(20) unsigned NOT NULL,"
+ "SUM_NO_GOOD_INDEX_USED bigint(20) unsigned NOT NULL)")},
+ false /* perpetual */
+};
+
+PFS_engine_table*
+table_prepared_stmt_instances::create(void)
+{
+ return new table_prepared_stmt_instances();
+}
+
+int
+table_prepared_stmt_instances::delete_all_rows(void)
+{
+ reset_prepared_stmt_instances();
+ return 0;
+}
+
+ha_rows
+table_prepared_stmt_instances::get_row_count(void)
+{
+ return global_prepared_stmt_container.get_row_count();
+}
+
+table_prepared_stmt_instances::table_prepared_stmt_instances()
+ : PFS_engine_table(&m_share, &m_pos),
+ m_row_exists(false), m_pos(0), m_next_pos(0)
+{}
+
+void table_prepared_stmt_instances::reset_position(void)
+{
+ m_pos= 0;
+ m_next_pos= 0;
+}
+
+int table_prepared_stmt_instances::rnd_next(void)
+{
+ PFS_prepared_stmt* pfs;
+
+ m_pos.set_at(&m_next_pos);
+ PFS_prepared_stmt_iterator it= global_prepared_stmt_container.iterate(m_pos.m_index);
+ pfs= it.scan_next(& m_pos.m_index);
+ if (pfs != NULL)
+ {
+ make_row(pfs);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+
+ return HA_ERR_END_OF_FILE;
+}
+
+int
+table_prepared_stmt_instances::rnd_pos(const void *pos)
+{
+ PFS_prepared_stmt* pfs;
+
+ set_position(pos);
+
+ pfs= global_prepared_stmt_container.get(m_pos.m_index);
+ if (pfs != NULL)
+ {
+ make_row(pfs);
+ return 0;
+ }
+
+ return HA_ERR_RECORD_DELETED;
+}
+
+
+void table_prepared_stmt_instances::make_row(PFS_prepared_stmt* prepared_stmt)
+{
+ pfs_optimistic_state lock;
+ m_row_exists= false;
+
+ prepared_stmt->m_lock.begin_optimistic_lock(&lock);
+
+ m_row.m_identity= prepared_stmt->m_identity;
+
+ m_row.m_stmt_id= prepared_stmt->m_stmt_id;
+
+ m_row.m_owner_thread_id= prepared_stmt->m_owner_thread_id;
+ m_row.m_owner_event_id= prepared_stmt->m_owner_event_id;
+
+ m_row.m_stmt_name_length= prepared_stmt->m_stmt_name_length;
+ if(m_row.m_stmt_name_length > 0)
+ memcpy(m_row.m_stmt_name, prepared_stmt->m_stmt_name,
+ m_row.m_stmt_name_length);
+
+ m_row.m_sql_text_length= prepared_stmt->m_sqltext_length;
+ if(m_row.m_sql_text_length > 0)
+ memcpy(m_row.m_sql_text, prepared_stmt->m_sqltext,
+ m_row.m_sql_text_length);
+
+ m_row.m_owner_object_type= prepared_stmt->m_owner_object_type;
+
+ m_row.m_owner_object_name_length= prepared_stmt->m_owner_object_name_length;
+ if(m_row.m_owner_object_name_length > 0)
+ memcpy(m_row.m_owner_object_name, prepared_stmt->m_owner_object_name,
+ m_row.m_owner_object_name_length);
+
+ m_row.m_owner_object_schema_length= prepared_stmt->m_owner_object_schema_length;
+ if(m_row.m_owner_object_schema_length > 0)
+ memcpy(m_row.m_owner_object_schema, prepared_stmt->m_owner_object_schema,
+ m_row.m_owner_object_schema_length);
+
+ time_normalizer *normalizer= time_normalizer::get(statement_timer);
+ /* Get prepared statement prepare stats. */
+ m_row.m_prepare_stat.set(normalizer, & prepared_stmt->m_prepare_stat);
+ /* Get prepared statement reprepare stats. */
+ m_row.m_reprepare_stat.set(normalizer, & prepared_stmt->m_reprepare_stat);
+ /* Get prepared statement execute stats. */
+ m_row.m_execute_stat.set(normalizer, & prepared_stmt->m_execute_stat);
+
+ if (! prepared_stmt->m_lock.end_optimistic_lock(&lock))
+ return;
+
+ m_row_exists= true;
+}
+
+int table_prepared_stmt_instances
+::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 0: /* OBJECT_INSTANCE_BEGIN */
+ set_field_ulonglong(f, (intptr)m_row.m_identity);
+ break;
+ case 1: /* STATEMENT_ID */
+ set_field_ulonglong(f, m_row.m_stmt_id);
+ break;
+ case 2: /* STATEMENT_NAME */
+ if(m_row.m_stmt_name_length > 0)
+ set_field_varchar_utf8(f, m_row.m_stmt_name,
+ m_row.m_stmt_name_length);
+ else
+ f->set_null();
+ break;
+ case 3: /* SQL_TEXT */
+ if(m_row.m_sql_text_length > 0)
+ set_field_longtext_utf8(f, m_row.m_sql_text,
+ m_row.m_sql_text_length);
+ else
+ f->set_null();
+ break;
+ case 4: /* OWNER_THREAD_ID */
+ set_field_ulonglong(f, m_row.m_owner_thread_id);
+ break;
+ case 5: /* OWNER_EVENT_ID */
+ if(m_row.m_owner_event_id > 0)
+ set_field_ulonglong(f, m_row.m_owner_event_id);
+ else
+ f->set_null();
+ break;
+ case 6: /* OWNER_OBJECT_TYPE */
+ if(m_row.m_owner_object_type != 0)
+ set_field_enum(f, m_row.m_owner_object_type);
+ else
+ f->set_null();
+ break;
+ case 7: /* OWNER_OBJECT_SCHEMA */
+ if(m_row.m_owner_object_schema_length > 0)
+ set_field_varchar_utf8(f, m_row.m_owner_object_schema,
+ m_row.m_owner_object_schema_length);
+ else
+ f->set_null();
+ break;
+ case 8: /* OWNER_OBJECT_NAME */
+ if(m_row.m_owner_object_name_length > 0)
+ set_field_varchar_utf8(f, m_row.m_owner_object_name,
+ m_row.m_owner_object_name_length);
+ else
+ f->set_null();
+ break;
+ case 9: /* TIMER_PREPARE */
+ m_row.m_prepare_stat.set_field(1, f);
+ break;
+ case 10: /* COUNT_REPREPARE */
+ m_row.m_reprepare_stat.set_field(0, f);
+ break;
+ default: /* 14, ... COUNT/SUM/MIN/AVG/MAX */
+ m_row.m_execute_stat.set_field(f->field_index - 11, f);
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
diff --git a/storage/perfschema/table_prepared_stmt_instances.h b/storage/perfschema/table_prepared_stmt_instances.h
new file mode 100644
index 00000000000..a17184d4312
--- /dev/null
+++ b/storage/perfschema/table_prepared_stmt_instances.h
@@ -0,0 +1,132 @@
+/* Copyright (c) 2014, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+
+#ifndef TABLE_PREPARED_STMT_INSTANCES
+#define TABLE_PREPARED_STMT_INSTANCES
+
+/**
+ @file storage/perfschema/table_prepared_stmt_instances.h
+ Table PREPARED_STATEMENT_INSTANCE(declarations).
+*/
+
+#include "table_helper.h"
+#include "pfs_prepared_stmt.h"
+
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+/**
+ A row of table
+ PERFORMANCE_SCHEMA.PREPARED_STATEMENT_INSTANCES.
+*/
+struct row_prepared_stmt_instances
+{
+ /** Column OBJECT_INSTANCE_BEGIN. */
+ const void *m_identity;
+
+ /** Column STMT_ID. */
+ ulonglong m_stmt_id;
+
+ /** Column STMT_NAME. */
+ char m_stmt_name[COL_INFO_SIZE];
+ int m_stmt_name_length;
+
+ /** Column SQL_TEXT. */
+ char m_sql_text[COL_INFO_SIZE];
+ int m_sql_text_length;
+
+ /** Column OWNER_THREAD_ID. */
+ ulonglong m_owner_thread_id;
+
+ /** Column OWNER_EVENT_ID. */
+ ulonglong m_owner_event_id;
+
+ /** Column OWNER_OBJECT_TYPE. */
+ enum_object_type m_owner_object_type;
+
+ /** Column OWNER_OBJECT_SCHEMA */
+ char m_owner_object_schema[COL_OBJECT_SCHEMA_SIZE];
+ int m_owner_object_schema_length;
+
+ /** Column OWNER_OBJECT_NAME */
+ char m_owner_object_name[COL_OBJECT_NAME_SIZE];
+ int m_owner_object_name_length;
+
+ /** Columns TIMER_PREPARE. */
+ PFS_stat_row m_prepare_stat;
+
+ /** Columns COUNT_REPREPARE. */
+ PFS_stat_row m_reprepare_stat;
+
+ /** Columns COUNT_STAR...SUM_NO_GOOD_INDEX_USED. */
+ PFS_statement_stat_row m_execute_stat;
+};
+
+/** Table PERFORMANCE_SCHEMA.PREPARED_STATEMENT_INSTANCES. */
+class table_prepared_stmt_instances : public PFS_engine_table
+{
+public:
+ /** Table share */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static int delete_all_rows();
+ static ha_rows get_row_count();
+
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+protected:
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+
+ table_prepared_stmt_instances();
+
+public:
+ ~table_prepared_stmt_instances()
+ {}
+
+protected:
+ void make_row(PFS_prepared_stmt*);
+
+private:
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /** Fields definition. */
+ static TABLE_FIELD_DEF m_field_def;
+
+ /** Current row. */
+ row_prepared_stmt_instances m_row;
+ /** True is the current row exists. */
+ bool m_row_exists;
+ /** Current position. */
+ PFS_simple_index m_pos;
+ /** Next position. */
+ PFS_simple_index m_next_pos;
+};
+
+/** @} */
+#endif
diff --git a/storage/perfschema/table_replication_applier_configuration.cc b/storage/perfschema/table_replication_applier_configuration.cc
new file mode 100644
index 00000000000..cb5dfd05e69
--- /dev/null
+++ b/storage/perfschema/table_replication_applier_configuration.cc
@@ -0,0 +1,192 @@
+/*
+ Copyright (c) 2013, 2018, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/**
+ @file storage/perfschema/table_replication_applier_configuration.cc
+ Table replication_applier_configuration (implementation).
+*/
+
+#define HAVE_REPLICATION
+
+#include "my_global.h"
+#include "table_replication_applier_configuration.h"
+#include "pfs_instr_class.h"
+#include "pfs_instr.h"
+#include "slave.h"
+//#include "rpl_info.h"
+#include "rpl_rli.h"
+#include "rpl_mi.h"
+#include "sql_parse.h"
+//#include "rpl_msr.h" /* Multisource replication */
+
+THR_LOCK table_replication_applier_configuration::m_table_lock;
+
+PFS_engine_table_share
+table_replication_applier_configuration::m_share=
+{
+ { C_STRING_WITH_LEN("replication_applier_configuration") },
+ &pfs_readonly_acl,
+ table_replication_applier_configuration::create,
+ NULL, /* write_row */
+ NULL, /* delete_all_rows */
+ table_replication_applier_configuration::get_row_count,
+ sizeof(pos_t), /* ref length */
+ &m_table_lock,
+ { C_STRING_WITH_LEN("CREATE TABLE replication_applier_configuration("
+ "CHANNEL_NAME CHAR(64) collate utf8_general_ci not null,"
+ "DESIRED_DELAY INTEGER not null)") },
+ false /* perpetual */
+};
+
+PFS_engine_table* table_replication_applier_configuration::create(void)
+{
+ return new table_replication_applier_configuration();
+}
+
+table_replication_applier_configuration
+ ::table_replication_applier_configuration()
+ : PFS_engine_table(&m_share, &m_pos),
+ m_row_exists(false), m_pos(0), m_next_pos(0)
+{}
+
+table_replication_applier_configuration
+ ::~table_replication_applier_configuration()
+{}
+
+void table_replication_applier_configuration::reset_position(void)
+{
+ m_pos.m_index= 0;
+ m_next_pos.m_index= 0;
+}
+
+
+ha_rows table_replication_applier_configuration::get_row_count()
+{
+ return master_info_index->master_info_hash.records;
+}
+
+
+int table_replication_applier_configuration::rnd_next(void)
+{
+ Master_info *mi;
+ mysql_mutex_lock(&LOCK_active_mi);
+
+ for (m_pos.set_at(&m_next_pos);
+ m_pos.m_index < master_info_index->master_info_hash.records;
+ m_pos.next())
+ {
+ mi= (Master_info *)my_hash_element(&master_info_index->master_info_hash, m_pos.m_index);
+
+ if (mi && mi->host[0])
+ {
+ make_row(mi);
+ m_next_pos.set_after(&m_pos);
+ channel_map.unlock();
+ return 0;
+ }
+ }
+
+ mysql_mutex_unlock(&LOCK_active_mi);
+ return HA_ERR_END_OF_FILE;
+}
+
+int table_replication_applier_configuration::rnd_pos(const void *pos)
+{
+ Master_info *mi;
+ int res= HA_ERR_RECORD_DELETED;
+
+ set_position(pos);
+
+ mysql_mutex_lock(&LOCK_active_mi);
+
+ if ((mi= (Master_info *)my_hash_element(&master_info_index->master_info_hash, m_pos.m_index)))
+ {
+ make_row(mi);
+ res= 0;
+ }
+
+ mysql_mutex_unlock(&LOCK_active_mi);
+ return res;
+}
+
+void table_replication_applier_configuration::make_row(Master_info *mi)
+{
+ m_row_exists= false;
+
+ DBUG_ASSERT(mi != NULL);
+
+ mysql_mutex_lock(&mi->data_lock);
+ mysql_mutex_lock(&mi->rli.data_lock);
+
+ m_row.channel_name_length= mi->connection_name.length;
+ memcpy(m_row.channel_name, mi->connection_name.str, m_row.channel_name_length);
+ m_row.desired_delay= 0; //mi->rli->get_sql_delay();
+
+ mysql_mutex_unlock(&mi->rli.data_lock);
+ mysql_mutex_unlock(&mi->data_lock);
+
+ m_row_exists= true;
+}
+
+int table_replication_applier_configuration::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;
+
+ /*
+ Note:
+ There are no NULL columns in this table,
+ so there are no null bits reserved for NULL flags per column.
+ There are no VARCHAR columns either, so the record is not
+ in HA_OPTION_PACK_RECORD format as most other performance_schema tables.
+ When HA_OPTION_PACK_RECORD is not set,
+ the table record reserves an extra null byte, see open_binary_frm().
+ */
+
+ 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 0: /**channel_name*/
+ set_field_char_utf8(f, m_row.channel_name, m_row.channel_name_length);
+ break;
+ case 1: /** desired_delay */
+ set_field_ulong(f, static_cast<ulong>(m_row.desired_delay));
+ break;
+ default:
+ DBUG_ASSERT(false);
+ }
+ }
+ }
+ return 0;
+}
diff --git a/storage/perfschema/table_replication_applier_configuration.h b/storage/perfschema/table_replication_applier_configuration.h
new file mode 100644
index 00000000000..18321ac079e
--- /dev/null
+++ b/storage/perfschema/table_replication_applier_configuration.h
@@ -0,0 +1,107 @@
+/*
+ Copyright (c) 2013, 2018, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+
+#ifndef TABLE_REPLICATION_APPLIER_CONFIGURATION_H
+#define TABLE_REPLICATION_APPLIER_CONFIGURATION_H
+
+/**
+ @file storage/perfschema/table_replication_applier_configuration.h
+ Table replication_applier_configuration (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "rpl_mi.h"
+#include "mysql_com.h"
+#include "my_thread.h"
+//#include "rpl_msr.h"
+//#include "rpl_info.h" /*CHANNEL_NAME_LENGTH*/
+
+class Master_info;
+
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+/** A row in the table*/
+struct st_row_applier_config {
+ char channel_name[CHANNEL_NAME_LENGTH];
+ uint channel_name_length;
+ time_t desired_delay;
+ bool desired_delay_is_set;
+};
+
+/** Table PERFORMANCE_SCHEMA.replication_applier_configuration */
+class table_replication_applier_configuration: public PFS_engine_table
+{
+ typedef PFS_simple_index pos_t;
+
+private:
+ void make_row(Master_info *mi);
+
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /** Fields definition. */
+ static TABLE_FIELD_DEF m_field_def;
+ /** Current row */
+ st_row_applier_config m_row;
+ /** True is the current row exists. */
+ bool m_row_exists;
+ /** Current position. */
+ pos_t m_pos;
+ /** Next position. */
+ pos_t m_next_pos;
+
+protected:
+ /**
+ Read the current row values.
+ @param table Table handle
+ @param buf row buffer
+ @param fields Table fields
+ @param read_all true if all columns are read.
+ */
+
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+
+ table_replication_applier_configuration();
+
+public:
+ ~table_replication_applier_configuration();
+
+ /** Table share. */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static ha_rows get_row_count();
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+};
+
+/** @} */
+#endif
diff --git a/storage/perfschema/table_replication_applier_status.cc b/storage/perfschema/table_replication_applier_status.cc
new file mode 100644
index 00000000000..b6d06ff442c
--- /dev/null
+++ b/storage/perfschema/table_replication_applier_status.cc
@@ -0,0 +1,219 @@
+/*
+ Copyright (c) 2013, 2018, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/**
+ @file storage/perfschema/table_replication_applier_status.cc
+ Table replication_applier_status (implementation).
+*/
+
+#define HAVE_REPLICATION
+
+#include "my_global.h"
+#include "table_replication_applier_status.h"
+#include "pfs_instr_class.h"
+#include "pfs_instr.h"
+#include "slave.h"
+//#include "rpl_info.h"
+#include "rpl_rli.h"
+#include "rpl_mi.h"
+#include "sql_parse.h"
+//#include "rpl_msr.h" /*Multi source replication */
+
+THR_LOCK table_replication_applier_status::m_table_lock;
+
+PFS_engine_table_share
+table_replication_applier_status::m_share=
+{
+ { C_STRING_WITH_LEN("replication_applier_status") },
+ &pfs_readonly_acl,
+ table_replication_applier_status::create,
+ NULL, /* write_row */
+ NULL, /* delete_all_rows */
+ table_replication_applier_status::get_row_count, /* records */
+ sizeof(pos_t), /* ref length */
+ &m_table_lock,
+ { C_STRING_WITH_LEN("CREATE TABLE replication_applier_status("
+ "CHANNEL_NAME CHAR(64) collate utf8_general_ci not null,"
+ "SERVICE_STATE ENUM('ON','OFF') not null,"
+ "REMAINING_DELAY INTEGER unsigned,"
+ "COUNT_TRANSACTIONS_RETRIES BIGINT unsigned not null)") },
+ false /* perpetual */
+};
+
+
+PFS_engine_table* table_replication_applier_status::create(void)
+{
+ return new table_replication_applier_status();
+}
+
+table_replication_applier_status::table_replication_applier_status()
+ : PFS_engine_table(&m_share, &m_pos),
+ m_row_exists(false), m_pos(0), m_next_pos(0)
+{}
+
+table_replication_applier_status::~table_replication_applier_status()
+{}
+
+void table_replication_applier_status::reset_position(void)
+{
+ m_pos.m_index= 0;
+ m_next_pos.m_index= 0;
+}
+
+ha_rows table_replication_applier_status::get_row_count()
+{
+ return master_info_index->master_info_hash.records;
+}
+
+
+int table_replication_applier_status::rnd_next(void)
+{
+ Master_info *mi;
+ mysql_mutex_lock(&LOCK_active_mi);
+
+ for (m_pos.set_at(&m_next_pos);
+ m_pos.m_index < master_info_index->master_info_hash.records;
+ m_pos.next())
+ {
+ mi= (Master_info *)my_hash_element(&master_info_index->master_info_hash, m_pos.m_index);
+
+ if (mi && mi->host[0])
+ {
+ make_row(mi);
+ m_next_pos.set_after(&m_pos);
+ mysql_mutex_unlock(&LOCK_active_mi);
+ return 0;
+ }
+ }
+
+ mysql_mutex_unlock(&LOCK_active_mi);
+ return HA_ERR_END_OF_FILE;
+}
+
+
+int table_replication_applier_status::rnd_pos(const void *pos)
+{
+ Master_info *mi=NULL;
+ int res= HA_ERR_RECORD_DELETED;
+
+ set_position(pos);
+
+ mysql_mutex_lock(&LOCK_active_mi);
+
+ if ((mi= (Master_info *)my_hash_element(&master_info_index->master_info_hash, m_pos.m_index)))
+ {
+ make_row(mi);
+ res= 0;
+ }
+
+ mysql_mutex_unlock(&LOCK_active_mi);
+ return res;
+}
+
+void table_replication_applier_status::make_row(Master_info *mi)
+{
+ char *slave_sql_running_state= NULL;
+
+ m_row_exists= false;
+
+ DBUG_ASSERT(mi != NULL);
+
+ m_row.channel_name_length= mi->connection_name.length;
+ memcpy(m_row.channel_name, mi->connection_name.str, m_row.channel_name_length);
+
+ //mysql_mutex_lock(&mi->rli->info_thd_lock);
+
+ slave_sql_running_state= const_cast<char *>
+ (mi->rli.sql_driver_thd ?
+ mi->rli.sql_driver_thd->get_proc_info() : "");
+ //mysql_mutex_unlock(&mi->rli->info_thd_lock);
+
+
+ mysql_mutex_lock(&mi->data_lock);
+ mysql_mutex_lock(&mi->rli.data_lock);
+
+ if (mi->rli.slave_running)
+ m_row.service_state= PS_RPL_YES;
+ else
+ m_row.service_state= PS_RPL_NO;
+
+ m_row.remaining_delay= 0;
+ if (slave_sql_running_state == stage_sql_thd_waiting_until_delay.m_name)
+ {
+ time_t t= my_time(0), sql_delay_end= 0; //mi->rli.>get_sql_delay_end();
+ m_row.remaining_delay= (uint)(t < sql_delay_end ?
+ sql_delay_end - t : 0);
+ m_row.remaining_delay_is_set= true;
+ }
+ else
+ m_row.remaining_delay_is_set= false;
+
+ m_row.count_transactions_retries= mi->rli.retried_trans;
+
+ mysql_mutex_unlock(&mi->rli.data_lock);
+ mysql_mutex_unlock(&mi->data_lock);
+
+ m_row_exists= true;
+}
+
+int table_replication_applier_status::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;
+
+ 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 0: /**channel_name*/
+ set_field_char_utf8(f, m_row.channel_name, m_row.channel_name_length);
+ break;
+ case 1: /* service_state */
+ set_field_enum(f, m_row.service_state);
+ break;
+ case 2: /* remaining_delay */
+ if (m_row.remaining_delay_is_set)
+ set_field_ulong(f, m_row.remaining_delay);
+ else
+ f->set_null();
+ break;
+ case 3: /* total number of times transactions were retried */
+ set_field_ulonglong(f, m_row.count_transactions_retries);
+ break;
+ default:
+ DBUG_ASSERT(false);
+ }
+ }
+ }
+ return 0;
+}
diff --git a/storage/perfschema/table_replication_applier_status.h b/storage/perfschema/table_replication_applier_status.h
new file mode 100644
index 00000000000..95845f38925
--- /dev/null
+++ b/storage/perfschema/table_replication_applier_status.h
@@ -0,0 +1,118 @@
+/*
+ Copyright (c) 2013, 2018, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+
+#ifndef TABLE_REPLICATION_APPLIER_STATUS_H
+#define TABLE_REPLICATION_APPLIER_STATUS_H
+
+/**
+ @file storage/perfschema/table_replication_applier_status.h
+ Table replication_applier_status (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "rpl_mi.h"
+#include "mysql_com.h"
+//#include "rpl_msr.h"
+//#include "rpl_info.h" /*CHANNEL_NAME_LENGTH*/
+#include "my_thread.h"
+
+class Master_info;
+
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+#ifndef ENUM_RPL_YES_NO
+#define ENUM_RPL_YES_NO
+/** enum values for Service_State field*/
+enum enum_rpl_yes_no {
+ PS_RPL_YES= 1,
+ PS_RPL_NO
+};
+#endif
+
+/** A row in the table. */
+struct st_row_applier_status {
+ char channel_name[CHANNEL_NAME_LENGTH];
+ uint channel_name_length;
+ enum_rpl_yes_no service_state;
+ uint remaining_delay;
+ bool remaining_delay_is_set;
+ ulong count_transactions_retries;
+};
+
+/** Table PERFORMANCE_SCHEMA.replication_applier_status */
+class table_replication_applier_status: public PFS_engine_table
+{
+ typedef PFS_simple_index pos_t;
+
+private:
+ void make_row(Master_info *mi);
+
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /** Fields definition. */
+ static TABLE_FIELD_DEF m_field_def;
+ /** Current row */
+ st_row_applier_status m_row;
+ /** True is the current row exists. */
+ bool m_row_exists;
+ /** Current position. */
+ pos_t m_pos;
+ /** Next position. */
+ pos_t m_next_pos;
+
+protected:
+ /**
+ Read the current row values.
+ @param table Table handle
+ @param buf row buffer
+ @param fields Table fields
+ @param read_all true if all columns are read.
+ */
+
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+
+ table_replication_applier_status();
+
+public:
+ ~table_replication_applier_status();
+
+ /** Table share. */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static ha_rows get_row_count();
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+};
+
+/** @} */
+#endif
diff --git a/storage/perfschema/table_replication_applier_status_by_coordinator.cc b/storage/perfschema/table_replication_applier_status_by_coordinator.cc
new file mode 100644
index 00000000000..5201bdc6de8
--- /dev/null
+++ b/storage/perfschema/table_replication_applier_status_by_coordinator.cc
@@ -0,0 +1,246 @@
+/*
+ Copyright (c) 2013, 2018, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/**
+ @file storage/perfschema/table_replication_applier_status_by_cordinator.cc
+ Table replication_applier_status_by_coordinator (implementation).
+*/
+
+#define HAVE_REPLICATION
+
+#include "my_global.h"
+#include "table_replication_applier_status_by_coordinator.h"
+#include "pfs_instr_class.h"
+#include "pfs_instr.h"
+#include "slave.h"
+//#include "rpl_info.h"
+#include "rpl_rli.h"
+#include "rpl_mi.h"
+#include "sql_parse.h"
+//#include "rpl_msr.h" /* Multisource replication */
+
+THR_LOCK table_replication_applier_status_by_coordinator::m_table_lock;
+
+PFS_engine_table_share
+table_replication_applier_status_by_coordinator::m_share=
+{
+ { C_STRING_WITH_LEN("replication_applier_status_by_coordinator") },
+ &pfs_readonly_acl,
+ table_replication_applier_status_by_coordinator::create,
+ NULL, /* write_row */
+ NULL, /* delete_all_rows */
+ table_replication_applier_status_by_coordinator::get_row_count,
+ sizeof(pos_t), /* ref length */
+ &m_table_lock,
+ { C_STRING_WITH_LEN("CREATE TABLE replication_applier_status_by_coordinator("
+ "CHANNEL_NAME CHAR(64) collate utf8_general_ci not null,"
+ "THREAD_ID BIGINT UNSIGNED,"
+ "SERVICE_STATE ENUM('ON','OFF') not null,"
+ "LAST_ERROR_NUMBER INTEGER not null,"
+ "LAST_ERROR_MESSAGE VARCHAR(1024) not null,"
+ "LAST_ERROR_TIMESTAMP TIMESTAMP(0) not null)") },
+ false /* perpetual */
+};
+
+PFS_engine_table* table_replication_applier_status_by_coordinator::create(void)
+{
+ return new table_replication_applier_status_by_coordinator();
+}
+
+table_replication_applier_status_by_coordinator
+ ::table_replication_applier_status_by_coordinator()
+ : PFS_engine_table(&m_share, &m_pos),
+ m_row_exists(false), m_pos(0), m_next_pos(0)
+{}
+
+table_replication_applier_status_by_coordinator
+ ::~table_replication_applier_status_by_coordinator()
+{}
+
+void table_replication_applier_status_by_coordinator::reset_position(void)
+{
+ m_pos.m_index= 0;
+ m_next_pos.m_index= 0;
+}
+
+ha_rows table_replication_applier_status_by_coordinator::get_row_count()
+{
+ return master_info_index->master_info_hash.records;
+}
+
+
+int table_replication_applier_status_by_coordinator::rnd_next(void)
+{
+ Master_info *mi;
+
+ mysql_mutex_lock(&LOCK_active_mi);
+
+
+ for (m_pos.set_at(&m_next_pos);
+ m_pos.m_index < master_info_index->master_info_hash.records;
+ m_pos.next())
+ {
+ mi= (Master_info *)my_hash_element(&master_info_index->master_info_hash, m_pos.m_index);
+
+ /*
+ Construct and display SQL Thread's (Coordinator) information in
+ 'replication_applier_status_by_coordinator' table only in the case of
+ multi threaded slave mode. Code should do nothing in the case of single
+ threaded slave mode. In case of single threaded slave mode SQL Thread's
+ status will be reported as part of
+ 'replication_applier_status_by_worker' table.
+ */
+ if (mi && mi->host[0] && /*mi->rli.get_worker_count() > */ 0)
+ {
+ make_row(mi);
+ m_next_pos.set_after(&m_pos);
+ channel_map.unlock();
+ return 0;
+ }
+ }
+
+ mysql_mutex_unlock(&LOCK_active_mi);
+ return HA_ERR_END_OF_FILE;
+}
+
+int table_replication_applier_status_by_coordinator::rnd_pos(const void *pos)
+{
+ Master_info *mi=NULL;
+ int res= HA_ERR_RECORD_DELETED;
+
+ set_position(pos);
+
+ mysql_mutex_lock(&LOCK_active_mi);
+
+ if ((mi= (Master_info *)my_hash_element(&master_info_index->master_info_hash, m_pos.m_index)))
+ {
+ make_row(mi);
+ res= 0;
+ }
+
+ mysql_mutex_unlock(&LOCK_active_mi);
+ return res;
+}
+
+void table_replication_applier_status_by_coordinator::make_row(Master_info *mi)
+{
+ m_row_exists= false;
+
+ DBUG_ASSERT(mi != NULL);
+
+ mysql_mutex_lock(&mi->rli.data_lock);
+
+ m_row.channel_name_length= mi->connection_name.length;
+ memcpy(m_row.channel_name, mi->connection_name.str, m_row.channel_name_length);
+
+ if (mi->rli.slave_running)
+ {
+ PSI_thread *psi= thd_get_psi(mi->rli.sql_driver_thd);
+ PFS_thread *pfs= reinterpret_cast<PFS_thread *> (psi);
+ if(pfs)
+ {
+ m_row.thread_id= pfs->m_thread_internal_id;
+ m_row.thread_id_is_null= false;
+ }
+ else
+ m_row.thread_id_is_null= true;
+ }
+ else
+ m_row.thread_id_is_null= true;
+
+ if (mi->rli.slave_running)
+ m_row.service_state= PS_RPL_YES;
+ else
+ m_row.service_state= PS_RPL_NO;
+
+ mysql_mutex_lock(&mi->rli.err_lock);
+
+ m_row.last_error_number= (long int) mi->rli.last_error().number;
+ m_row.last_error_message_length= 0;
+ m_row.last_error_timestamp= 0;
+
+ /** if error, set error message and timestamp */
+ if (m_row.last_error_number)
+ {
+ char *temp_store= (char*) mi->rli.last_error().message;
+ m_row.last_error_message_length= strlen(temp_store);
+ memcpy(m_row.last_error_message, temp_store,
+ m_row.last_error_message_length);
+
+ /** time in millisecond since epoch */
+ m_row.last_error_timestamp= 0;//(ulonglong)mi->rli.last_error().skr*1000000;
+ }
+
+ mysql_mutex_unlock(&mi->rli.err_lock);
+ mysql_mutex_unlock(&mi->rli.data_lock);
+
+ m_row_exists= true;
+}
+
+int table_replication_applier_status_by_coordinator
+ ::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;
+
+ 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 0: /* channel_name */
+ set_field_char_utf8(f, m_row.channel_name, m_row.channel_name_length);
+ break;
+ case 1: /*thread_id*/
+ if (!m_row.thread_id_is_null)
+ set_field_ulonglong(f, m_row.thread_id);
+ else
+ f->set_null();
+ break;
+ case 2: /*service_state*/
+ set_field_enum(f, m_row.service_state);
+ break;
+ case 3: /*last_error_number*/
+ set_field_ulong(f, m_row.last_error_number);
+ break;
+ case 4: /*last_error_message*/
+ set_field_varchar_utf8(f, m_row.last_error_message,
+ m_row.last_error_message_length);
+ break;
+ case 5: /*last_error_timestamp*/
+ set_field_timestamp(f, m_row.last_error_timestamp);
+ break;
+ default:
+ DBUG_ASSERT(false);
+ }
+ }
+ }
+ return 0;
+}
diff --git a/storage/perfschema/table_replication_applier_status_by_coordinator.h b/storage/perfschema/table_replication_applier_status_by_coordinator.h
new file mode 100644
index 00000000000..8c1d4c4f029
--- /dev/null
+++ b/storage/perfschema/table_replication_applier_status_by_coordinator.h
@@ -0,0 +1,124 @@
+/*
+ Copyright (c) 2013, 2018, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+
+#ifndef TABLE_REPLICATION_APPLIER_STATUS_BY_COORDINATOR_H
+#define TABLE_REPLICATION_APPLIER_STATUS_BY_COORDINATOR_H
+
+/**
+ @file storage/perfschema/table_replication_applier_applier_by_coordinator.h
+ Table replication_applier_status_by_coordinator(declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "rpl_mi.h"
+#include "mysql_com.h"
+//#include "rpl_msr.h"
+//#include "rpl_info.h" /*CHANNEL_NAME_LENGTH*/
+#include "my_thread.h"
+
+class Master_info;
+
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+#ifndef ENUM_RPL_YES_NO
+#define ENUM_RPL_YES_NO
+/** enum values for Service_State of coordinator thread */
+enum enum_rpl_yes_no {
+ PS_RPL_YES= 1, /* Service_State= on */
+ PS_RPL_NO /* Service_State= off */
+};
+#endif
+
+/*
+ A row in coordinator's table. The fields with string values have an
+ additional length field denoted by <field_name>_length.
+*/
+struct st_row_coordinator {
+ char channel_name[CHANNEL_NAME_LENGTH];
+ uint channel_name_length;
+ ulonglong thread_id;
+ bool thread_id_is_null;
+ enum_rpl_yes_no service_state;
+ uint last_error_number;
+ char last_error_message[MAX_SLAVE_ERRMSG];
+ uint last_error_message_length;
+ ulonglong last_error_timestamp;
+};
+
+/** Table PERFORMANCE_SCHEMA.replication_applier_status_by_coordinator */
+class table_replication_applier_status_by_coordinator: public PFS_engine_table
+{
+ typedef PFS_simple_index pos_t;
+
+private:
+ void make_row(Master_info *mi);
+
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /** Fields definition. */
+ static TABLE_FIELD_DEF m_field_def;
+ /** Current row */
+ st_row_coordinator m_row;
+ /** True is the current row exists. */
+ bool m_row_exists;
+ /** Current position. */
+ pos_t m_pos;
+ /** Next position. */
+ pos_t m_next_pos;
+
+protected:
+ /**
+ Read the current row values.
+ @param table Table handle
+ @param buf row buffer
+ @param fields Table fields
+ @param read_all true if all columns are read.
+ */
+
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+
+ table_replication_applier_status_by_coordinator();
+
+public:
+ ~table_replication_applier_status_by_coordinator();
+
+ /** Table share. */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static ha_rows get_row_count();
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+};
+
+/** @} */
+#endif
diff --git a/storage/perfschema/table_replication_applier_status_by_worker.cc b/storage/perfschema/table_replication_applier_status_by_worker.cc
new file mode 100644
index 00000000000..65a1e277805
--- /dev/null
+++ b/storage/perfschema/table_replication_applier_status_by_worker.cc
@@ -0,0 +1,412 @@
+/*
+ Copyright (c) 2013, 2018, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/**
+ @file storage/perfschema/table_replication_applier_status_by_worker.cc
+ Table replication_applier_status_by_worker (implementation).
+*/
+
+#define HAVE_REPLICATION
+
+#include "my_global.h"
+#include "table_replication_applier_status_by_worker.h"
+#include "pfs_instr_class.h"
+#include "pfs_instr.h"
+#include "slave.h"
+//#include "rpl_info.h"
+#include "rpl_rli.h"
+#include "rpl_mi.h"
+#include "sql_parse.h"
+//#include "rpl_rli_pdb.h"
+//#include "rpl_msr.h" /*Multi source replication */
+
+THR_LOCK table_replication_applier_status_by_worker::m_table_lock;
+
+PFS_engine_table_share
+table_replication_applier_status_by_worker::m_share=
+{
+ { C_STRING_WITH_LEN("replication_applier_status_by_worker") },
+ &pfs_readonly_acl,
+ table_replication_applier_status_by_worker::create,
+ NULL, /* write_row */
+ NULL, /* delete_all_rows */
+ table_replication_applier_status_by_worker::get_row_count, /*records*/
+ sizeof(pos_t), /* ref length */
+ &m_table_lock,
+ { C_STRING_WITH_LEN("CREATE TABLE replication_applier_status_by_worker("
+ "CHANNEL_NAME CHAR(64) collate utf8_general_ci not null,"
+ "WORKER_ID BIGINT UNSIGNED not null,"
+ "THREAD_ID BIGINT UNSIGNED,"
+ "SERVICE_STATE ENUM('ON','OFF') not null,"
+ "LAST_SEEN_TRANSACTION CHAR(57) not null,"
+ "LAST_ERROR_NUMBER INTEGER not null,"
+ "LAST_ERROR_MESSAGE VARCHAR(1024) not null,"
+ "LAST_ERROR_TIMESTAMP TIMESTAMP(0) not null)") },
+ false /* perpetual */
+};
+
+PFS_engine_table* table_replication_applier_status_by_worker::create(void)
+{
+ return new table_replication_applier_status_by_worker();
+}
+
+table_replication_applier_status_by_worker
+ ::table_replication_applier_status_by_worker()
+ : PFS_engine_table(&m_share, &m_pos),
+ m_row_exists(false), m_pos(), m_next_pos()
+{}
+
+table_replication_applier_status_by_worker
+ ::~table_replication_applier_status_by_worker()
+{}
+
+void table_replication_applier_status_by_worker::reset_position(void)
+{
+ m_pos.reset();
+ m_next_pos.reset();
+}
+
+ha_rows table_replication_applier_status_by_worker::get_row_count()
+{
+ /*
+ Return an estimate, number of master info's multipled by worker threads
+ */
+ return master_info_index->master_info_hash.records*32;
+}
+
+
+int table_replication_applier_status_by_worker::rnd_next(void)
+{
+ Slave_worker *worker;
+ Master_info *mi;
+ size_t wc;
+
+ mysql_mutex_lock(&LOCK_active_mi);
+
+ for (m_pos.set_at(&m_next_pos);
+ m_pos.has_more_channels(master_info_index->master_info_hash.records);
+ m_pos.next_channel())
+ {
+ mi= (Master_info *)my_hash_element(&master_info_index->master_info_hash, m_pos.m_index_1);
+
+ if (mi && mi->host[0])
+ {
+ wc= mi->rli->get_worker_count();
+
+ if (wc == 0)
+ {
+ /* Single Thread Slave */
+ make_row(mi);
+ m_next_pos.set_channel_after(&m_pos);
+ channel_map.unlock();
+ return 0;
+ }
+
+ for (; m_pos.m_index_2 < wc; m_pos.next_worker())
+ {
+ /* Multi Thread Slave */
+
+ worker = mi->rli->get_worker(m_pos.m_index_2);
+ if (worker)
+ {
+ make_row(worker);
+ m_next_pos.set_after(&m_pos);
+ channel_map.unlock();
+ return 0;
+ }
+ }
+ }
+ }
+
+ mysql_mutex_unlock(&LOCK_active_mi);
+ return HA_ERR_END_OF_FILE;
+}
+
+int table_replication_applier_status_by_worker::rnd_pos(const void *pos)
+{
+ Slave_worker *worker;
+ Master_info *mi;
+ int res= HA_ERR_RECORD_DELETED;
+ size_t wc;
+
+ set_position(pos);
+
+ mysql_mutex_lock(&LOCK_active_mi);
+
+ mi= (Master_info *)my_hash_element(&master_info_index->master_info_hash, m_pos.m_index_1);
+
+ if (!mi || !mi->host[0])
+ goto end;
+
+ wc = mi->rli->get_worker_count();
+
+ if (wc == 0)
+ {
+ /* Single Thread Slave */
+ make_row(mi);
+ res=0;
+ }
+ else
+ {
+ /* Multi Thread Slave */
+ if (m_pos.m_index_2 < wc)
+ {
+ worker = mi->rli->get_worker(m_pos.m_index_2);
+ if (worker != NULL)
+ {
+ make_row(worker);
+ res=0;
+ }
+ }
+ }
+
+end:
+ mysql_mutex_unlock(&LOCK_active_mi);
+ return res;
+}
+
+/**
+ Function to display SQL Thread's status as part of
+ 'replication_applier_status_by_worker' in single threaded slave mode.
+
+ @param[in] Master_info
+
+ @retval void
+*/
+void table_replication_applier_status_by_worker::make_row(Master_info *mi)
+{
+ m_row_exists= false;
+
+ m_row.worker_id= 0;
+
+ m_row.thread_id= 0;
+
+ DBUG_ASSERT(mi != NULL);
+ DBUG_ASSERT(mi->rli != NULL);
+
+ mysql_mutex_lock(&mi->rli->data_lock);
+
+ m_row.channel_name_length= strlen(mi->get_channel());
+ memcpy(m_row.channel_name, (char*)mi->get_channel(), m_row.channel_name_length);
+
+ if (mi->rli->slave_running)
+ {
+ PSI_thread *psi= thd_get_psi(mi->rli->info_thd);
+ PFS_thread *pfs= reinterpret_cast<PFS_thread *> (psi);
+ if(pfs)
+ {
+ m_row.thread_id= pfs->m_thread_internal_id;
+ m_row.thread_id_is_null= false;
+ }
+ else
+ m_row.thread_id_is_null= true;
+ }
+ else
+ m_row.thread_id_is_null= true;
+
+ if (mi->rli->slave_running)
+ m_row.service_state= PS_RPL_YES;
+ else
+ m_row.service_state= PS_RPL_NO;
+
+ if (mi->rli->currently_executing_gtid.type == GTID_GROUP)
+ {
+ global_sid_lock->rdlock();
+ m_row.last_seen_transaction_length=
+ mi->rli->currently_executing_gtid.to_string(global_sid_map,
+ m_row.last_seen_transaction);
+ global_sid_lock->unlock();
+ }
+ else if (mi->rli->currently_executing_gtid.type == ANONYMOUS_GROUP)
+ {
+ m_row.last_seen_transaction_length=
+ mi->rli->currently_executing_gtid.to_string((rpl_sid *)NULL,
+ m_row.last_seen_transaction);
+ }
+ else
+ {
+ /*
+ For SQL thread currently_executing_gtid, type is set to
+ AUTOMATIC_GROUP when the SQL thread is not executing any
+ transaction. For this case, the field should be empty.
+ */
+ DBUG_ASSERT(mi->rli->currently_executing_gtid.type == AUTOMATIC_GROUP);
+ m_row.last_seen_transaction_length= 0;
+ memcpy(m_row.last_seen_transaction, "", 1);
+ }
+
+ mysql_mutex_lock(&mi->rli->err_lock);
+
+ m_row.last_error_number= (long int) mi->rli->last_error().number;
+ m_row.last_error_message_length= 0;
+ m_row.last_error_timestamp= 0;
+
+ /** if error, set error message and timestamp */
+ if (m_row.last_error_number)
+ {
+ char *temp_store= (char*) mi->rli->last_error().message;
+ m_row.last_error_message_length= strlen(temp_store);
+ memcpy(m_row.last_error_message, temp_store,
+ m_row.last_error_message_length);
+
+ /** time in millisecond since epoch */
+ m_row.last_error_timestamp= (ulonglong)mi->rli->last_error().skr*1000000;
+ }
+
+ mysql_mutex_unlock(&mi->rli->err_lock);
+ mysql_mutex_unlock(&mi->rli->data_lock);
+ m_row_exists= true;
+}
+
+void table_replication_applier_status_by_worker::make_row(Slave_worker *w)
+{
+ m_row_exists= false;
+
+ m_row.worker_id= w->get_internal_id();
+
+ m_row.thread_id= 0;
+
+ m_row.channel_name_length= strlen(w->get_channel());
+ memcpy(m_row.channel_name, (char*)w->get_channel(), m_row.channel_name_length);
+
+ mysql_mutex_lock(&w->jobs_lock);
+ if (w->running_status == Slave_worker::RUNNING)
+ {
+ PSI_thread *psi= thd_get_psi(w->info_thd);
+ PFS_thread *pfs= reinterpret_cast<PFS_thread *> (psi);
+ if(pfs)
+ {
+ m_row.thread_id= pfs->m_thread_internal_id;
+ m_row.thread_id_is_null= false;
+ }
+ else /* no instrumentation found */
+ m_row.thread_id_is_null= true;
+ }
+ else
+ m_row.thread_id_is_null= true;
+
+ if (w->running_status == Slave_worker::RUNNING)
+ m_row.service_state= PS_RPL_YES;
+ else
+ m_row.service_state= PS_RPL_NO;
+
+ m_row.last_error_number= (unsigned int) w->last_error().number;
+
+ if (w->currently_executing_gtid.type == GTID_GROUP)
+ {
+ global_sid_lock->rdlock();
+ m_row.last_seen_transaction_length=
+ w->currently_executing_gtid.to_string(global_sid_map,
+ m_row.last_seen_transaction);
+ global_sid_lock->unlock();
+ }
+ else if (w->currently_executing_gtid.type == ANONYMOUS_GROUP)
+ {
+ m_row.last_seen_transaction_length=
+ w->currently_executing_gtid.to_string((rpl_sid *)NULL,
+ m_row.last_seen_transaction);
+ }
+ else
+ {
+ /*
+ For worker->currently_executing_gtid, type is set to
+ AUTOMATIC_GROUP when the worker is not executing any
+ transaction. For this case, the field should be empty.
+ */
+ DBUG_ASSERT(w->currently_executing_gtid.type == AUTOMATIC_GROUP);
+ m_row.last_seen_transaction_length= 0;
+ memcpy(m_row.last_seen_transaction, "", 1);
+ }
+
+ m_row.last_error_number= (unsigned int) w->last_error().number;
+ m_row.last_error_message_length= 0;
+ m_row.last_error_timestamp= 0;
+
+ /** if error, set error message and timestamp */
+ if (m_row.last_error_number)
+ {
+ char * temp_store= (char*)w->last_error().message;
+ m_row.last_error_message_length= strlen(temp_store);
+ memcpy(m_row.last_error_message, w->last_error().message,
+ m_row.last_error_message_length);
+
+ /** time in millisecond since epoch */
+ m_row.last_error_timestamp= (ulonglong)w->last_error().skr*1000000;
+ }
+ mysql_mutex_unlock(&w->jobs_lock);
+
+ m_row_exists= true;
+}
+
+int table_replication_applier_status_by_worker
+ ::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;
+
+ 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 0: /** channel_name */
+ set_field_char_utf8(f, m_row.channel_name, m_row.channel_name_length);
+ break;
+ case 1: /*worker_id*/
+ set_field_ulonglong(f, m_row.worker_id);
+ break;
+ case 2: /*thread_id*/
+ if(m_row.thread_id_is_null)
+ f->set_null();
+ else
+ set_field_ulonglong(f, m_row.thread_id);
+ break;
+ case 3: /*service_state*/
+ set_field_enum(f, m_row.service_state);
+ break;
+ case 4: /*last_seen_transaction*/
+ set_field_char_utf8(f, m_row.last_seen_transaction, m_row.last_seen_transaction_length);
+ break;
+ case 5: /*last_error_number*/
+ set_field_ulong(f, m_row.last_error_number);
+ break;
+ case 6: /*last_error_message*/
+ set_field_varchar_utf8(f, m_row.last_error_message, m_row.last_error_message_length);
+ break;
+ case 7: /*last_error_timestamp*/
+ set_field_timestamp(f, m_row.last_error_timestamp);
+ break;
+ default:
+ DBUG_ASSERT(false);
+ }
+ }
+ }
+ return 0;
+}
diff --git a/storage/perfschema/table_replication_applier_status_by_worker.h b/storage/perfschema/table_replication_applier_status_by_worker.h
new file mode 100644
index 00000000000..0a881dae73f
--- /dev/null
+++ b/storage/perfschema/table_replication_applier_status_by_worker.h
@@ -0,0 +1,182 @@
+/*
+ Copyright (c) 2013, 2018, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+
+#ifndef TABLE_REPLICATION_APPLIER_STATUS_BY_WORKER_H
+#define TABLE_REPLICATION_APPLIER_STATUS_BY_WORKER_H
+
+/**
+ @file storage/perfschema/table_replication_applier_status_by_worker.h
+ Table replication_applier_status_by_worker (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "rpl_mi.h"
+#include "mysql_com.h"
+//#include "rpl_rli_pdb.h"
+//#include "rpl_msr.h"
+//#include "rpl_info.h" /*CHANNEL_NAME_LENGTH*/
+#include "my_thread.h"
+
+class Slave_worker;
+class Master_info;
+
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+#ifndef ENUM_RPL_YES_NO
+#define ENUM_RPL_YES_NO
+/** enumerated values for service_state of worker thread*/
+enum enum_rpl_yes_no {
+ PS_RPL_YES= 1, /* service_state= on */
+ PS_RPL_NO /* service_state= off */
+};
+#endif
+
+/*
+ A row in worker's table. The fields with string values have an additional
+ length field denoted by <field_name>_length.
+*/
+struct st_row_worker {
+
+ char channel_name[CHANNEL_NAME_LENGTH];
+ uint channel_name_length;
+ /*
+ worker_id is added to the table because thread is killed at STOP SLAVE
+ but the status needs to show up, so worker_id is used as a permanent
+ identifier.
+ */
+ ulonglong worker_id;
+ ulonglong thread_id;
+ uint thread_id_is_null;
+ enum_rpl_yes_no service_state;
+ char last_seen_transaction[GTID_MAX_STR_LENGTH + 1];
+ uint last_seen_transaction_length;
+ uint last_error_number;
+ char last_error_message[MAX_SLAVE_ERRMSG];
+ uint last_error_message_length;
+ ulonglong last_error_timestamp;
+};
+
+/**
+ Position in table replication_applier_status_by_worker.
+ Index 1 for replication channel.
+ Index 2 for worker:
+ - position [0] is for Single Thread Slave (Master_info)
+ - position [1] .. [N] is for Multi Thread Slave (Slave_worker)
+*/
+struct pos_replication_applier_status_by_worker : public PFS_double_index
+{
+
+ pos_replication_applier_status_by_worker() : PFS_double_index(0, 0)
+ {}
+
+ inline void reset(void)
+ {
+ m_index_1= 0;
+ m_index_2= 0;
+ }
+
+ inline bool has_more_channels(uint num)
+ { return (m_index_1 < num); }
+
+ inline void next_channel(void)
+ {
+ m_index_1++;
+ m_index_2= 0;
+ }
+
+ inline void next_worker()
+ {
+ m_index_2++;
+ }
+
+ inline void
+ set_channel_after(const pos_replication_applier_status_by_worker *other)
+ {
+ m_index_1 = other->m_index_1 + 1;
+ m_index_2 = 0;
+ }
+};
+
+
+/** Table PERFORMANCE_SCHEMA.replication_applier_status_by_worker */
+class table_replication_applier_status_by_worker: public PFS_engine_table
+{
+ typedef pos_replication_applier_status_by_worker pos_t;
+
+private:
+ void make_row(Slave_worker *);
+ /*
+ Master_info to construct a row to display SQL Thread's status
+ information in STS mode
+ */
+ void make_row(Master_info *);
+
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /** Fields definition. */
+ static TABLE_FIELD_DEF m_field_def;
+ /** current row*/
+ st_row_worker m_row;
+ /** True is the current row exists. */
+ bool m_row_exists;
+ /** Current position. */
+ pos_t m_pos;
+ /** Next position. */
+ pos_t m_next_pos;
+
+protected:
+ /**
+ Read the current row values.
+ @param table Table handle
+ @param buf row buffer
+ @param fields Table fields
+ @param read_all true if all columns are read.
+ */
+
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+
+ table_replication_applier_status_by_worker();
+
+public:
+ ~table_replication_applier_status_by_worker();
+
+ /** Table share. */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static ha_rows get_row_count();
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+};
+
+/** @} */
+#endif
diff --git a/storage/perfschema/table_replication_connection_configuration.cc b/storage/perfschema/table_replication_connection_configuration.cc
new file mode 100644
index 00000000000..219d6b8259c
--- /dev/null
+++ b/storage/perfschema/table_replication_connection_configuration.cc
@@ -0,0 +1,331 @@
+/*
+ Copyright (c) 2013, 2018, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/**
+ @file storage/perfschema/table_replication_connection_configuration.cc
+ Table replication_connection_configuration (implementation).
+*/
+
+#define HAVE_REPLICATION
+
+#include "my_global.h"
+#include "table_replication_connection_configuration.h"
+#include "pfs_instr_class.h"
+#include "pfs_instr.h"
+#include "slave.h"
+//#include "rpl_info.h"
+#include "rpl_rli.h"
+#include "rpl_mi.h"
+#include "sql_parse.h"
+//#include "rpl_msr.h" /* Multisource replciation */
+
+THR_LOCK table_replication_connection_configuration::m_table_lock;
+
+PFS_engine_table_share
+table_replication_connection_configuration::m_share=
+{
+ { C_STRING_WITH_LEN("replication_connection_configuration") },
+ &pfs_readonly_acl,
+ table_replication_connection_configuration::create,
+ NULL, /* write_row */
+ NULL, /* delete_all_rows */
+ table_replication_connection_configuration::get_row_count, /* records */
+ sizeof(pos_t), /* ref length */
+ &m_table_lock,
+ { C_STRING_WITH_LEN("CREATE TABLE replication_connection_configuration("
+ "CHANNEL_NAME CHAR(64) collate utf8_general_ci not null,"
+ "HOST CHAR(60) collate utf8_bin not null,"
+ "PORT INTEGER not null,"
+ "USER CHAR(32) collate utf8_bin not null,"
+ "NETWORK_INTERFACE CHAR(60) collate utf8_bin not null,"
+ "AUTO_POSITION ENUM('1','0') not null,"
+ "SSL_ALLOWED ENUM('YES','NO','IGNORED') not null,"
+ "SSL_CA_FILE VARCHAR(512) not null,"
+ "SSL_CA_PATH VARCHAR(512) not null,"
+ "SSL_CERTIFICATE VARCHAR(512) not null,"
+ "SSL_CIPHER VARCHAR(512) not null,"
+ "SSL_KEY VARCHAR(512) not null,"
+ "SSL_VERIFY_SERVER_CERTIFICATE ENUM('YES','NO') not null,"
+ "SSL_CRL_FILE VARCHAR(255) not null,"
+ "SSL_CRL_PATH VARCHAR(255) not null,"
+ "CONNECTION_RETRY_INTERVAL INTEGER not null,"
+ "CONNECTION_RETRY_COUNT BIGINT unsigned not null,"
+ "HEARTBEAT_INTERVAL DOUBLE(10,3) unsigned not null COMMENT 'Number of seconds after which a heartbeat will be sent .',"
+ "TLS_VERSION VARCHAR(255) not null)") },
+ false /* perpetual */
+};
+
+
+PFS_engine_table* table_replication_connection_configuration::create(void)
+{
+ return new table_replication_connection_configuration();
+}
+
+table_replication_connection_configuration
+ ::table_replication_connection_configuration()
+ : PFS_engine_table(&m_share, &m_pos),
+ m_row_exists(false), m_pos(0), m_next_pos(0)
+{}
+
+table_replication_connection_configuration
+ ::~table_replication_connection_configuration()
+{}
+
+void table_replication_connection_configuration::reset_position(void)
+{
+ m_pos.m_index= 0;
+ m_next_pos.m_index= 0;
+}
+
+ha_rows table_replication_connection_configuration::get_row_count()
+{
+ /*
+ We actually give the MAX_CHANNELS rather than the current
+ number of channels
+ */
+
+ return master_info_index->master_info_hash.records;
+}
+
+int table_replication_connection_configuration::rnd_next(void)
+{
+ Master_info *mi;
+
+ mysql_mutex_lock(&LOCK_active_mi);
+
+ for (m_pos.set_at(&m_next_pos);
+ m_pos.m_index < master_info_index->master_info_hash.records;
+ m_pos.next())
+ {
+ mi= (Master_info *)my_hash_element(&master_info_index->master_info_hash, m_pos.m_index);
+
+ if (mi && mi->host[0])
+ {
+ make_row(mi);
+ m_next_pos.set_after(&m_pos);
+ channel_map.unlock();
+ return 0;
+ }
+ }
+
+ mysql_mutex_unlock(&LOCK_active_mi);
+ return HA_ERR_END_OF_FILE;
+}
+
+int table_replication_connection_configuration::rnd_pos(const void *pos)
+{
+ Master_info *mi;
+ int res= HA_ERR_RECORD_DELETED;
+
+ mysql_mutex_lock(&LOCK_active_mi);
+
+ set_position(pos);
+
+ if ((mi= (Master_info *)my_hash_element(&master_info_index->master_info_hash, m_pos.m_index)))
+ {
+ make_row(mi);
+ res= 0;
+ }
+
+ mysql_mutex_unlock(&LOCK_active_mi);
+ return res;
+}
+
+void table_replication_connection_configuration::make_row(Master_info *mi)
+{
+ char * temp_store;
+
+ m_row_exists= false;
+
+
+ DBUG_ASSERT(mi != NULL);
+
+ mysql_mutex_lock(&mi->data_lock);
+ mysql_mutex_lock(&mi->rli.data_lock);
+
+ m_row.channel_name_length= mi->connection_name.length;
+ memcpy(m_row.channel_name, mi->connection_name.str, m_row.channel_name_length);
+
+ m_row.host_length= strlen(mi->host);
+ memcpy(m_row.host, mi->host, m_row.host_length);
+
+ m_row.port= (unsigned int) mi->port;
+
+ /* can't the user be NULL? */
+ temp_store= (char*)mi->user;
+ m_row.user_length= strlen(temp_store);
+ memcpy(m_row.user, temp_store, m_row.user_length);
+
+ temp_store= const_cast<char*>(""); //(char*)mi->bind_addr;
+ m_row.network_interface_length= strlen(temp_store);
+ memcpy(m_row.network_interface, temp_store, m_row.network_interface_length);
+
+ if (mi->using_gtid)
+ m_row.auto_position= PS_RPL_YES;
+ else
+ m_row.auto_position= PS_RPL_NO;
+
+#ifdef HAVE_OPENSSL
+ m_row.ssl_allowed= mi->ssl? PS_SSL_ALLOWED_YES:PS_SSL_ALLOWED_NO;
+#else
+ m_row.ssl_allowed= mi->ssl? PS_SSL_ALLOWED_IGNORED:PS_SSL_ALLOWED_NO;
+#endif
+
+ temp_store= (char*)mi->ssl_ca;
+ m_row.ssl_ca_file_length= strlen(temp_store);
+ memcpy(m_row.ssl_ca_file, temp_store, m_row.ssl_ca_file_length);
+
+ temp_store= (char*)mi->ssl_capath;
+ m_row.ssl_ca_path_length= strlen(temp_store);
+ memcpy(m_row.ssl_ca_path, temp_store, m_row.ssl_ca_path_length);
+
+ temp_store= (char*)mi->ssl_cert;
+ m_row.ssl_certificate_length= strlen(temp_store);
+ memcpy(m_row.ssl_certificate, temp_store, m_row.ssl_certificate_length);
+
+ temp_store= (char*)mi->ssl_cipher;
+ m_row.ssl_cipher_length= strlen(temp_store);
+ memcpy(m_row.ssl_cipher, temp_store, m_row.ssl_cipher_length);
+
+ temp_store= (char*)mi->ssl_key;
+ m_row.ssl_key_length= strlen(temp_store);
+ memcpy(m_row.ssl_key, temp_store, m_row.ssl_key_length);
+
+ if (mi->ssl_verify_server_cert)
+ m_row.ssl_verify_server_certificate= PS_RPL_YES;
+ else
+ m_row.ssl_verify_server_certificate= PS_RPL_NO;
+
+ temp_store= (char*)mi->ssl_crl;
+ m_row.ssl_crl_file_length= strlen(temp_store);
+ memcpy(m_row.ssl_crl_file, temp_store, m_row.ssl_crl_file_length);
+
+ temp_store= (char*)mi->ssl_crlpath;
+ m_row.ssl_crl_path_length= strlen(temp_store);
+ memcpy(m_row.ssl_crl_path, temp_store, m_row.ssl_crl_path_length);
+
+ m_row.connection_retry_interval= (unsigned int) mi->connect_retry;
+
+ m_row.connection_retry_count= 0; //(ulong) mi->retry_count;
+
+ m_row.heartbeat_interval= (double)mi->heartbeat_period;
+
+ temp_store= (char*)""; //mi->tls_version;
+ m_row.tls_version_length= strlen(temp_store);
+ memcpy(m_row.tls_version, temp_store, m_row.tls_version_length);
+
+ mysql_mutex_unlock(&mi->rli.data_lock);
+ mysql_mutex_unlock(&mi->data_lock);
+
+ m_row_exists= true;
+}
+
+int table_replication_connection_configuration::read_row_values(TABLE *table,
+ unsigned char *,
+ Field **fields,
+ bool read_all)
+{
+ Field *f;
+
+ if (unlikely(! m_row_exists))
+ return HA_ERR_RECORD_DELETED;
+
+ DBUG_ASSERT(table->s->null_bytes == 0);
+
+ for (; (f= *fields) ; fields++)
+ {
+ if (read_all || bitmap_is_set(table->read_set, f->field_index))
+ {
+ switch(f->field_index)
+ {
+ case 0: /** channel_name */
+ set_field_char_utf8(f, m_row.channel_name, m_row.channel_name_length);
+ break;
+ case 1: /** host */
+ set_field_char_utf8(f, m_row.host, m_row.host_length);
+ break;
+ case 2: /** port */
+ set_field_ulong(f, m_row.port);
+ break;
+ case 3: /** user */
+ set_field_char_utf8(f, m_row.user, m_row.user_length);
+ break;
+ case 4: /** network_interface */
+ set_field_char_utf8(f, m_row.network_interface,
+ m_row.network_interface_length);
+ break;
+ case 5: /** auto_position */
+ set_field_enum(f, m_row.auto_position);
+ break;
+ case 6: /** ssl_allowed */
+ set_field_enum(f, m_row. ssl_allowed);
+ break;
+ case 7: /**ssl_ca_file */
+ set_field_varchar_utf8(f, m_row.ssl_ca_file,
+ m_row.ssl_ca_file_length);
+ break;
+ case 8: /** ssl_ca_path */
+ set_field_varchar_utf8(f, m_row.ssl_ca_path,
+ m_row.ssl_ca_path_length);
+ break;
+ case 9: /** ssl_certificate */
+ set_field_varchar_utf8(f, m_row.ssl_certificate,
+ m_row.ssl_certificate_length);
+ break;
+ case 10: /** ssl_cipher */
+ set_field_varchar_utf8(f, m_row.ssl_cipher, m_row.ssl_cipher_length);
+ break;
+ case 11: /** ssl_key */
+ set_field_varchar_utf8(f, m_row.ssl_key, m_row.ssl_key_length);
+ break;
+ case 12: /** ssl_verify_server_certificate */
+ set_field_enum(f, m_row.ssl_verify_server_certificate);
+ break;
+ case 13: /** ssl_crl_file */
+ set_field_varchar_utf8(f, m_row.ssl_crl_file,
+ m_row.ssl_crl_file_length);
+ break;
+ case 14: /** ssl_crl_path */
+ set_field_varchar_utf8(f, m_row.ssl_crl_path,
+ m_row.ssl_crl_path_length);
+ break;
+ case 15: /** connection_retry_interval */
+ set_field_ulong(f, m_row.connection_retry_interval);
+ break;
+ case 16: /** connect_retry_count */
+ set_field_ulonglong(f, m_row.connection_retry_count);
+ break;
+ case 17:/** number of seconds after which heartbeat will be sent */
+ set_field_double(f, m_row.heartbeat_interval);
+ break;
+ case 18: /** tls_version */
+ set_field_varchar_utf8(f, m_row.tls_version,
+ m_row.tls_version_length);
+ break;
+ default:
+ DBUG_ASSERT(false);
+ }
+ }
+ }
+ return 0;
+}
diff --git a/storage/perfschema/table_replication_connection_configuration.h b/storage/perfschema/table_replication_connection_configuration.h
new file mode 100644
index 00000000000..d1c8861cf0d
--- /dev/null
+++ b/storage/perfschema/table_replication_connection_configuration.h
@@ -0,0 +1,152 @@
+/*
+ Copyright (c) 2013, 2018, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+
+#ifndef TABLE_REPLICATION_CONFIGURATION_H
+#define TABLE_REPLICATION_CONFIGURATION_H
+
+/**
+ @file storage/perfschema/table_replication_connection_configuration.h
+ Table replication_connection_configuration (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "rpl_mi.h"
+#include "mysql_com.h"
+#include "my_thread.h"
+//#include "rpl_msr.h"
+//#include "rpl_info.h" /* CHANNEL_NAME_LENGTH*/
+
+class Master_info;
+
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+#ifndef ENUM_RPL_YES_NO
+#define ENUM_RPL_YES_NO
+enum enum_rpl_yes_no {
+ PS_RPL_YES= 1,
+ PS_RPL_NO
+};
+#endif
+
+/** enum values for SSL_Allowed*/
+enum enum_ssl_allowed {
+ PS_SSL_ALLOWED_YES= 1,
+ PS_SSL_ALLOWED_NO,
+ PS_SSL_ALLOWED_IGNORED
+};
+
+/**
+ A row in the table. The fields with string values have an additional
+ length field denoted by <field_name>_length.
+*/
+struct st_row_connect_config {
+ char channel_name[CHANNEL_NAME_LENGTH];
+ uint channel_name_length;
+ char host[HOSTNAME_LENGTH];
+ uint host_length;
+ uint port;
+ char user[USERNAME_LENGTH];
+ uint user_length;
+ char network_interface[HOSTNAME_LENGTH];
+ uint network_interface_length;
+ enum_rpl_yes_no auto_position;
+ enum_ssl_allowed ssl_allowed;
+ char ssl_ca_file[FN_REFLEN];
+ uint ssl_ca_file_length;
+ char ssl_ca_path[FN_REFLEN];
+ uint ssl_ca_path_length;
+ char ssl_certificate[FN_REFLEN];
+ uint ssl_certificate_length;
+ char ssl_cipher[FN_REFLEN];
+ uint ssl_cipher_length;
+ char ssl_key[FN_REFLEN];
+ uint ssl_key_length;
+ enum_rpl_yes_no ssl_verify_server_certificate;
+ char ssl_crl_file[FN_REFLEN];
+ uint ssl_crl_file_length;
+ char ssl_crl_path[FN_REFLEN];
+ uint ssl_crl_path_length;
+ uint connection_retry_interval;
+ ulong connection_retry_count;
+ double heartbeat_interval;
+ char tls_version[FN_REFLEN];
+ uint tls_version_length;
+};
+
+/** Table PERFORMANCE_SCHEMA.TABLE_REPLICATION_CONNECTION_CONFIGURATION. */
+class table_replication_connection_configuration: public PFS_engine_table
+{
+ typedef PFS_simple_index pos_t;
+
+private:
+ void make_row(Master_info *);
+
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /** Fields definition. */
+ static TABLE_FIELD_DEF m_field_def;
+ /** True if the current row exists. */
+ bool m_row_exists;
+ /** Current row */
+ st_row_connect_config m_row;
+ /** Current position. */
+ pos_t m_pos;
+ /** Next position. */
+ pos_t m_next_pos;
+
+protected:
+ /**
+ Read the current row values.
+ @param table Table handle
+ @param buf row buffer
+ @param fields Table fields
+ @param read_all true if all columns are read.
+ */
+
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+
+ table_replication_connection_configuration();
+
+public:
+ ~table_replication_connection_configuration();
+
+ /** Table share. */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static ha_rows get_row_count();
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+};
+
+/** @} */
+#endif
diff --git a/storage/perfschema/table_replication_connection_status.cc b/storage/perfschema/table_replication_connection_status.cc
new file mode 100644
index 00000000000..eb1d3c8ef71
--- /dev/null
+++ b/storage/perfschema/table_replication_connection_status.cc
@@ -0,0 +1,440 @@
+/*
+ Copyright (c) 2013, 2018, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/**
+ @file storage/perfschema/table_replication_connection_status.cc
+ Table replication_connection_status (implementation).
+*/
+
+#define HAVE_REPLICATION
+
+#include "my_global.h"
+#include "table_replication_connection_status.h"
+#include "pfs_instr_class.h"
+#include "pfs_instr.h"
+#include "slave.h"
+//#include "rpl_info.h"
+#include "rpl_rli.h"
+#include "rpl_mi.h"
+#include "sql_parse.h"
+//#include "rpl_msr.h" /* Multi source replication */
+#include "log.h"
+//#include "rpl_group_replication.h"
+
+/*
+ Callbacks implementation for GROUP_REPLICATION_CONNECTION_STATUS_CALLBACKS.
+*/
+static void set_channel_name(void* const context, const char& value,
+ size_t length)
+{
+}
+
+static void set_group_name(void* const context, const char& value,
+ size_t length)
+{
+ struct st_row_connect_status* row=
+ static_cast<struct st_row_connect_status*>(context);
+ const size_t max= UUID_LENGTH;
+ length= std::min(length, max);
+
+ row->group_name_is_null= false;
+ memcpy(row->group_name, &value, length);
+}
+
+static void set_source_uuid(void* const context, const char& value,
+ size_t length)
+{
+ struct st_row_connect_status* row=
+ static_cast<struct st_row_connect_status*>(context);
+ const size_t max= UUID_LENGTH;
+ length= std::min(length, max);
+
+ row->source_uuid_is_null= false;
+ memcpy(row->source_uuid, &value, length);
+}
+
+static void set_service_state(void* const context, bool value)
+{
+ struct st_row_connect_status* row=
+ static_cast<struct st_row_connect_status*>(context);
+
+ row->service_state= value ? PS_RPL_CONNECT_SERVICE_STATE_YES
+ : PS_RPL_CONNECT_SERVICE_STATE_NO;
+}
+
+
+THR_LOCK table_replication_connection_status::m_table_lock;
+
+
+/* Numbers in varchar count utf8 characters. */
+static const TABLE_FIELD_TYPE field_types[]=
+{
+ {
+ {C_STRING_WITH_LEN("CHANNEL_NAME")},
+ {C_STRING_WITH_LEN("char(64)")},
+ {NULL, 0}
+ },
+ {
+ {C_STRING_WITH_LEN("GROUP_NAME")},
+ {C_STRING_WITH_LEN("char(36)")},
+ {NULL, 0}
+ },
+ {
+ {C_STRING_WITH_LEN("SOURCE_UUID")},
+ {C_STRING_WITH_LEN("char(36)")},
+ {NULL, 0}
+ },
+ {
+ {C_STRING_WITH_LEN("THREAD_ID")},
+ {C_STRING_WITH_LEN("bigint(20)")},
+ {NULL, 0}
+ },
+ {
+ {C_STRING_WITH_LEN("SERVICE_STATE")},
+ {C_STRING_WITH_LEN("enum('ON','OFF','CONNECTING')")},
+ {NULL, 0}
+ },
+ {
+ {C_STRING_WITH_LEN("COUNT_RECEIVED_HEARTBEATS")},
+ {C_STRING_WITH_LEN("bigint(20)")},
+ {NULL, 0}
+ },
+ {
+ {C_STRING_WITH_LEN("LAST_HEARTBEAT_TIMESTAMP")},
+ {C_STRING_WITH_LEN("timestamp")},
+ {NULL, 0}
+ },
+ {
+ {C_STRING_WITH_LEN("RECEIVED_TRANSACTION_SET")},
+ {C_STRING_WITH_LEN("longtext")},
+ {NULL, 0}
+ },
+ {
+ {C_STRING_WITH_LEN("LAST_ERROR_NUMBER")},
+ {C_STRING_WITH_LEN("int(11)")},
+ {NULL, 0}
+ },
+ {
+ {C_STRING_WITH_LEN("LAST_ERROR_MESSAGE")},
+ {C_STRING_WITH_LEN("varchar(1024)")},
+ {NULL, 0}
+ },
+ {
+ {C_STRING_WITH_LEN("LAST_ERROR_TIMESTAMP")},
+ {C_STRING_WITH_LEN("timestamp")},
+ {NULL, 0}
+ }
+};
+
+TABLE_FIELD_DEF
+table_replication_connection_status::m_field_def= { 11, field_types };
+
+PFS_engine_table_share
+table_replication_connection_status::m_share=
+{
+ { C_STRING_WITH_LEN("replication_connection_status") },
+ &pfs_readonly_acl,
+ table_replication_connection_status::create,
+ NULL, /* write_row */
+ NULL, /* delete_all_rows */
+ table_replication_connection_status::get_row_count, /* records */
+ sizeof(pos_t), /* ref length */
+ &m_table_lock,
+ &m_field_def,
+ false, /* checked */
+ false /* perpetual */
+};
+
+PFS_engine_table* table_replication_connection_status::create(void)
+{
+ return new table_replication_connection_status();
+}
+
+table_replication_connection_status::table_replication_connection_status()
+ : PFS_engine_table(&m_share, &m_pos),
+ m_row_exists(false), m_pos(0), m_next_pos(0)
+{
+}
+
+table_replication_connection_status::~table_replication_connection_status()
+{
+}
+
+void table_replication_connection_status::reset_position(void)
+{
+ m_pos.m_index= 0;
+ m_next_pos.m_index= 0;
+}
+
+ha_rows table_replication_connection_status::get_row_count()
+{
+ /*A lock is not needed for an estimate */
+ return channel_map.get_max_channels();
+}
+
+
+
+int table_replication_connection_status::rnd_next(void)
+{
+ Master_info *mi= NULL;
+ channel_map.rdlock();
+
+ for (m_pos.set_at(&m_next_pos);
+ m_pos.m_index < channel_map.get_max_channels();
+ m_pos.next())
+ {
+ mi= channel_map.get_mi_at_pos(m_pos.m_index);
+
+ if (mi && mi->host[0])
+ {
+ make_row(mi);
+ m_next_pos.set_after(&m_pos);
+ channel_map.unlock();
+ return 0;
+ }
+ }
+
+ channel_map.unlock();
+ return HA_ERR_END_OF_FILE;
+}
+
+int table_replication_connection_status::rnd_pos(const void *pos)
+{
+ Master_info *mi;
+ int res= HA_ERR_RECORD_DELETED;
+
+ set_position(pos);
+
+ channel_map.rdlock();
+
+ if ((mi= channel_map.get_mi_at_pos(m_pos.m_index)))
+ {
+ make_row(mi);
+ res= 0;
+ }
+
+ channel_map.unlock();
+ return res;
+}
+
+void table_replication_connection_status::make_row(Master_info *mi)
+{
+ DBUG_ENTER("table_replication_connection_status::make_row");
+ m_row_exists= false;
+ bool error= false;
+
+ /* Default values */
+ m_row.group_name_is_null= true;
+ m_row.source_uuid_is_null= true;
+ m_row.thread_id_is_null= true;
+ m_row.service_state= PS_RPL_CONNECT_SERVICE_STATE_NO;
+
+ DBUG_ASSERT(mi != NULL);
+ DBUG_ASSERT(mi->rli != NULL);
+
+ mysql_mutex_lock(&mi->data_lock);
+ mysql_mutex_lock(&mi->rli->data_lock);
+
+ m_row.channel_name_length= mi->get_channel() ? strlen(mi->get_channel()):0;
+ memcpy(m_row.channel_name, mi->get_channel(), m_row.channel_name_length);
+
+ if (is_group_replication_plugin_loaded() &&
+ channel_map.is_group_replication_channel_name(mi->get_channel(), true))
+ {
+ /*
+ Group Replication applier channel.
+ Set callbacks on GROUP_REPLICATION_GROUP_MEMBER_STATS_CALLBACKS.
+ */
+ const GROUP_REPLICATION_CONNECTION_STATUS_CALLBACKS callbacks=
+ {
+ &m_row,
+ &set_channel_name,
+ &set_group_name,
+ &set_source_uuid,
+ &set_service_state,
+ };
+
+ // Query plugin and let callbacks do their job.
+ if (get_group_replication_connection_status_info(callbacks))
+ {
+ DBUG_PRINT("info", ("Group Replication stats not available!"));
+ }
+ }
+ else
+ {
+ /* Slave channel. */
+ if (mi->master_uuid[0] != 0)
+ {
+ memcpy(m_row.source_uuid, mi->master_uuid, UUID_LENGTH);
+ m_row.source_uuid_is_null= false;
+ }
+
+ if (mi->slave_running == MYSQL_SLAVE_RUN_CONNECT)
+ m_row.service_state= PS_RPL_CONNECT_SERVICE_STATE_YES;
+ else
+ {
+ if (mi->slave_running == MYSQL_SLAVE_RUN_NOT_CONNECT)
+ m_row.service_state= PS_RPL_CONNECT_SERVICE_STATE_CONNECTING;
+ else
+ m_row.service_state= PS_RPL_CONNECT_SERVICE_STATE_NO;
+ }
+ }
+
+ if (mi->slave_running == MYSQL_SLAVE_RUN_CONNECT)
+ {
+ PSI_thread *psi= thd_get_psi(mi->info_thd);
+ PFS_thread *pfs= reinterpret_cast<PFS_thread *> (psi);
+ if(pfs)
+ {
+ m_row.thread_id= pfs->m_thread_internal_id;
+ m_row.thread_id_is_null= false;
+ }
+ }
+
+ m_row.count_received_heartbeats= mi->received_heartbeats;
+ /*
+ Time in Milliseconds since epoch. active_mi->last_heartbeat contains
+ number of seconds so we multiply by 1000000.
+ */
+ m_row.last_heartbeat_timestamp= (ulonglong)mi->last_heartbeat*1000000;
+
+ {
+ global_sid_lock->wrlock();
+ const Gtid_set* io_gtid_set= mi->rli->get_gtid_set();
+
+ if ((m_row.received_transaction_set_length=
+ io_gtid_set->to_string(&m_row.received_transaction_set)) < 0)
+ {
+ my_free(m_row.received_transaction_set);
+ m_row.received_transaction_set_length= 0;
+ global_sid_lock->unlock();
+ error= true;
+ goto end;
+ }
+ global_sid_lock->unlock();
+ }
+
+ /* Errors */
+ mysql_mutex_lock(&mi->err_lock);
+ mysql_mutex_lock(&mi->rli->err_lock);
+ m_row.last_error_number= (unsigned int) mi->last_error().number;
+ m_row.last_error_message_length= 0;
+ m_row.last_error_timestamp= 0;
+
+ /** If error, set error message and timestamp */
+ if (m_row.last_error_number)
+ {
+ char* temp_store= (char*)mi->last_error().message;
+ m_row.last_error_message_length= strlen(temp_store);
+ memcpy(m_row.last_error_message, temp_store,
+ m_row.last_error_message_length);
+
+ /*
+ Time in millisecond since epoch. active_mi->last_error().skr contains
+ number of seconds so we multiply by 1000000. */
+ m_row.last_error_timestamp= (ulonglong)mi->last_error().skr*1000000;
+ }
+ mysql_mutex_unlock(&mi->rli->err_lock);
+ mysql_mutex_unlock(&mi->err_lock);
+
+end:
+ mysql_mutex_unlock(&mi->rli->data_lock);
+ mysql_mutex_unlock(&mi->data_lock);
+
+ if (!error)
+ m_row_exists= true;
+ DBUG_VOID_RETURN;
+}
+
+int table_replication_connection_status::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;
+
+ 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 0: /** channel_name*/
+ set_field_char_utf8(f, m_row.channel_name,m_row.channel_name_length);
+ break;
+ case 1: /** group_name */
+ if (m_row.group_name_is_null)
+ f->set_null();
+ else
+ set_field_char_utf8(f, m_row.group_name, UUID_LENGTH);
+ break;
+ case 2: /** source_uuid */
+ if (m_row.source_uuid_is_null)
+ f->set_null();
+ else
+ set_field_char_utf8(f, m_row.source_uuid, UUID_LENGTH);
+ break;
+ case 3: /** thread_id */
+ if(m_row.thread_id_is_null)
+ f->set_null();
+ else
+ set_field_ulonglong(f, m_row.thread_id);
+ break;
+ case 4: /** service_state */
+ set_field_enum(f, m_row.service_state);
+ break;
+ case 5: /** number of heartbeat events received **/
+ set_field_ulonglong(f, m_row.count_received_heartbeats);
+ break;
+ case 6: /** time of receipt of last heartbeat event **/
+ set_field_timestamp(f, m_row.last_heartbeat_timestamp);
+ break;
+ case 7: /** received_transaction_set */
+ set_field_longtext_utf8(f, m_row.received_transaction_set,
+ m_row.received_transaction_set_length);
+ break;
+ case 8: /*last_error_number*/
+ set_field_ulong(f, m_row.last_error_number);
+ break;
+ case 9: /*last_error_message*/
+ set_field_varchar_utf8(f, m_row.last_error_message,
+ m_row.last_error_message_length);
+ break;
+ case 10: /*last_error_timestamp*/
+ set_field_timestamp(f, m_row.last_error_timestamp);
+ break;
+ default:
+ DBUG_ASSERT(false);
+ }
+ }
+ }
+ m_row.cleanup();
+
+ return 0;
+}
diff --git a/storage/perfschema/table_replication_connection_status.h b/storage/perfschema/table_replication_connection_status.h
new file mode 100644
index 00000000000..a1a5eb116bc
--- /dev/null
+++ b/storage/perfschema/table_replication_connection_status.h
@@ -0,0 +1,150 @@
+/*
+ Copyright (c) 2013, 2018, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+
+#ifndef TABLE_REPLICATION_CONNECTION_STATUS_H
+#define TABLE_REPLICATION_CONNECTION_STATUS_H
+
+/**
+ @file storage/perfschema/table_replication_connection_status.h
+ Table replication_connection_status (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "rpl_mi.h"
+#include "rpl_reporting.h" /* MAX_SLAVE_ERRMSG */
+#include "mysql_com.h"
+//#include "rpl_msr.h"
+//#include "rpl_info.h" /*CHANNEL_NAME_LENGTH */
+#include "my_thread.h"
+
+class Master_info;
+
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+#ifndef ENUM_RPL_YES_NO
+#define ENUM_RPL_YES_NO
+enum enum_rpl_yes_no {
+ PS_RPL_YES= 1,
+ PS_RPL_NO
+};
+#endif
+
+enum enum_rpl_connect_status_service_state {
+ PS_RPL_CONNECT_SERVICE_STATE_YES= 1,
+ PS_RPL_CONNECT_SERVICE_STATE_NO,
+ PS_RPL_CONNECT_SERVICE_STATE_CONNECTING
+};
+
+/*
+ A row in the table. The fields with string values have an additional
+ length field denoted by <field_name>_length.
+*/
+struct st_row_connect_status {
+ char group_name[NAME_LEN];
+ bool group_name_is_null;
+ char channel_name[CHANNEL_NAME_LENGTH];
+ uint channel_name_length;
+ char source_uuid[11]; // typeof(server_id) == uint32
+ bool source_uuid_is_null;
+ ulonglong thread_id;
+ bool thread_id_is_null;
+ enum_rpl_connect_status_service_state service_state;
+ ulonglong count_received_heartbeats;
+ ulonglong last_heartbeat_timestamp;
+ char* received_transaction_set;
+ int received_transaction_set_length;
+ uint last_error_number;
+ char last_error_message[MAX_SLAVE_ERRMSG];
+ uint last_error_message_length;
+ ulonglong last_error_timestamp;
+
+ st_row_connect_status() : received_transaction_set(NULL) {}
+
+ void cleanup()
+ {
+ if (received_transaction_set != NULL)
+ {
+ my_free(received_transaction_set);
+ received_transaction_set= NULL;
+ }
+ }
+};
+
+
+/** Table PERFORMANCE_SCHEMA.REPLICATION_CONNECTION_STATUS. */
+class table_replication_connection_status: public PFS_engine_table
+{
+ typedef PFS_simple_index pos_t;
+
+private:
+ void make_row(Master_info *mi);
+
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /** Fields definition. */
+ static TABLE_FIELD_DEF m_field_def;
+ /** True if the current row exists. */
+ bool m_row_exists;
+ /** Current row */
+ st_row_connect_status m_row;
+ /** Current position. */
+ pos_t m_pos;
+ /** Next position. */
+ pos_t m_next_pos;
+
+protected:
+ /**
+ Read the current row values.
+ @param table Table handle
+ @param buf row buffer
+ @param fields Table fields
+ @param read_all true if all columns are read.
+ */
+
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+
+ table_replication_connection_status();
+
+public:
+ ~table_replication_connection_status();
+
+ /** Table share. */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static ha_rows get_row_count();
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+};
+
+/** @} */
+#endif
diff --git a/storage/perfschema/table_replication_group_member_stats.cc b/storage/perfschema/table_replication_group_member_stats.cc
new file mode 100644
index 00000000000..9c7f61817d1
--- /dev/null
+++ b/storage/perfschema/table_replication_group_member_stats.cc
@@ -0,0 +1,372 @@
+/*
+ Copyright (c) 2014, 2016, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/**
+ @file storage/perfschema/table_replication_group_member_stats.cc
+ Table replication_group_member_stats (implementation).
+*/
+
+#define HAVE_REPLICATION
+
+#include "my_global.h"
+#include "table_replication_group_member_stats.h"
+#include "pfs_instr_class.h"
+#include "pfs_instr.h"
+#include "log.h"
+#include "rpl_group_replication.h"
+
+/*
+ Callbacks implementation for GROUP_REPLICATION_GROUP_MEMBER_STATS_CALLBACKS.
+*/
+static void set_channel_name(void* const context, const char& value,
+ size_t length)
+{
+ struct st_row_group_member_stats* row=
+ static_cast<struct st_row_group_member_stats*>(context);
+ const size_t max= CHANNEL_NAME_LENGTH;
+ length= std::min(length, max);
+
+ row->channel_name_length= length;
+ memcpy(row->channel_name, &value, length);
+}
+
+static void set_view_id(void* const context, const char& value, size_t length)
+{
+ struct st_row_group_member_stats* row=
+ static_cast<struct st_row_group_member_stats*>(context);
+ const size_t max= HOSTNAME_LENGTH;
+ length= std::min(length, max);
+
+ row->view_id_length= length;
+ memcpy(row->view_id, &value, length);
+}
+
+static void set_member_id(void* const context, const char& value, size_t length)
+{
+ struct st_row_group_member_stats* row=
+ static_cast<struct st_row_group_member_stats*>(context);
+ const size_t max= UUID_LENGTH;
+ length= std::min(length, max);
+
+ row->member_id_length= length;
+ memcpy(row->member_id, &value, length);
+}
+
+static void set_transactions_committed(void* const context, const char& value,
+ size_t length)
+{
+ struct st_row_group_member_stats* row=
+ static_cast<struct st_row_group_member_stats*>(context);
+
+ if (row->trx_committed != NULL)
+ my_free(row->trx_committed);
+
+ row->trx_committed_length= length;
+ row->trx_committed= (char*) my_malloc(PSI_NOT_INSTRUMENTED,
+ length,
+ MYF(0));
+ memcpy(row->trx_committed, &value, length);
+}
+
+static void set_last_conflict_free_transaction(void* const context,
+ const char& value, size_t length)
+{
+ struct st_row_group_member_stats* row=
+ static_cast<struct st_row_group_member_stats*>(context);
+ const size_t max= Gtid::MAX_TEXT_LENGTH+1;
+ length= std::min(length, max);
+
+ row->last_cert_trx_length= length;
+ memcpy(row->last_cert_trx, &value, length);
+}
+
+static void set_transactions_in_queue(void* const context,
+ unsigned long long int value)
+{
+ struct st_row_group_member_stats* row=
+ static_cast<struct st_row_group_member_stats*>(context);
+ row->trx_in_queue= value;
+}
+
+static void set_transactions_certified(void* const context,
+ unsigned long long int value)
+{
+ struct st_row_group_member_stats* row=
+ static_cast<struct st_row_group_member_stats*>(context);
+ row->trx_checked= value;
+}
+
+static void set_transactions_conflicts_detected(void* const context,
+ unsigned long long int value)
+{
+ struct st_row_group_member_stats* row=
+ static_cast<struct st_row_group_member_stats*>(context);
+ row->trx_conflicts= value;
+}
+
+static void set_transactions_rows_in_validation(void* const context,
+ unsigned long long int value)
+{
+ struct st_row_group_member_stats* row=
+ static_cast<struct st_row_group_member_stats*>(context);
+ row->trx_rows_validating= value;
+}
+
+
+THR_LOCK table_replication_group_member_stats::m_table_lock;
+
+static const TABLE_FIELD_TYPE field_types[]=
+{
+ {
+ {C_STRING_WITH_LEN("CHANNEL_NAME")},
+ {C_STRING_WITH_LEN("char(64)")},
+ {NULL, 0}
+ },
+ {
+ {C_STRING_WITH_LEN("VIEW_ID")},
+ {C_STRING_WITH_LEN("char(60)")},
+ {NULL, 0}
+ },
+ {
+ {C_STRING_WITH_LEN("MEMBER_ID")},
+ {C_STRING_WITH_LEN("char(36)")},
+ {NULL, 0}
+ },
+ {
+ {C_STRING_WITH_LEN("COUNT_TRANSACTIONS_IN_QUEUE")},
+ {C_STRING_WITH_LEN("bigint")},
+ {NULL, 0}
+ },
+ {
+ {C_STRING_WITH_LEN("COUNT_TRANSACTIONS_CHECKED")},
+ {C_STRING_WITH_LEN("bigint")},
+ {NULL, 0}
+ },
+ {
+ {C_STRING_WITH_LEN("COUNT_CONFLICTS_DETECTED")},
+ {C_STRING_WITH_LEN("bigint")},
+ {NULL, 0}
+ },
+ {
+ {C_STRING_WITH_LEN("COUNT_TRANSACTIONS_ROWS_VALIDATING")},
+ {C_STRING_WITH_LEN("bigint")},
+ {NULL, 0}
+ },
+ {
+ {C_STRING_WITH_LEN("TRANSACTIONS_COMMITTED_ALL_MEMBERS")},
+ {C_STRING_WITH_LEN("longtext")},
+ {NULL, 0}
+ },
+ {
+ {C_STRING_WITH_LEN("LAST_CONFLICT_FREE_TRANSACTION")},
+ {C_STRING_WITH_LEN("text")},
+ {NULL, 0}
+ }
+};
+
+TABLE_FIELD_DEF
+table_replication_group_member_stats::m_field_def=
+{ 9, field_types };
+
+PFS_engine_table_share
+table_replication_group_member_stats::m_share=
+{
+ { C_STRING_WITH_LEN("replication_group_member_stats") },
+ &pfs_readonly_acl,
+ &table_replication_group_member_stats::create,
+ NULL, /* write_row */
+ NULL, /* delete_all_rows */
+ table_replication_group_member_stats::get_row_count,
+ sizeof(PFS_simple_index), /* ref length */
+ &m_table_lock,
+ &m_field_def,
+ false, /* checked */
+ false /* perpetual */
+};
+
+PFS_engine_table* table_replication_group_member_stats::create(void)
+{
+ return new table_replication_group_member_stats();
+}
+
+table_replication_group_member_stats::table_replication_group_member_stats()
+ : PFS_engine_table(&m_share, &m_pos),
+ m_row_exists(false), m_pos(0), m_next_pos(0)
+{
+ m_row.trx_committed= NULL;
+}
+
+table_replication_group_member_stats::~table_replication_group_member_stats()
+{
+ if (m_row.trx_committed != NULL)
+ {
+ my_free(m_row.trx_committed);
+ m_row.trx_committed= NULL;
+ }
+}
+
+void table_replication_group_member_stats::reset_position(void)
+{
+ m_pos.m_index= 0;
+ m_next_pos.m_index= 0;
+}
+
+ha_rows table_replication_group_member_stats::get_row_count()
+{
+ uint row_count= 0;
+
+ if (is_group_replication_plugin_loaded())
+ row_count= 1;
+
+ return row_count;
+}
+
+int table_replication_group_member_stats::rnd_next(void)
+{
+ if (!is_group_replication_plugin_loaded())
+ return HA_ERR_END_OF_FILE;
+
+ m_pos.set_at(&m_next_pos);
+ if (m_pos.m_index == 0)
+ {
+ make_row();
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+
+ return HA_ERR_END_OF_FILE;
+}
+
+int table_replication_group_member_stats::rnd_pos(const void *pos)
+{
+ if (get_row_count() == 0)
+ return HA_ERR_END_OF_FILE;
+
+ set_position(pos);
+ DBUG_ASSERT(m_pos.m_index < 1);
+ make_row();
+
+ return 0;
+}
+
+void table_replication_group_member_stats::make_row()
+{
+ DBUG_ENTER("table_replication_group_member_stats::make_row");
+ // Set default values.
+ m_row_exists= false;
+ m_row.channel_name_length= 0;
+ m_row.view_id_length= 0;
+ m_row.member_id_length= 0;
+ m_row.trx_committed_length= 0;
+ m_row.last_cert_trx_length= 0;
+ m_row.trx_in_queue= 0;
+ m_row.trx_checked= 0;
+ m_row.trx_conflicts= 0;
+ m_row.trx_rows_validating= 0;
+
+ // Set callbacks on GROUP_REPLICATION_GROUP_MEMBER_STATS_CALLBACKS.
+ const GROUP_REPLICATION_GROUP_MEMBER_STATS_CALLBACKS callbacks=
+ {
+ &m_row,
+ &set_channel_name,
+ &set_view_id,
+ &set_member_id,
+ &set_transactions_committed,
+ &set_last_conflict_free_transaction,
+ &set_transactions_in_queue,
+ &set_transactions_certified,
+ &set_transactions_conflicts_detected,
+ &set_transactions_rows_in_validation,
+ };
+
+ // Query plugin and let callbacks do their job.
+ if (get_group_replication_group_member_stats_info(callbacks))
+ {
+ DBUG_PRINT("info", ("Group Replication stats not available!"));
+ }
+ else
+ {
+ m_row_exists= true;
+ }
+
+ DBUG_VOID_RETURN;
+}
+
+
+int table_replication_group_member_stats::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;
+
+ DBUG_ASSERT(table->s->null_bytes == 0);
+ buf[0]= 0;
+
+ for (; (f= *fields) ; fields++)
+ {
+ if (read_all || bitmap_is_set(table->read_set, f->field_index))
+ {
+ switch(f->field_index)
+ {
+ case 0: /** channel_name */
+ set_field_char_utf8(f, m_row.channel_name,
+ m_row.channel_name_length);
+ break;
+ case 1: /** view id */
+ set_field_char_utf8(f, m_row.view_id, m_row.view_id_length);
+ break;
+ case 2: /** member_id */
+ set_field_char_utf8(f, m_row.member_id, m_row.member_id_length);
+ break;
+ case 3: /** transaction_in_queue */
+ set_field_ulonglong(f, m_row.trx_in_queue);
+ break;
+ case 4: /** transactions_certified */
+ set_field_ulonglong(f, m_row.trx_checked);
+ break;
+ case 5: /** negatively_certified_transaction */
+ set_field_ulonglong(f, m_row.trx_conflicts);
+ break;
+ case 6: /** certification_db_size */
+ set_field_ulonglong(f, m_row.trx_rows_validating);
+ break;
+ case 7: /** stable_set */
+ set_field_longtext_utf8(f, m_row.trx_committed,
+ m_row.trx_committed_length);
+ break;
+ case 8: /** last_certified_transaction */
+ set_field_longtext_utf8(f, m_row.last_cert_trx,
+ m_row.last_cert_trx_length);
+
+ break;
+ default:
+ DBUG_ASSERT(false);
+ }
+ }
+ }
+ return 0;
+}
diff --git a/storage/perfschema/table_replication_group_member_stats.h b/storage/perfschema/table_replication_group_member_stats.h
new file mode 100644
index 00000000000..f2fcaf553b4
--- /dev/null
+++ b/storage/perfschema/table_replication_group_member_stats.h
@@ -0,0 +1,116 @@
+/*
+ Copyright (c) 2014, 2016, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+
+#ifndef TABLE_REPLICATION_GROUP_MEMBER_STATS_H
+#define TABLE_REPLICATION_GROUP_MEMBER_STATS_H
+
+/**
+ @file storage/perfschema/table_replication_group_member_stats.h
+ Table replication_group_member_stats (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "mysql_com.h"
+//#include "rpl_info.h"
+//#include "rpl_gtid.h"
+//#include <mysql/plugin_group_replication.h>
+
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+/**
+ A row in node status table. The fields with string values have an additional
+ length field denoted by <field_name>_length.
+*/
+
+struct st_row_group_member_stats {
+ char channel_name[CHANNEL_NAME_LENGTH];
+ uint channel_name_length;
+ char view_id[HOSTNAME_LENGTH];
+ uint view_id_length;
+ char member_id[11]; // typeof(server_id) == uint32
+ uint member_id_length;
+ ulonglong trx_in_queue;
+ ulonglong trx_checked;
+ ulonglong trx_conflicts;
+ ulonglong trx_rows_validating;
+ char *trx_committed;
+ size_t trx_committed_length;
+ char last_cert_trx[GTID_MAX_STR_LENGTH + 1];
+ int last_cert_trx_length;
+};
+
+/** Table PERFORMANCE_SCHEMA.REPLICATION_GROUP_MEMBER_STATS. */
+class table_replication_group_member_stats: public PFS_engine_table
+{
+private:
+ void make_row();
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /** Fields definition. */
+ static TABLE_FIELD_DEF m_field_def;
+ /** True if the current row exists. */
+ bool m_row_exists;
+ /** Current row */
+ st_row_group_member_stats m_row;
+ /** Current position. */
+ PFS_simple_index m_pos;
+ /** Next position. */
+ PFS_simple_index m_next_pos;
+
+protected:
+ /**
+ Read the current row values.
+ @param table Table handle
+ @param buf row buffer
+ @param fields Table fields
+ @param read_all true if all columns are read.
+ */
+
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+
+ table_replication_group_member_stats();
+
+public:
+ ~table_replication_group_member_stats();
+
+ /** Table share. */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static ha_rows get_row_count();
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+};
+
+/** @} */
+#endif
+
diff --git a/storage/perfschema/table_replication_group_members.cc b/storage/perfschema/table_replication_group_members.cc
new file mode 100644
index 00000000000..d86052d687f
--- /dev/null
+++ b/storage/perfschema/table_replication_group_members.cc
@@ -0,0 +1,281 @@
+/*
+ Copyright (c) 2013, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/**
+ @file storage/perfschema/table_replication_group_members.cc
+ Table replication_group_members (implementation).
+*/
+
+#define HAVE_REPLICATION
+
+#include "my_global.h"
+#include "table_replication_group_members.h"
+#include "pfs_instr_class.h"
+#include "pfs_instr.h"
+#include "log.h"
+//#include "rpl_group_replication.h"
+
+/*
+ Callbacks implementation for GROUP_REPLICATION_GROUP_MEMBERS_CALLBACKS.
+*/
+static void set_channel_name(void* const context, const char& value,
+ size_t length)
+{
+ struct st_row_group_members* row=
+ static_cast<struct st_row_group_members*>(context);
+ const size_t max= CHANNEL_NAME_LENGTH;
+ length= std::min(length, max);
+
+ row->channel_name_length= length;
+ memcpy(row->channel_name, &value, length);
+}
+
+static void set_member_id(void* const context, const char& value,
+ size_t length)
+{
+ struct st_row_group_members* row=
+ static_cast<struct st_row_group_members*>(context);
+ const size_t max= UUID_LENGTH;
+ length= std::min(length, max);
+
+ row->member_id_length= length;
+ memcpy(row->member_id, &value, length);
+}
+
+static void set_member_host(void* const context, const char& value,
+ size_t length)
+{
+ struct st_row_group_members* row=
+ static_cast<struct st_row_group_members*>(context);
+ const size_t max= HOSTNAME_LENGTH;
+ length= std::min(length, max);
+
+ row->member_host_length= length;
+ memcpy(row->member_host, &value, length);
+}
+
+static void set_member_port(void* const context, unsigned int value)
+{
+ struct st_row_group_members* row=
+ static_cast<struct st_row_group_members*>(context);
+ row->member_port= value;
+}
+
+static void set_member_state(void* const context, const char& value,
+ size_t length)
+{
+ struct st_row_group_members* row=
+ static_cast<struct st_row_group_members*>(context);
+ const size_t max= NAME_LEN;
+ length= std::min(length, max);
+
+ row->member_state_length= length;
+ memcpy(row->member_state, &value, length);
+}
+
+
+THR_LOCK table_replication_group_members::m_table_lock;
+
+/* Numbers in varchar count utf8 characters. */
+static const TABLE_FIELD_TYPE field_types[]=
+{
+ {
+ {C_STRING_WITH_LEN("CHANNEL_NAME")},
+ {C_STRING_WITH_LEN("char(64)")},
+ {NULL, 0}
+ },
+ {
+ {C_STRING_WITH_LEN("MEMBER_ID")},
+ {C_STRING_WITH_LEN("char(36)")},
+ {NULL, 0}
+ },
+ {
+ {C_STRING_WITH_LEN("MEMBER_HOST")},
+ {C_STRING_WITH_LEN("char(60)")},
+ {NULL, 0}
+ },
+ {
+ {C_STRING_WITH_LEN("MEMBER_PORT")},
+ {C_STRING_WITH_LEN("int(11)")},
+ {NULL, 0}
+ },
+ {
+ {C_STRING_WITH_LEN("MEMBER_STATE")},
+ {C_STRING_WITH_LEN("char(64)")},
+ {NULL, 0}
+ }
+};
+
+TABLE_FIELD_DEF
+table_replication_group_members::m_field_def=
+{ 5, field_types };
+
+PFS_engine_table_share
+table_replication_group_members::m_share=
+{
+ { C_STRING_WITH_LEN("replication_group_members") },
+ &pfs_readonly_acl,
+ &table_replication_group_members::create,
+ NULL, /* write_row */
+ NULL, /* delete_all_rows */
+ table_replication_group_members::get_row_count,
+ sizeof(PFS_simple_index), /* ref length */
+ &m_table_lock,
+ &m_field_def,
+ false, /* checked */
+ false /* perpetual */
+};
+
+PFS_engine_table* table_replication_group_members::create(void)
+{
+ return new table_replication_group_members();
+}
+
+table_replication_group_members::table_replication_group_members()
+ : PFS_engine_table(&m_share, &m_pos),
+ m_row_exists(false), m_pos(0), m_next_pos(0)
+{}
+
+table_replication_group_members::~table_replication_group_members()
+{}
+
+void table_replication_group_members::reset_position(void)
+{
+ m_pos.m_index= 0;
+ m_next_pos.m_index= 0;
+}
+
+ha_rows table_replication_group_members::get_row_count()
+{
+ return get_group_replication_members_number_info();
+}
+
+int table_replication_group_members::rnd_next(void)
+{
+ if (!is_group_replication_plugin_loaded())
+ return HA_ERR_END_OF_FILE;
+
+ for (m_pos.set_at(&m_next_pos);
+ m_pos.m_index < get_row_count();
+ m_pos.next())
+ {
+ make_row(m_pos.m_index);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+
+ return HA_ERR_END_OF_FILE;
+}
+
+int table_replication_group_members::rnd_pos(const void *pos)
+{
+ if (!is_group_replication_plugin_loaded())
+ return HA_ERR_END_OF_FILE;
+
+ set_position(pos);
+ DBUG_ASSERT(m_pos.m_index < get_row_count());
+ make_row(m_pos.m_index);
+
+ return 0;
+}
+
+void table_replication_group_members::make_row(uint index)
+{
+ DBUG_ENTER("table_replication_group_members::make_row");
+ // Set default values.
+ m_row_exists= false;
+ m_row.channel_name_length= 0;
+ m_row.member_id_length= 0;
+ m_row.member_host_length= 0;
+ m_row.member_port= 0;
+ m_row.member_state_length= 0;
+
+ // Set callbacks on GROUP_REPLICATION_GROUP_MEMBERS_CALLBACKS.
+ const GROUP_REPLICATION_GROUP_MEMBERS_CALLBACKS callbacks=
+ {
+ &m_row,
+ &set_channel_name,
+ &set_member_id,
+ &set_member_host,
+ &set_member_port,
+ &set_member_state,
+ };
+
+ // Query plugin and let callbacks do their job.
+ if (get_group_replication_group_members_info(index, callbacks))
+ {
+ DBUG_PRINT("info", ("Group Replication stats not available!"));
+ }
+ else
+ {
+ m_row_exists= true;
+ }
+
+ DBUG_VOID_RETURN;
+}
+
+
+int table_replication_group_members::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;
+
+ 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 0: /** channel_name */
+ set_field_char_utf8(f, m_row.channel_name, m_row.channel_name_length);
+ break;
+ case 1: /** member_id */
+ set_field_char_utf8(f, m_row.member_id, m_row.member_id_length);
+ break;
+ case 2: /** member_host */
+ set_field_char_utf8(f, m_row.member_host, m_row.member_host_length);
+ break;
+ case 3: /** member_port */
+ if (m_row.member_port > 0)
+ set_field_ulong(f, m_row.member_port);
+ else
+ f->set_null();
+ break;
+ case 4: /** member_state */
+ set_field_char_utf8(f, m_row.member_state, m_row.member_state_length);
+ break;
+ default:
+ DBUG_ASSERT(false);
+ }
+ }
+ }
+ return 0;
+}
diff --git a/storage/perfschema/table_replication_group_members.h b/storage/perfschema/table_replication_group_members.h
new file mode 100644
index 00000000000..8ce875eba3a
--- /dev/null
+++ b/storage/perfschema/table_replication_group_members.h
@@ -0,0 +1,108 @@
+/*
+ Copyright (c) 2013, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+
+#ifndef TABLE_REPLICATION_GROUP_MEMBERS_H
+#define TABLE_REPLICATION_GROUP_MEMBERS_H
+
+/**
+ @file storage/perfschema/table_replication_group_members.h
+ Table replication_group_members (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "mysql_com.h"
+//#include "rpl_info.h"
+//#include <mysql/plugin_group_replication.h>
+
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+/**
+ A row in connection nodes table. The fields with string values have an additional
+ length field denoted by <field_name>_length.
+*/
+struct st_row_group_members {
+ char channel_name[CHANNEL_NAME_LENGTH];
+ uint channel_name_length;
+ char member_id[11]; // typeof(server_id) == uint32
+ uint member_id_length;
+ char member_host[HOSTNAME_LENGTH];
+ uint member_host_length;
+ uint member_port;
+ char member_state[NAME_LEN];
+ uint member_state_length;
+};
+
+/** Table PERFORMANCE_SCHEMA.replication_group_members. */
+class table_replication_group_members: public PFS_engine_table
+{
+private:
+ void make_row(uint index);
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /** Fields definition. */
+ static TABLE_FIELD_DEF m_field_def;
+ /** True if the current row exists. */
+ bool m_row_exists;
+ /** Current row */
+ st_row_group_members m_row;
+ /** Current position. */
+ PFS_simple_index m_pos;
+ /** Next position. */
+ PFS_simple_index m_next_pos;
+
+protected:
+ /**
+ Read the current row values.
+ @param table Table handle
+ @param buf row buffer
+ @param fields Table fields
+ @param read_all true if all columns are read.
+ */
+
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+
+ table_replication_group_members();
+
+public:
+ ~table_replication_group_members();
+
+ /** Table share. */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static ha_rows get_row_count();
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+};
+
+/** @} */
+#endif
diff --git a/storage/perfschema/table_session_account_connect_attrs.cc b/storage/perfschema/table_session_account_connect_attrs.cc
index fcb4f001ba7..0e8be68d602 100644
--- a/storage/perfschema/table_session_account_connect_attrs.cc
+++ b/storage/perfschema/table_session_account_connect_attrs.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -29,12 +29,11 @@ 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,
+ &pfs_readonly_world_acl,
+ table_session_account_connect_attrs::create,
NULL, /* write_row */
NULL, /* delete_all_rows */
- NULL, /* get_row_count */
- 1000, /* records */
+ cursor_by_thread_connect_attr::get_row_count,
sizeof(pos_connect_attr_by_thread_by_attr), /* ref length */
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE session_account_connect_attrs("
@@ -42,7 +41,8 @@ table_session_account_connect_attrs::m_share=
"ATTR_NAME VARCHAR(32) NOT NULL,"
"ATTR_VALUE VARCHAR(1024),"
"ORDINAL_POSITION INT"
- ") CHARACTER SET utf8 COLLATE utf8_bin") }
+ ") CHARACTER SET utf8 COLLATE utf8_bin") },
+ false /* perpetual */
};
PFS_engine_table* table_session_account_connect_attrs::create()
diff --git a/storage/perfschema/table_session_account_connect_attrs.h b/storage/perfschema/table_session_account_connect_attrs.h
index 483001fcb91..043f83da184 100644
--- a/storage/perfschema/table_session_account_connect_attrs.h
+++ b/storage/perfschema/table_session_account_connect_attrs.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2012, 2015, 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, version 2.0,
diff --git a/storage/perfschema/table_session_connect.cc b/storage/perfschema/table_session_connect.cc
index 0d12ab2562e..09f32feaa4d 100644
--- a/storage/perfschema/table_session_connect.cc
+++ b/storage/perfschema/table_session_connect.cc
@@ -22,13 +22,14 @@
#include <my_global.h>
#include "table_session_connect.h"
+#include "field.h"
table_session_connect::table_session_connect(const PFS_engine_table_share *share)
: cursor_by_thread_connect_attr(share)
{
if (session_connect_attrs_size_per_thread > 0)
{
- m_copy_session_connect_attrs= (char *) my_malloc(/* 5.7: PSI_INSTRUMENT_ME, */
+ m_copy_session_connect_attrs= (char *) my_malloc(PSI_INSTRUMENT_ME,
session_connect_attrs_size_per_thread,
MYF(0));
}
@@ -146,7 +147,7 @@ bool read_nth_attr(const char *connect_attrs,
if (idx == ordinal)
*attr_name_length= copy_length;
-
+
/* read the value */
if (parse_length_encoded_string(&ptr,
attr_value, max_attr_value, &copy_length,
@@ -168,8 +169,8 @@ bool read_nth_attr(const char *connect_attrs,
void table_session_connect::make_row(PFS_thread *pfs, uint ordinal)
{
- pfs_lock lock;
- pfs_lock session_lock;
+ pfs_optimistic_state lock;
+ pfs_optimistic_state session_lock;
PFS_thread_class *safe_class;
const CHARSET_INFO *cs;
diff --git a/storage/perfschema/table_session_connect.h b/storage/perfschema/table_session_connect.h
index ee1019fe7f2..55433e2571a 100644
--- a/storage/perfschema/table_session_connect.h
+++ b/storage/perfschema/table_session_connect.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2012, 2015, 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, version 2.0,
@@ -59,6 +59,7 @@ struct row_session_connect_attrs
ulong m_ordinal_position;
};
+/** Abstract table PERFORMANCE_SCHEMA.SESSION_CONNECT_ATTRS. */
class table_session_connect : public cursor_by_thread_connect_attr
{
protected:
diff --git a/storage/perfschema/table_session_connect_attrs.cc b/storage/perfschema/table_session_connect_attrs.cc
index cb7b64a7fdf..cc3fae46290 100644
--- a/storage/perfschema/table_session_connect_attrs.cc
+++ b/storage/perfschema/table_session_connect_attrs.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -30,11 +30,10 @@ table_session_connect_attrs::m_share=
{
{ C_STRING_WITH_LEN("session_connect_attrs") },
&pfs_readonly_acl,
- &table_session_connect_attrs::create,
+ table_session_connect_attrs::create,
NULL, /* write_row */
NULL, /* delete_all_rows */
- NULL, /* get_row_count */
- 1000, /* records */
+ cursor_by_thread_connect_attr::get_row_count,
sizeof(pos_connect_attr_by_thread_by_attr), /* ref length */
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE session_connect_attrs("
@@ -42,7 +41,8 @@ table_session_connect_attrs::m_share=
"ATTR_NAME VARCHAR(32) NOT NULL,"
"ATTR_VALUE VARCHAR(1024),"
"ORDINAL_POSITION INT"
- ") CHARACTER SET utf8 COLLATE utf8_bin") }
+ ") CHARACTER SET utf8 COLLATE utf8_bin") },
+ false /* perpetual */
};
PFS_engine_table* table_session_connect_attrs::create()
diff --git a/storage/perfschema/table_session_connect_attrs.h b/storage/perfschema/table_session_connect_attrs.h
index 927c3a92af2..09b9d1c49e1 100644
--- a/storage/perfschema/table_session_connect_attrs.h
+++ b/storage/perfschema/table_session_connect_attrs.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2012, 2015, 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, version 2.0,
diff --git a/storage/perfschema/table_session_status.cc b/storage/perfschema/table_session_status.cc
new file mode 100644
index 00000000000..acff99caed0
--- /dev/null
+++ b/storage/perfschema/table_session_status.cc
@@ -0,0 +1,185 @@
+/* Copyright (c) 2015, 2016, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/**
+ @file storage/perfschema/table_session_status.cc
+ Table SESSION_STATUS (implementation).
+*/
+
+#include "my_global.h"
+#include "my_thread.h"
+#include "table_session_status.h"
+#include "pfs_instr_class.h"
+#include "pfs_column_types.h"
+#include "pfs_column_values.h"
+#include "pfs_global.h"
+
+THR_LOCK table_session_status::m_table_lock;
+
+PFS_engine_table_share
+table_session_status::m_share=
+{
+ { C_STRING_WITH_LEN("session_status") },
+ &pfs_readonly_world_acl,
+ table_session_status::create,
+ NULL, /* write_row */
+ NULL, /* delete_all_rows */
+ table_session_status::get_row_count,
+ sizeof(pos_t),
+ &m_table_lock,
+ { C_STRING_WITH_LEN("CREATE TABLE session_status("
+ "VARIABLE_NAME VARCHAR(64) not null,"
+ "VARIABLE_VALUE VARCHAR(1024))") },
+ true /* perpetual */
+};
+
+PFS_engine_table*
+table_session_status::create(void)
+{
+ return new table_session_status();
+}
+
+ha_rows table_session_status::get_row_count(void)
+{
+ mysql_mutex_lock(&LOCK_status);
+ ha_rows status_var_count= all_status_vars.elements;
+ mysql_mutex_unlock(&LOCK_status);
+ return status_var_count;
+}
+
+table_session_status::table_session_status()
+ : PFS_engine_table(&m_share, &m_pos),
+ m_status_cache(false), m_row_exists(false), m_pos(0), m_next_pos(0)
+{}
+
+void table_session_status::reset_position(void)
+{
+ m_pos.m_index = 0;
+ m_next_pos.m_index = 0;
+}
+
+int table_session_status::rnd_init(bool scan)
+{
+ /* Build a cache of all status variables for this thread. */
+ m_status_cache.materialize_all(current_thd);
+
+ /* Record the current number of status variables to detect subsequent changes. */
+ ulonglong status_version= m_status_cache.get_status_array_version();
+
+ /*
+ The table context holds the current version of the global status array.
+ If scan == true, then allocate a new context from mem_root and store in TLS.
+ If scan == false, then restore from TLS.
+ */
+ m_context= (table_session_status_context *)current_thd->alloc(sizeof(table_session_status_context));
+ new(m_context) table_session_status_context(status_version, !scan);
+ return 0;
+}
+
+int table_session_status::rnd_next(void)
+{
+ for (m_pos.set_at(&m_next_pos);
+ m_pos.m_index < m_status_cache.size();
+ m_pos.next())
+ {
+ if (m_status_cache.is_materialized())
+ {
+ const Status_variable *stat_var= m_status_cache.get(m_pos.m_index);
+ if (stat_var != NULL)
+ {
+ make_row(stat_var);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+ }
+ }
+ return HA_ERR_END_OF_FILE;
+}
+
+int
+table_session_status::rnd_pos(const void *pos)
+{
+ /* If global status array has changed, do nothing. */ // TODO: warning
+ if (!m_context->versions_match())
+ return HA_ERR_RECORD_DELETED;
+
+ set_position(pos);
+ DBUG_ASSERT(m_pos.m_index < m_status_cache.size());
+
+ if (m_status_cache.is_materialized())
+ {
+ const Status_variable *stat_var= m_status_cache.get(m_pos.m_index);
+ if (stat_var != NULL)
+ {
+ make_row(stat_var);
+ return 0;
+ }
+ }
+
+ return HA_ERR_RECORD_DELETED;
+}
+
+void table_session_status
+::make_row(const Status_variable *status_var)
+{
+ m_row_exists= false;
+ m_row.m_variable_name.make_row(status_var->m_name, status_var->m_name_length);
+ m_row.m_variable_value.make_row(status_var);
+ m_row_exists= true;
+}
+
+int table_session_status
+::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 0: /* VARIABLE_NAME */
+ set_field_varchar_utf8(f, m_row.m_variable_name.m_str, m_row.m_variable_name.m_length);
+ break;
+ case 1: /* VARIABLE_VALUE */
+ m_row.m_variable_value.set_field(f);
+ break;
+ default:
+ DBUG_ASSERT(false);
+ }
+ }
+ }
+
+ return 0;
+}
+
diff --git a/storage/perfschema/table_session_status.h b/storage/perfschema/table_session_status.h
new file mode 100644
index 00000000000..24634fe47b5
--- /dev/null
+++ b/storage/perfschema/table_session_status.h
@@ -0,0 +1,119 @@
+/* Copyright (c) 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#ifndef TABLE_SESSION_STATUS_H
+#define TABLE_SESSION_STATUS_H
+
+/**
+ @file storage/perfschema/table_session_status.h
+ Table SESSION_STATUS (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "pfs_instr_class.h"
+#include "pfs_instr.h"
+#include "table_helper.h"
+#include "pfs_variable.h"
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+/**
+ A row of table
+ PERFORMANCE_SCHEMA.SESSION_STATUS.
+*/
+struct row_session_status
+{
+ /** Column THREAD_ID. */
+ ulonglong m_thread_internal_id;
+ /** Column VARIABLE_NAME. */
+ PFS_variable_name_row m_variable_name;
+ /** Column VARIABLE_VALUE. */
+ PFS_variable_value_row m_variable_value;
+};
+
+/**
+ Store and retrieve table state information for queries that reinstantiate
+ the table object.
+*/
+class table_session_status_context : public PFS_table_context
+{
+public:
+ table_session_status_context(ulonglong current_version, bool restore) :
+ PFS_table_context(current_version, restore, THR_PFS_SS) { }
+};
+
+/** Table PERFORMANCE_SCHEMA.SESSION_STATUS. */
+class table_session_status : public PFS_engine_table
+{
+ typedef PFS_simple_index pos_t;
+
+public:
+ /** Table share */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static ha_rows get_row_count();
+
+ virtual int rnd_init(bool scan);
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+protected:
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+ table_session_status();
+
+public:
+ ~table_session_status()
+ {}
+
+protected:
+ void make_row(const Status_variable *status_var);
+
+private:
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /** Fields definition. */
+ static TABLE_FIELD_DEF m_field_def;
+
+ /** Current THD variables. */
+ PFS_status_variable_cache m_status_cache;
+ /** Current row. */
+ row_session_status m_row;
+ /** True if the current row exists. */
+ bool m_row_exists;
+ /** Current position. */
+ pos_t m_pos;
+ /** Next position. */
+ pos_t m_next_pos;
+
+ /** Table context with global status array version. */
+ table_session_status_context *m_context;
+};
+
+/** @} */
+#endif
diff --git a/storage/perfschema/table_session_variables.cc b/storage/perfschema/table_session_variables.cc
new file mode 100644
index 00000000000..f293af4a1cf
--- /dev/null
+++ b/storage/perfschema/table_session_variables.cc
@@ -0,0 +1,187 @@
+/* Copyright (c) 2015, 2018, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/**
+ @file storage/perfschema/table_session_variables.cc
+ Table SESSION_VARIABLES (implementation).
+*/
+
+#include "my_global.h"
+#include "my_thread.h"
+#include "table_session_variables.h"
+#include "pfs_instr_class.h"
+#include "pfs_column_types.h"
+#include "pfs_column_values.h"
+#include "pfs_global.h"
+
+THR_LOCK table_session_variables::m_table_lock;
+
+PFS_engine_table_share
+table_session_variables::m_share=
+{
+ { C_STRING_WITH_LEN("session_variables") },
+ &pfs_readonly_world_acl,
+ table_session_variables::create,
+ NULL, /* write_row */
+ NULL, /* delete_all_rows */
+ table_session_variables::get_row_count,
+ sizeof(pos_t),
+ &m_table_lock,
+ { C_STRING_WITH_LEN("CREATE TABLE session_variables("
+ "VARIABLE_NAME VARCHAR(64) not null,"
+ "VARIABLE_VALUE VARCHAR(1024))") },
+ true /* perpetual */
+};
+
+PFS_engine_table*
+table_session_variables::create(void)
+{
+ return new table_session_variables();
+}
+
+ha_rows table_session_variables::get_row_count(void)
+{
+ mysql_mutex_lock(&LOCK_plugin_delete);
+ mysql_rwlock_rdlock(&LOCK_system_variables_hash);
+ ha_rows system_var_count= get_system_variable_hash_records();
+ mysql_rwlock_unlock(&LOCK_system_variables_hash);
+ mysql_mutex_unlock(&LOCK_plugin_delete);
+ return system_var_count;
+}
+
+table_session_variables::table_session_variables()
+ : PFS_engine_table(&m_share, &m_pos),
+ m_sysvar_cache(false), m_row_exists(false), m_pos(0), m_next_pos(0)
+{}
+
+void table_session_variables::reset_position(void)
+{
+ m_pos.m_index = 0;
+ m_next_pos.m_index = 0;
+}
+
+int table_session_variables::rnd_init(bool scan)
+{
+ /* Build a cache of system variables for this thread. */
+ m_sysvar_cache.materialize_all(current_thd);
+
+ /* Record the version of the system variable hash. */
+ ulonglong hash_version= m_sysvar_cache.get_sysvar_hash_version();
+
+ /*
+ The table context holds the current version of the system variable hash.
+ If scan == true, then allocate a new context from mem_root and store in TLS.
+ If scan == false, then restore from TLS.
+ */
+ m_context= (table_session_variables_context *)current_thd->alloc(sizeof(table_session_variables_context));
+ new(m_context) table_session_variables_context(hash_version, !scan);
+ return 0;
+}
+
+int table_session_variables::rnd_next(void)
+{
+ for (m_pos.set_at(&m_next_pos);
+ m_pos.m_index < m_sysvar_cache.size();
+ m_pos.next())
+ {
+ if (m_sysvar_cache.is_materialized())
+ {
+ const System_variable *system_var= m_sysvar_cache.get(m_pos.m_index);
+ if (system_var != NULL)
+ {
+ make_row(system_var);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+ }
+ }
+ return HA_ERR_END_OF_FILE;
+}
+
+int table_session_variables::rnd_pos(const void *pos)
+{
+ /* If system variable hash changes, do nothing. */
+ if (!m_context->versions_match())
+ return HA_ERR_RECORD_DELETED;
+
+ set_position(pos);
+ DBUG_ASSERT(m_pos.m_index < m_sysvar_cache.size());
+
+ if (m_sysvar_cache.is_materialized())
+ {
+ const System_variable *system_var= m_sysvar_cache.get(m_pos.m_index);
+ if (system_var != NULL)
+ {
+ make_row(system_var);
+ return 0;
+ }
+ }
+ return HA_ERR_RECORD_DELETED;
+}
+
+void table_session_variables
+::make_row(const System_variable *system_var)
+{
+ m_row_exists= false;
+ if (system_var->is_null() || system_var->is_ignored())
+ return;
+ m_row.m_variable_name.make_row(system_var->m_name, system_var->m_name_length);
+ m_row.m_variable_value.make_row(system_var);
+ m_row_exists= true;
+}
+
+int table_session_variables
+::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 0: /* VARIABLE_NAME */
+ set_field_varchar_utf8(f, m_row.m_variable_name.m_str, m_row.m_variable_name.m_length);
+ break;
+ case 1: /* VARIABLE_VALUE */
+ m_row.m_variable_value.set_field(f);
+ break;
+ default:
+ DBUG_ASSERT(false);
+ }
+ }
+ }
+
+ return 0;
+}
+
diff --git a/storage/perfschema/table_session_variables.h b/storage/perfschema/table_session_variables.h
new file mode 100644
index 00000000000..576bf73edbb
--- /dev/null
+++ b/storage/perfschema/table_session_variables.h
@@ -0,0 +1,117 @@
+/* Copyright (c) 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#ifndef TABLE_SESSION_VARIABLES_H
+#define TABLE_SESSION_VARIABLES_H
+
+/**
+ @file storage/perfschema/table_session_variables.h
+ Table SESSION_VARIABLES (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "pfs_instr_class.h"
+#include "pfs_instr.h"
+#include "table_helper.h"
+#include "pfs_variable.h"
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+/**
+ Store and retrieve table state information during queries that reinstantiate
+ the table object.
+*/
+class table_session_variables_context : public PFS_table_context
+{
+public:
+ table_session_variables_context(ulonglong hash_version, bool restore) :
+ PFS_table_context(hash_version, restore, THR_PFS_SV) {}
+};
+
+/**
+ A row of table
+ PERFORMANCE_SCHEMA.SESSION_VARIABLES.
+*/
+struct row_session_variables
+{
+ /** Column VARIABLE_NAME. */
+ PFS_variable_name_row m_variable_name;
+ /** Column VARIABLE_VALUE. */
+ PFS_variable_value_row m_variable_value;
+};
+
+/** Table PERFORMANCE_SCHEMA.SESSION_VARIABLES. */
+class table_session_variables : public PFS_engine_table
+{
+ typedef PFS_simple_index pos_t;
+
+public:
+ /** Table share */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static ha_rows get_row_count();
+
+ virtual int rnd_init(bool scan);
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+protected:
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+ table_session_variables();
+
+public:
+ ~table_session_variables()
+ {}
+
+protected:
+ void make_row(const System_variable *system_var);
+
+private:
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /** Fields definition. */
+ static TABLE_FIELD_DEF m_field_def;
+
+ /** Current THD variables. */
+ PFS_system_variable_cache m_sysvar_cache;
+ /** Current row. */
+ row_session_variables m_row;
+ /** True if the current row exists. */
+ bool m_row_exists;
+ /** Current position. */
+ pos_t m_pos;
+ /** Next position. */
+ pos_t m_next_pos;
+
+ /** Table context with system variable hash version. */
+ table_session_variables_context *m_context;
+};
+
+/** @} */
+#endif
diff --git a/storage/perfschema/table_setup_actors.cc b/storage/perfschema/table_setup_actors.cc
index 007081a83c9..5004dbc7c16 100644
--- a/storage/perfschema/table_setup_actors.cc
+++ b/storage/perfschema/table_setup_actors.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2016, 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, version 2.0,
@@ -26,13 +26,15 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_instr_class.h"
#include "pfs_column_types.h"
#include "pfs_column_values.h"
#include "pfs_setup_actor.h"
#include "table_setup_actors.h"
#include "pfs_global.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
THR_LOCK table_setup_actors::m_table_lock;
@@ -45,13 +47,15 @@ table_setup_actors::m_share=
table_setup_actors::write_row,
table_setup_actors::delete_all_rows,
table_setup_actors::get_row_count,
- 1000, /* records */
sizeof(PFS_simple_index),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE setup_actors("
"HOST CHAR(60) collate utf8_bin default '%' not null,"
- "USER CHAR(16) collate utf8_bin default '%' not null,"
- "ROLE CHAR(16) collate utf8_bin default '%' not null)") }
+ "USER CHAR(" USERNAME_CHAR_LENGTH_STR ") collate utf8_bin default '%' not null,"
+ "ROLE CHAR(16) collate utf8_bin default '%' not null,"
+ "ENABLED ENUM('YES', 'NO') not null,"
+ "HISTORY ENUM('YES', 'NO') not null)") },
+ false /* perpetual */
};
PFS_engine_table* table_setup_actors::create()
@@ -69,6 +73,10 @@ int table_setup_actors::write_row(TABLE *table, const unsigned char *buf,
String *user= &user_data;
String *host= &host_data;
String *role= &role_data;
+ enum_yes_no enabled_value= ENUM_YES;
+ enum_yes_no history_value= ENUM_YES;
+ bool enabled;
+ bool history;
for (; (f= *fields) ; fields++)
{
@@ -85,16 +93,34 @@ int table_setup_actors::write_row(TABLE *table, const unsigned char *buf,
case 2: /* ROLE */
role= get_field_char_utf8(f, &role_data);
break;
+ case 3: /* ENABLED */
+ enabled_value= (enum_yes_no) get_field_enum(f);
+ break;
+ case 4: /* HISTORY */
+ history_value= (enum_yes_no) get_field_enum(f);
+ break;
default:
DBUG_ASSERT(false);
}
}
}
+ /* Reject illegal enum values in ENABLED */
+ if ((enabled_value != ENUM_YES) && (enabled_value != ENUM_NO))
+ return HA_ERR_NO_REFERENCED_ROW;
+
+ /* Reject illegal enum values in HISTORY */
+ if ((history_value != ENUM_YES) && (history_value != ENUM_NO))
+ return HA_ERR_NO_REFERENCED_ROW;
+
+ /* Reject if any of user/host/role is not provided */
if (user->length() == 0 || host->length() == 0 || role->length() == 0)
return HA_ERR_WRONG_COMMAND;
- return insert_setup_actor(user, host, role);
+ enabled= (enabled_value == ENUM_YES) ? true : false;
+ history= (history_value == ENUM_YES) ? true : false;
+
+ return insert_setup_actor(user, host, role, enabled, history);
}
int table_setup_actors::delete_all_rows(void)
@@ -104,7 +130,7 @@ int table_setup_actors::delete_all_rows(void)
ha_rows table_setup_actors::get_row_count(void)
{
- return setup_actor_count();
+ return global_setup_actor_container.get_row_count();
}
table_setup_actors::table_setup_actors()
@@ -122,17 +148,14 @@ int table_setup_actors::rnd_next()
{
PFS_setup_actor *pfs;
- for (m_pos.set_at(&m_next_pos);
- m_pos.m_index < setup_actor_max;
- m_pos.next())
+ m_pos.set_at(&m_next_pos);
+ PFS_setup_actor_iterator it= global_setup_actor_container.iterate(m_pos.m_index);
+ pfs= it.scan_next(& m_pos.m_index);
+ if (pfs != NULL)
{
- pfs= &setup_actor_array[m_pos.m_index];
- if (pfs->m_lock.is_populated())
- {
- make_row(pfs);
- m_next_pos.set_after(&m_pos);
- return 0;
- }
+ make_row(pfs);
+ m_next_pos.set_after(&m_pos);
+ return 0;
}
return HA_ERR_END_OF_FILE;
@@ -144,9 +167,8 @@ int table_setup_actors::rnd_pos(const void *pos)
set_position(pos);
- DBUG_ASSERT(m_pos.m_index < setup_actor_max);
- pfs= &setup_actor_array[m_pos.m_index];
- if (pfs->m_lock.is_populated())
+ pfs= global_setup_actor_container.get(m_pos.m_index);
+ if (pfs != NULL)
{
make_row(pfs);
return 0;
@@ -157,7 +179,7 @@ int table_setup_actors::rnd_pos(const void *pos)
void table_setup_actors::make_row(PFS_setup_actor *pfs)
{
- pfs_lock lock;
+ pfs_optimistic_state lock;
m_row_exists= false;
@@ -181,6 +203,9 @@ void table_setup_actors::make_row(PFS_setup_actor *pfs)
return;
memcpy(m_row.m_rolename, pfs->m_rolename, m_row.m_rolename_length);
+ m_row.m_enabled_ptr= &pfs->m_enabled;
+ m_row.m_history_ptr= &pfs->m_history;
+
if (pfs->m_lock.end_optimistic_lock(&lock))
m_row_exists= true;
}
@@ -213,6 +238,12 @@ int table_setup_actors::read_row_values(TABLE *table,
case 2: /* ROLE */
set_field_char_utf8(f, m_row.m_rolename, m_row.m_rolename_length);
break;
+ case 3: /* ENABLED */
+ set_field_enum(f, (*m_row.m_enabled_ptr) ? ENUM_YES : ENUM_NO);
+ break;
+ case 4: /* HISTORY */
+ set_field_enum(f, (*m_row.m_history_ptr) ? ENUM_YES : ENUM_NO);
+ break;
default:
DBUG_ASSERT(false);
}
@@ -227,7 +258,9 @@ int table_setup_actors::update_row_values(TABLE *table,
const unsigned char *new_buf,
Field **fields)
{
+ int result;
Field *f;
+ enum_yes_no value;
for (; (f= *fields) ; fields++)
{
@@ -239,6 +272,19 @@ int table_setup_actors::update_row_values(TABLE *table,
case 1: /* USER */
case 2: /* ROLE */
return HA_ERR_WRONG_COMMAND;
+ case 3: /* ENABLED */
+ value= (enum_yes_no) get_field_enum(f);
+ /* Reject illegal enum values in ENABLED */
+ if ((value != ENUM_YES) && (value != ENUM_NO))
+ return HA_ERR_NO_REFERENCED_ROW;
+ *m_row.m_enabled_ptr= (value == ENUM_YES) ? true : false;
+ break;
+ case 4: /* HISTORY */
+ value= (enum_yes_no) get_field_enum(f);
+ /* Reject illegal enum values in HISTORY */
+ if ((value != ENUM_YES) && (value != ENUM_NO))
+ return HA_ERR_NO_REFERENCED_ROW;
+ *m_row.m_history_ptr= (value == ENUM_YES) ? true : false;
break;
default:
DBUG_ASSERT(false);
@@ -246,7 +292,8 @@ int table_setup_actors::update_row_values(TABLE *table,
}
}
- return 0;
+ result= update_setup_actors_derived_flags();
+ return result;
}
int table_setup_actors::delete_row_values(TABLE *table,
diff --git a/storage/perfschema/table_setup_actors.h b/storage/perfschema/table_setup_actors.h
index 6bfc480a9c5..32a603317b9 100644
--- a/storage/perfschema/table_setup_actors.h
+++ b/storage/perfschema/table_setup_actors.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -52,6 +52,10 @@ struct row_setup_actors
char m_rolename[16];
/** Length in bytes of @c m_rolename. */
uint m_rolename_length;
+ /** Column ENABLED. */
+ bool *m_enabled_ptr;
+ /** Column HISTORY. */
+ bool *m_history_ptr;
};
/** Table PERFORMANCE_SCHEMA.SETUP_ACTORS. */
diff --git a/storage/perfschema/table_setup_consumers.cc b/storage/perfschema/table_setup_consumers.cc
index 7355efae45b..1745bf35c56 100644
--- a/storage/perfschema/table_setup_consumers.cc
+++ b/storage/perfschema/table_setup_consumers.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -26,73 +26,105 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "table_setup_consumers.h"
#include "pfs_instr.h"
#include "pfs_events_waits.h"
#include "pfs_digest.h"
+#include "field.h"
+
+#define COUNT_SETUP_CONSUMERS 15
-#define COUNT_SETUP_CONSUMERS 12
static row_setup_consumers all_setup_consumers_data[COUNT_SETUP_CONSUMERS]=
{
{
{ C_STRING_WITH_LEN("events_stages_current") },
&flag_events_stages_current,
+ false,
false
},
{
{ C_STRING_WITH_LEN("events_stages_history") },
&flag_events_stages_history,
- false
+ false,
+ true
},
{
{ C_STRING_WITH_LEN("events_stages_history_long") },
&flag_events_stages_history_long,
- false
+ false,
+ true
},
{
{ C_STRING_WITH_LEN("events_statements_current") },
&flag_events_statements_current,
+ false,
false
},
{
{ C_STRING_WITH_LEN("events_statements_history") },
&flag_events_statements_history,
- false
+ false,
+ true
},
{
{ C_STRING_WITH_LEN("events_statements_history_long") },
&flag_events_statements_history_long,
+ false,
+ true
+ },
+ {
+ { C_STRING_WITH_LEN("events_transactions_current") },
+ &flag_events_transactions_current,
+ false,
false
},
{
+ { C_STRING_WITH_LEN("events_transactions_history") },
+ &flag_events_transactions_history,
+ false,
+ true
+ },
+ {
+ { C_STRING_WITH_LEN("events_transactions_history_long") },
+ &flag_events_transactions_history_long,
+ false,
+ true
+ },
+ {
{ C_STRING_WITH_LEN("events_waits_current") },
&flag_events_waits_current,
+ false,
false
},
{
{ C_STRING_WITH_LEN("events_waits_history") },
&flag_events_waits_history,
- false
+ false,
+ true
},
{
{ C_STRING_WITH_LEN("events_waits_history_long") },
&flag_events_waits_history_long,
- false
+ false,
+ true
},
{
{ C_STRING_WITH_LEN("global_instrumentation") },
&flag_global_instrumentation,
+ true,
true
},
{
{ C_STRING_WITH_LEN("thread_instrumentation") },
&flag_thread_instrumentation,
- false
+ false,
+ true
},
{
{ C_STRING_WITH_LEN("statements_digest") },
&flag_statements_digest,
+ false,
false
}
};
@@ -104,16 +136,16 @@ table_setup_consumers::m_share=
{
{ C_STRING_WITH_LEN("setup_consumers") },
&pfs_updatable_acl,
- &table_setup_consumers::create,
+ table_setup_consumers::create,
NULL, /* write_row */
NULL, /* delete_all_rows */
- NULL, /* get_row_count */
- COUNT_SETUP_CONSUMERS, /* records */
+ table_setup_consumers::get_row_count,
sizeof(PFS_simple_index), /* ref length */
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE setup_consumers("
"NAME VARCHAR(64) not null,"
- "ENABLED ENUM ('YES', 'NO') not null)") }
+ "ENABLED ENUM ('YES', 'NO') not null)") },
+ false /* perpetual */
};
PFS_engine_table* table_setup_consumers::create(void)
@@ -121,6 +153,12 @@ PFS_engine_table* table_setup_consumers::create(void)
return new table_setup_consumers();
}
+ha_rows
+table_setup_consumers::get_row_count(void)
+{
+ return COUNT_SETUP_CONSUMERS;
+}
+
table_setup_consumers::table_setup_consumers()
: PFS_engine_table(&m_share, &m_pos),
m_row(NULL), m_pos(0), m_next_pos(0)
@@ -225,9 +263,12 @@ int table_setup_consumers::update_row_values(TABLE *table,
}
}
- if (m_row->m_refresh)
+ if (m_row->m_instrument_refresh)
update_instruments_derived_flags();
+ if (m_row->m_thread_refresh)
+ update_thread_derived_flags();
+
return 0;
}
diff --git a/storage/perfschema/table_setup_consumers.h b/storage/perfschema/table_setup_consumers.h
index 90da55920c6..9d601622adf 100644
--- a/storage/perfschema/table_setup_consumers.h
+++ b/storage/perfschema/table_setup_consumers.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -43,8 +43,10 @@ struct row_setup_consumers
LEX_STRING m_name;
/** Column ENABLED. */
bool *m_enabled_ptr;
- /** Hidden column, refresh. */
- bool m_refresh;
+ /** Hidden column, instrument refresh. */
+ bool m_instrument_refresh;
+ /** Hidden column, thread refresh. */
+ bool m_thread_refresh;
};
/** Table PERFORMANCE_SCHEMA.SETUP_CONSUMERS. */
@@ -54,6 +56,7 @@ public:
/** Table share. */
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
+ static ha_rows get_row_count();
virtual int rnd_next();
virtual int rnd_pos(const void *pos);
diff --git a/storage/perfschema/table_setup_instruments.cc b/storage/perfschema/table_setup_instruments.cc
index 490226c7c83..69e48b9c2ad 100644
--- a/storage/perfschema/table_setup_instruments.cc
+++ b/storage/perfschema/table_setup_instruments.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -26,14 +26,16 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_instr_class.h"
+#include "pfs_builtin_memory.h"
#include "pfs_instr.h"
#include "pfs_column_types.h"
#include "pfs_column_values.h"
#include "table_setup_instruments.h"
#include "pfs_global.h"
#include "pfs_setup_object.h"
+#include "field.h"
THR_LOCK table_setup_instruments::m_table_lock;
@@ -42,17 +44,17 @@ table_setup_instruments::m_share=
{
{ C_STRING_WITH_LEN("setup_instruments") },
&pfs_updatable_acl,
- &table_setup_instruments::create,
+ table_setup_instruments::create,
NULL, /* write_row */
NULL, /* delete_all_rows */
- NULL, /* get_row_count */
- 1000, /* records */
+ table_setup_instruments::get_row_count,
sizeof(pos_setup_instruments),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE setup_instruments("
"NAME VARCHAR(128) not null,"
"ENABLED ENUM ('YES', 'NO') not null,"
- "TIMED ENUM ('YES', 'NO') not null)") }
+ "TIMED ENUM ('YES', 'NO') not null)") },
+ false /* perpetual */
};
PFS_engine_table* table_setup_instruments::create(void)
@@ -60,6 +62,16 @@ PFS_engine_table* table_setup_instruments::create(void)
return new table_setup_instruments();
}
+ha_rows
+table_setup_instruments::get_row_count(void)
+{
+ return wait_class_max
+ + stage_class_max
+ + statement_class_max
+ + transaction_class_max
+ + memory_class_max;
+}
+
table_setup_instruments::table_setup_instruments()
: PFS_engine_table(&m_share, &m_pos),
m_pos(), m_next_pos()
@@ -74,6 +86,9 @@ void table_setup_instruments::reset_position(void)
int table_setup_instruments::rnd_next(void)
{
PFS_instr_class *instr_class= NULL;
+ PFS_builtin_memory_class *pfs_builtin;
+ bool update_enabled;
+ bool update_timed;
/* Do not advertise hard coded instruments when disabled. */
if (! pfs_initialized)
@@ -83,6 +98,9 @@ int table_setup_instruments::rnd_next(void)
m_pos.has_more_view();
m_pos.next_view())
{
+ update_enabled= true;
+ update_timed= true;
+
switch (m_pos.m_index_1)
{
case pos_setup_instruments::VIEW_MUTEX:
@@ -109,16 +127,35 @@ int table_setup_instruments::rnd_next(void)
case pos_setup_instruments::VIEW_STATEMENT:
instr_class= find_statement_class(m_pos.m_index_2);
break;
+ case pos_setup_instruments::VIEW_TRANSACTION:
+ instr_class= find_transaction_class(m_pos.m_index_2);
+ break;
case pos_setup_instruments::VIEW_SOCKET:
instr_class= find_socket_class(m_pos.m_index_2);
break;
case pos_setup_instruments::VIEW_IDLE:
instr_class= find_idle_class(m_pos.m_index_2);
break;
+ case pos_setup_instruments::VIEW_BUILTIN_MEMORY:
+ update_enabled= false;
+ update_timed= false;
+ pfs_builtin= find_builtin_memory_class(m_pos.m_index_2);
+ if (pfs_builtin != NULL)
+ instr_class= & pfs_builtin->m_class;
+ else
+ instr_class= NULL;
+ break;
+ case pos_setup_instruments::VIEW_MEMORY:
+ update_timed= false;
+ instr_class= find_memory_class(m_pos.m_index_2);
+ break;
+ case pos_setup_instruments::VIEW_METADATA:
+ instr_class= find_metadata_class(m_pos.m_index_2);
+ break;
}
if (instr_class)
{
- make_row(instr_class);
+ make_row(instr_class, update_enabled, update_timed);
m_next_pos.set_after(&m_pos);
return 0;
}
@@ -130,6 +167,9 @@ int table_setup_instruments::rnd_next(void)
int table_setup_instruments::rnd_pos(const void *pos)
{
PFS_instr_class *instr_class= NULL;
+ PFS_builtin_memory_class *pfs_builtin;
+ bool update_enabled;
+ bool update_timed;
/* Do not advertise hard coded instruments when disabled. */
if (! pfs_initialized)
@@ -137,6 +177,9 @@ int table_setup_instruments::rnd_pos(const void *pos)
set_position(pos);
+ update_enabled= true;
+ update_timed= true;
+
switch (m_pos.m_index_1)
{
case pos_setup_instruments::VIEW_MUTEX:
@@ -163,25 +206,46 @@ int table_setup_instruments::rnd_pos(const void *pos)
case pos_setup_instruments::VIEW_STATEMENT:
instr_class= find_statement_class(m_pos.m_index_2);
break;
+ case pos_setup_instruments::VIEW_TRANSACTION:
+ instr_class= find_transaction_class(m_pos.m_index_2);
+ break;
case pos_setup_instruments::VIEW_SOCKET:
instr_class= find_socket_class(m_pos.m_index_2);
break;
case pos_setup_instruments::VIEW_IDLE:
instr_class= find_idle_class(m_pos.m_index_2);
break;
+ case pos_setup_instruments::VIEW_BUILTIN_MEMORY:
+ update_enabled= false;
+ update_timed= false;
+ pfs_builtin= find_builtin_memory_class(m_pos.m_index_2);
+ if (pfs_builtin != NULL)
+ instr_class= & pfs_builtin->m_class;
+ else
+ instr_class= NULL;
+ break;
+ case pos_setup_instruments::VIEW_MEMORY:
+ update_timed= false;
+ instr_class= find_memory_class(m_pos.m_index_2);
+ break;
+ case pos_setup_instruments::VIEW_METADATA:
+ instr_class= find_metadata_class(m_pos.m_index_2);
+ break;
}
if (instr_class)
{
- make_row(instr_class);
+ make_row(instr_class, update_enabled, update_timed);
return 0;
}
return HA_ERR_RECORD_DELETED;
}
-void table_setup_instruments::make_row(PFS_instr_class *klass)
+void table_setup_instruments::make_row(PFS_instr_class *klass, bool update_enabled, bool update_timed)
{
m_row.m_instr_class= klass;
+ m_row.m_update_enabled= update_enabled;
+ m_row.m_update_timed= update_timed;
}
int table_setup_instruments::read_row_values(TABLE *table,
@@ -239,12 +303,20 @@ int table_setup_instruments::update_row_values(TABLE *table,
case 0: /* NAME */
return HA_ERR_WRONG_COMMAND;
case 1: /* ENABLED */
- value= (enum_yes_no) get_field_enum(f);
- m_row.m_instr_class->m_enabled= (value == ENUM_YES) ? true : false;
+ /* Do not raise error if m_update_enabled is false, silently ignore. */
+ if (m_row.m_update_enabled)
+ {
+ value= (enum_yes_no) get_field_enum(f);
+ m_row.m_instr_class->m_enabled= (value == ENUM_YES) ? true : false;
+ }
break;
case 2: /* TIMED */
- value= (enum_yes_no) get_field_enum(f);
- m_row.m_instr_class->m_timed= (value == ENUM_YES) ? true : false;
+ /* Do not raise error if m_update_timed is false, silently ignore. */
+ if (m_row.m_update_timed)
+ {
+ value= (enum_yes_no) get_field_enum(f);
+ m_row.m_instr_class->m_timed= (value == ENUM_YES) ? true : false;
+ }
break;
default:
DBUG_ASSERT(false);
@@ -274,6 +346,7 @@ int table_setup_instruments::update_row_values(TABLE *table,
break;
case pos_setup_instruments::VIEW_STAGE:
case pos_setup_instruments::VIEW_STATEMENT:
+ case pos_setup_instruments::VIEW_TRANSACTION:
/* No flag to update. */
break;
case pos_setup_instruments::VIEW_SOCKET:
@@ -282,6 +355,13 @@ int table_setup_instruments::update_row_values(TABLE *table,
case pos_setup_instruments::VIEW_IDLE:
/* No flag to update. */
break;
+ case pos_setup_instruments::VIEW_BUILTIN_MEMORY:
+ case pos_setup_instruments::VIEW_MEMORY:
+ /* No flag to update. */
+ break;
+ case pos_setup_instruments::VIEW_METADATA:
+ update_metadata_derived_flags();
+ break;
default:
DBUG_ASSERT(false);
break;
diff --git a/storage/perfschema/table_setup_instruments.h b/storage/perfschema/table_setup_instruments.h
index cd3715cfe55..42aa2dd91d0 100644
--- a/storage/perfschema/table_setup_instruments.h
+++ b/storage/perfschema/table_setup_instruments.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -41,6 +41,10 @@ struct row_setup_instruments
{
/** Columns NAME, ENABLED, TIMED. */
PFS_instr_class *m_instr_class;
+ /** True if column ENABLED can be updated. */
+ bool m_update_enabled;
+ /** True if column TIMED can be updated. */
+ bool m_update_timed;
};
/** Position of a cursor on PERFORMANCE_SCHEMA.SETUP_INSTRUMENTS. */
@@ -55,9 +59,13 @@ struct pos_setup_instruments : public PFS_double_index
static const uint VIEW_TABLE= 6;
static const uint VIEW_STAGE= 7;
static const uint VIEW_STATEMENT= 8;
- static const uint VIEW_SOCKET= 9;
- static const uint VIEW_IDLE= 10;
- static const uint LAST_VIEW= 10;
+ static const uint VIEW_TRANSACTION=9;
+ static const uint VIEW_SOCKET= 10;
+ static const uint VIEW_IDLE= 11;
+ static const uint VIEW_BUILTIN_MEMORY= 12;
+ static const uint VIEW_MEMORY= 13;
+ static const uint VIEW_METADATA= 14;
+ static const uint LAST_VIEW= 14;
pos_setup_instruments()
: PFS_double_index(FIRST_VIEW, 1)
@@ -86,6 +94,7 @@ public:
/** Table share. */
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
+ static ha_rows get_row_count();
virtual int rnd_next();
virtual int rnd_pos(const void *pos);
@@ -109,7 +118,7 @@ public:
{}
private:
- void make_row(PFS_instr_class *klass);
+ void make_row(PFS_instr_class *klass, bool update_enabled, bool update_timed);
/** Table share lock. */
static THR_LOCK m_table_lock;
diff --git a/storage/perfschema/table_setup_objects.cc b/storage/perfschema/table_setup_objects.cc
index ce8b7e73927..23d4bcaab0f 100644
--- a/storage/perfschema/table_setup_objects.cc
+++ b/storage/perfschema/table_setup_objects.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -26,7 +26,7 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_instr.h"
#include "pfs_column_types.h"
#include "pfs_column_values.h"
@@ -34,6 +34,8 @@
#include "table_setup_objects.h"
#include "table_helper.h"
#include "pfs_global.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
THR_LOCK table_setup_objects::m_table_lock;
@@ -46,15 +48,16 @@ table_setup_objects::m_share=
table_setup_objects::write_row,
table_setup_objects::delete_all_rows,
table_setup_objects::get_row_count,
- 1000, /* records */
sizeof(PFS_simple_index),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE setup_objects("
- "OBJECT_TYPE ENUM ('TABLE') not null default 'TABLE',"
+ "OBJECT_TYPE ENUM ('EVENT','FUNCTION','PROCEDURE','TABLE','TRIGGER') not null default 'EVENT',"
+
"OBJECT_SCHEMA VARCHAR(64) default '%',"
"OBJECT_NAME VARCHAR(64) not null default '%',"
"ENABLED ENUM ('YES', 'NO') not null default 'YES',"
- "TIMED ENUM ('YES', 'NO') not null default 'YES')") }
+ "TIMED ENUM ('YES', 'NO') not null default 'YES')") },
+ false /* perpetual */
};
int update_derived_flags()
@@ -64,6 +67,7 @@ int update_derived_flags()
return HA_ERR_OUT_OF_MEM;
update_table_share_derived_flags(thread);
+ update_program_share_derived_flags(thread);
update_table_derived_flags();
return 0;
}
@@ -116,7 +120,9 @@ int table_setup_objects::write_row(TABLE *table, const unsigned char *buf,
}
/* Reject illegal enum values in OBJECT_TYPE */
- if (object_type != OBJECT_TYPE_TABLE)
+ if (object_type < FIRST_OBJECT_TYPE ||
+ object_type > LAST_OBJECT_TYPE ||
+ object_type == OBJECT_TYPE_TEMPORARY_TABLE)
return HA_ERR_NO_REFERENCED_ROW;
/* Reject illegal enum values in ENABLED */
@@ -147,7 +153,7 @@ int table_setup_objects::delete_all_rows(void)
ha_rows table_setup_objects::get_row_count(void)
{
- return setup_object_count();
+ return global_setup_object_container.get_row_count();
}
table_setup_objects::table_setup_objects()
@@ -165,17 +171,14 @@ int table_setup_objects::rnd_next(void)
{
PFS_setup_object *pfs;
- for (m_pos.set_at(&m_next_pos);
- m_pos.m_index < setup_object_max;
- m_pos.next())
+ m_pos.set_at(&m_next_pos);
+ PFS_setup_object_iterator it= global_setup_object_container.iterate(m_pos.m_index);
+ pfs= it.scan_next(& m_pos.m_index);
+ if (pfs != NULL)
{
- pfs= &setup_object_array[m_pos.m_index];
- if (pfs->m_lock.is_populated())
- {
- make_row(pfs);
- m_next_pos.set_after(&m_pos);
- return 0;
- }
+ make_row(pfs);
+ m_next_pos.set_after(&m_pos);
+ return 0;
}
return HA_ERR_END_OF_FILE;
@@ -187,9 +190,8 @@ int table_setup_objects::rnd_pos(const void *pos)
set_position(pos);
- DBUG_ASSERT(m_pos.m_index < setup_object_max);
- pfs= &setup_object_array[m_pos.m_index];
- if (pfs->m_lock.is_populated())
+ pfs= global_setup_object_container.get(m_pos.m_index);
+ if (pfs != NULL)
{
make_row(pfs);
return 0;
@@ -200,7 +202,7 @@ int table_setup_objects::rnd_pos(const void *pos)
void table_setup_objects::make_row(PFS_setup_object *pfs)
{
- pfs_lock lock;
+ pfs_optimistic_state lock;
m_row_exists= false;
diff --git a/storage/perfschema/table_setup_objects.h b/storage/perfschema/table_setup_objects.h
index 570acc865ad..abe36f73818 100644
--- a/storage/perfschema/table_setup_objects.h
+++ b/storage/perfschema/table_setup_objects.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
diff --git a/storage/perfschema/table_setup_timers.cc b/storage/perfschema/table_setup_timers.cc
index a2d34828f08..e43a9943fc6 100644
--- a/storage/perfschema/table_setup_timers.cc
+++ b/storage/perfschema/table_setup_timers.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2017, 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, version 2.0,
@@ -26,12 +26,14 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "table_setup_timers.h"
#include "pfs_column_values.h"
#include "pfs_timer.h"
+#include "field.h"
+#include "derror.h" /* ER_THD */
-#define COUNT_SETUP_TIMERS 4
+#define COUNT_SETUP_TIMERS 5
static row_setup_timers all_setup_timers_data[COUNT_SETUP_TIMERS]=
{
@@ -50,6 +52,10 @@ static row_setup_timers all_setup_timers_data[COUNT_SETUP_TIMERS]=
{
{ C_STRING_WITH_LEN("statement") },
&statement_timer
+ },
+ {
+ { C_STRING_WITH_LEN("transaction") },
+ &transaction_timer
}
};
@@ -60,23 +66,36 @@ table_setup_timers::m_share=
{
{ C_STRING_WITH_LEN("setup_timers") },
&pfs_updatable_acl,
- &table_setup_timers::create,
+ table_setup_timers::create,
NULL, /* write_row */
NULL, /* delete_all_rows */
- NULL, /* get_row_count */
- COUNT_SETUP_TIMERS,
+ table_setup_timers::get_row_count,
sizeof(PFS_simple_index),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE setup_timers("
"NAME VARCHAR(64) not null,"
- "TIMER_NAME ENUM ('CYCLE', 'NANOSECOND', 'MICROSECOND', 'MILLISECOND', 'TICK') not null)") }
+ "TIMER_NAME ENUM ('CYCLE', 'NANOSECOND', 'MICROSECOND', 'MILLISECOND', 'TICK') not null)") },
+ false /* perpetual */
};
PFS_engine_table* table_setup_timers::create(void)
{
+ THD *thd = current_thd;
+ push_warning_printf(thd,
+ Sql_condition::SL_WARNING,
+ ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT,
+ ER_THD(thd, ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT),
+ "performance_schema.setup_timers");
+
return new table_setup_timers();
}
+ha_rows
+table_setup_timers::get_row_count(void)
+{
+ return COUNT_SETUP_TIMERS;
+}
+
table_setup_timers::table_setup_timers()
: PFS_engine_table(&m_share, &m_pos),
m_row(NULL), m_pos(0), m_next_pos(0)
diff --git a/storage/perfschema/table_setup_timers.h b/storage/perfschema/table_setup_timers.h
index d591f3e0b67..43100bf3dd0 100644
--- a/storage/perfschema/table_setup_timers.h
+++ b/storage/perfschema/table_setup_timers.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -52,6 +52,7 @@ public:
/** Table share. */
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
+ static ha_rows get_row_count();
virtual int rnd_next();
virtual int rnd_pos(const void *pos);
diff --git a/storage/perfschema/table_socket_instances.cc b/storage/perfschema/table_socket_instances.cc
index 920531136d5..24c9b0d02a9 100644
--- a/storage/perfschema/table_socket_instances.cc
+++ b/storage/perfschema/table_socket_instances.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -26,12 +26,14 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_instr.h"
#include "pfs_column_types.h"
#include "pfs_column_values.h"
#include "table_socket_instances.h"
#include "pfs_global.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
THR_LOCK table_socket_instances::m_table_lock;
@@ -40,11 +42,10 @@ table_socket_instances::m_share=
{
{ C_STRING_WITH_LEN("socket_instances") },
&pfs_readonly_acl,
- &table_socket_instances::create,
+ table_socket_instances::create,
NULL, /* write_row */
NULL, /* delete_all_rows */
- NULL, /* get_row_count */
- 1000, /* records */
+ table_socket_instances::get_row_count,
sizeof(PFS_simple_index),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE socket_instances("
@@ -54,7 +55,8 @@ table_socket_instances::m_share=
"SOCKET_ID INTEGER not null,"
"IP VARCHAR(64) not null,"
"PORT INTEGER not null,"
- "STATE ENUM('IDLE','ACTIVE') not null)") }
+ "STATE ENUM('IDLE','ACTIVE') not null)") },
+ false /* perpetual */
};
PFS_engine_table* table_socket_instances::create(void)
@@ -62,6 +64,12 @@ PFS_engine_table* table_socket_instances::create(void)
return new table_socket_instances();
}
+ha_rows
+table_socket_instances::get_row_count(void)
+{
+ return global_socket_container.get_row_count();
+}
+
table_socket_instances::table_socket_instances()
: PFS_engine_table(&m_share, &m_pos),
m_row_exists(false), m_pos(0), m_next_pos(0)
@@ -77,17 +85,14 @@ int table_socket_instances::rnd_next(void)
{
PFS_socket *pfs;
- for (m_pos.set_at(&m_next_pos);
- m_pos.m_index < socket_max;
- m_pos.next())
+ m_pos.set_at(&m_next_pos);
+ PFS_socket_iterator it= global_socket_container.iterate(m_pos.m_index);
+ pfs= it.scan_next(& m_pos.m_index);
+ if (pfs != NULL)
{
- pfs= &socket_array[m_pos.m_index];
- if (pfs->m_lock.is_populated())
- {
- make_row(pfs);
- m_next_pos.set_after(&m_pos);
- return 0;
- }
+ make_row(pfs);
+ m_next_pos.set_after(&m_pos);
+ return 0;
}
return HA_ERR_END_OF_FILE;
@@ -98,19 +103,20 @@ int table_socket_instances::rnd_pos(const void *pos)
PFS_socket *pfs;
set_position(pos);
- DBUG_ASSERT(m_pos.m_index < socket_max);
- pfs= &socket_array[m_pos.m_index];
- if (! pfs->m_lock.is_populated())
- return HA_ERR_RECORD_DELETED;
+ pfs= global_socket_container.get(m_pos.m_index);
+ if (pfs != NULL)
+ {
+ make_row(pfs);
+ return 0;
+ }
- make_row(pfs);
- return 0;
+ return HA_ERR_RECORD_DELETED;
}
void table_socket_instances::make_row(PFS_socket *pfs)
{
- pfs_lock lock;
+ pfs_optimistic_state lock;
PFS_socket_class *safe_class;
m_row_exists= false;
diff --git a/storage/perfschema/table_socket_instances.h b/storage/perfschema/table_socket_instances.h
index 41b5ee3fd21..4e32bbdcd00 100644
--- a/storage/perfschema/table_socket_instances.h
+++ b/storage/perfschema/table_socket_instances.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -70,6 +70,7 @@ public:
/** Table share */
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
+ static ha_rows get_row_count();
virtual int rnd_next();
virtual int rnd_pos(const void *pos);
diff --git a/storage/perfschema/table_socket_summary_by_event_name.cc b/storage/perfschema/table_socket_summary_by_event_name.cc
index c813d45b732..bdfff75614d 100644
--- a/storage/perfschema/table_socket_summary_by_event_name.cc
+++ b/storage/perfschema/table_socket_summary_by_event_name.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -26,13 +26,14 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_instr.h"
#include "pfs_column_types.h"
#include "pfs_column_values.h"
#include "table_socket_summary_by_event_name.h"
#include "pfs_global.h"
#include "pfs_visitor.h"
+#include "field.h"
THR_LOCK table_socket_summary_by_event_name::m_table_lock;
@@ -41,11 +42,10 @@ table_socket_summary_by_event_name::m_share=
{
{ C_STRING_WITH_LEN("socket_summary_by_event_name") },
&pfs_readonly_acl,
- &table_socket_summary_by_event_name::create,
+ table_socket_summary_by_event_name::create,
NULL, /* write_row */
table_socket_summary_by_event_name::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ table_socket_summary_by_event_name::get_row_count,
sizeof(PFS_simple_index),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE socket_summary_by_event_name("
@@ -71,7 +71,8 @@ table_socket_summary_by_event_name::m_share=
"SUM_TIMER_MISC BIGINT unsigned not null,"
"MIN_TIMER_MISC BIGINT unsigned not null,"
"AVG_TIMER_MISC BIGINT unsigned not null,"
- "MAX_TIMER_MISC BIGINT unsigned not null)") }
+ "MAX_TIMER_MISC BIGINT unsigned not null)") },
+ false /* perpetual */
};
PFS_engine_table* table_socket_summary_by_event_name::create(void)
@@ -91,6 +92,12 @@ int table_socket_summary_by_event_name::delete_all_rows(void)
return 0;
}
+ha_rows
+table_socket_summary_by_event_name::get_row_count(void)
+{
+ return socket_class_max;
+}
+
void table_socket_summary_by_event_name::reset_position(void)
{
m_pos.m_index= 1;
@@ -138,7 +145,7 @@ void table_socket_summary_by_event_name::make_row(PFS_socket_class *socket_class
PFS_instance_iterator::visit_socket_instances(socket_class, &visitor);
time_normalizer *normalizer= time_normalizer::get(wait_timer);
-
+
/* Collect timer and byte count stats */
m_row.m_io_stat.set(normalizer, &visitor.m_socket_io_stat);
m_row_exists= true;
diff --git a/storage/perfschema/table_socket_summary_by_event_name.h b/storage/perfschema/table_socket_summary_by_event_name.h
index 4f679d89b09..e25d38b9bfa 100644
--- a/storage/perfschema/table_socket_summary_by_event_name.h
+++ b/storage/perfschema/table_socket_summary_by_event_name.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -60,6 +60,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_next();
virtual int rnd_pos(const void *pos);
diff --git a/storage/perfschema/table_socket_summary_by_instance.cc b/storage/perfschema/table_socket_summary_by_instance.cc
index a4b1477aa90..372cde61a87 100644
--- a/storage/perfschema/table_socket_summary_by_instance.cc
+++ b/storage/perfschema/table_socket_summary_by_instance.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -26,12 +26,14 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_instr.h"
#include "pfs_column_types.h"
#include "pfs_column_values.h"
#include "table_socket_summary_by_instance.h"
#include "pfs_global.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
THR_LOCK table_socket_summary_by_instance::m_table_lock;
@@ -40,11 +42,10 @@ table_socket_summary_by_instance::m_share=
{
{ C_STRING_WITH_LEN("socket_summary_by_instance") },
&pfs_readonly_acl,
- &table_socket_summary_by_instance::create,
+ table_socket_summary_by_instance::create,
NULL, /* write_row */
table_socket_summary_by_instance::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ table_socket_summary_by_instance::get_row_count,
sizeof(PFS_simple_index),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE socket_summary_by_instance("
@@ -71,7 +72,8 @@ table_socket_summary_by_instance::m_share=
"SUM_TIMER_MISC BIGINT unsigned not null,"
"MIN_TIMER_MISC BIGINT unsigned not null,"
"AVG_TIMER_MISC BIGINT unsigned not null,"
- "MAX_TIMER_MISC BIGINT unsigned not null)") }
+ "MAX_TIMER_MISC BIGINT unsigned not null)") },
+ false /* perpetual */
};
PFS_engine_table* table_socket_summary_by_instance::create(void)
@@ -90,6 +92,12 @@ int table_socket_summary_by_instance::delete_all_rows(void)
return 0;
}
+ha_rows
+table_socket_summary_by_instance::get_row_count(void)
+{
+ return global_socket_container.get_row_count();
+}
+
void table_socket_summary_by_instance::reset_position(void)
{
m_pos.m_index= 0;
@@ -100,17 +108,14 @@ int table_socket_summary_by_instance::rnd_next(void)
{
PFS_socket *pfs;
- for (m_pos.set_at(&m_next_pos);
- m_pos.m_index < socket_max;
- m_pos.next())
+ m_pos.set_at(&m_next_pos);
+ PFS_socket_iterator it= global_socket_container.iterate(m_pos.m_index);
+ pfs= it.scan_next(& m_pos.m_index);
+ if (pfs != NULL)
{
- pfs= &socket_array[m_pos.m_index];
- if (pfs->m_lock.is_populated())
- {
- make_row(pfs);
- m_next_pos.set_after(&m_pos);
- return 0;
- }
+ make_row(pfs);
+ m_next_pos.set_after(&m_pos);
+ return 0;
}
return HA_ERR_END_OF_FILE;
@@ -121,19 +126,20 @@ int table_socket_summary_by_instance::rnd_pos(const void *pos)
PFS_socket *pfs;
set_position(pos);
- DBUG_ASSERT(m_pos.m_index < socket_max);
- pfs= &socket_array[m_pos.m_index];
- if (! pfs->m_lock.is_populated())
- return HA_ERR_RECORD_DELETED;
+ pfs= global_socket_container.get(m_pos.m_index);
+ if (pfs != NULL)
+ {
+ make_row(pfs);
+ return 0;
+ }
- make_row(pfs);
- return 0;
+ return HA_ERR_RECORD_DELETED;
}
void table_socket_summary_by_instance::make_row(PFS_socket *pfs)
{
- pfs_lock lock;
+ pfs_optimistic_state lock;
PFS_socket_class *safe_class;
m_row_exists= false;
diff --git a/storage/perfschema/table_socket_summary_by_instance.h b/storage/perfschema/table_socket_summary_by_instance.h
index a9eab8d18b6..3f6d1295728 100644
--- a/storage/perfschema/table_socket_summary_by_instance.h
+++ b/storage/perfschema/table_socket_summary_by_instance.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -63,6 +63,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_next();
virtual int rnd_pos(const void *pos);
diff --git a/storage/perfschema/table_status_by_account.cc b/storage/perfschema/table_status_by_account.cc
new file mode 100644
index 00000000000..30a1b6db036
--- /dev/null
+++ b/storage/perfschema/table_status_by_account.cc
@@ -0,0 +1,246 @@
+/* Copyright (c) 2015, 2016, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/**
+ @file storage/perfschema/table_status_by_account.cc
+ Table STATUS_BY_ACCOUNT (implementation).
+*/
+
+#include "my_global.h"
+#include "table_status_by_account.h"
+#include "my_thread.h"
+#include "pfs_instr_class.h"
+#include "pfs_column_types.h"
+#include "pfs_column_values.h"
+#include "pfs_global.h"
+#include "pfs_account.h"
+
+THR_LOCK table_status_by_account::m_table_lock;
+
+PFS_engine_table_share
+table_status_by_account::m_share=
+{
+ { C_STRING_WITH_LEN("status_by_account") },
+ &pfs_truncatable_acl,
+ table_status_by_account::create,
+ NULL, /* write_row */
+ table_status_by_account::delete_all_rows,
+ table_status_by_account::get_row_count,
+ sizeof(pos_t),
+ &m_table_lock,
+ { C_STRING_WITH_LEN("CREATE TABLE status_by_account("
+ "USER CHAR(32) collate utf8_bin default null,"
+ "HOST CHAR(60) collate utf8_bin default null,"
+ "VARIABLE_NAME VARCHAR(64) not null,"
+ "VARIABLE_VALUE VARCHAR(1024))") },
+ false /* perpetual */
+};
+
+PFS_engine_table*
+table_status_by_account::create(void)
+{
+ return new table_status_by_account();
+}
+
+int table_status_by_account::delete_all_rows(void)
+{
+ mysql_mutex_lock(&LOCK_status);
+ reset_status_by_thread();
+ reset_status_by_account();
+ mysql_mutex_unlock(&LOCK_status);
+ return 0;
+}
+
+ha_rows table_status_by_account::get_row_count(void)
+{
+ mysql_mutex_lock(&LOCK_status);
+ size_t status_var_count= all_status_vars.elements;
+ mysql_mutex_unlock(&LOCK_status);
+ return (global_account_container.get_row_count() * status_var_count);
+}
+
+table_status_by_account::table_status_by_account()
+ : PFS_engine_table(&m_share, &m_pos),
+ m_status_cache(true), m_row_exists(false), m_pos(), m_next_pos()
+{}
+
+void table_status_by_account::reset_position(void)
+{
+ m_pos.reset();
+ m_next_pos.reset();
+}
+
+int table_status_by_account::rnd_init(bool scan)
+{
+ if (show_compatibility_56)
+ return 0;
+
+ /*
+ Build array of SHOW_VARs from the global status array prior to materializing
+ threads in rnd_next() or rnd_pos().
+ */
+ m_status_cache.initialize_client_session();
+
+ /* Use the current number of status variables to detect changes. */
+ ulonglong status_version= m_status_cache.get_status_array_version();
+
+ /*
+ The table context holds the current version of the global status array
+ and a record of which accounts were materialized. If scan == true, then
+ allocate a new context from mem_root and store in TLS. If scan == false,
+ then restore from TLS.
+ */
+ m_context= (table_status_by_account_context *)current_thd->alloc(sizeof(table_status_by_account_context));
+ new(m_context) table_status_by_account_context(status_version, !scan);
+ return 0;
+}
+
+int table_status_by_account::rnd_next(void)
+{
+ if (show_compatibility_56)
+ return HA_ERR_END_OF_FILE;
+
+ /* If status array changes, exit with warning. */ // TODO: Issue warning
+ if (!m_context->versions_match())
+ return HA_ERR_END_OF_FILE;
+
+ /*
+ For each account, build a cache of status variables using totals from all
+ threads associated with the account.
+ */
+ bool has_more_account= true;
+
+ for (m_pos.set_at(&m_next_pos);
+ has_more_account;
+ m_pos.next_account())
+ {
+ PFS_account *pfs_account= global_account_container.get(m_pos.m_index_1, &has_more_account);
+
+ if (m_status_cache.materialize_account(pfs_account) == 0)
+ {
+ /* Mark this account as materialized. */
+ m_context->set_item(m_pos.m_index_1);
+
+ /* Get the next status variable. */
+ const Status_variable *stat_var= m_status_cache.get(m_pos.m_index_2);
+ if (stat_var != NULL)
+ {
+ make_row(pfs_account, stat_var);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+ }
+ }
+ return HA_ERR_END_OF_FILE;
+}
+
+int
+table_status_by_account::rnd_pos(const void *pos)
+{
+ if (show_compatibility_56)
+ return HA_ERR_RECORD_DELETED;
+
+ /* If status array changes, exit with warning. */ // TODO: Issue warning
+ if (!m_context->versions_match())
+ return HA_ERR_END_OF_FILE;
+
+ set_position(pos);
+ DBUG_ASSERT(m_pos.m_index_1 < global_account_container.get_row_count());
+
+ PFS_account *pfs_account= global_account_container.get(m_pos.m_index_1);
+
+ /*
+ Only materialize threads that were previously materialized by rnd_next().
+ If a account cannot be rematerialized, then do nothing.
+ */
+ if (m_context->is_item_set(m_pos.m_index_1) &&
+ m_status_cache.materialize_account(pfs_account) == 0)
+ {
+ const Status_variable *stat_var= m_status_cache.get(m_pos.m_index_2);
+ if (stat_var != NULL)
+ {
+ make_row(pfs_account, stat_var);
+ return 0;
+ }
+ }
+ return HA_ERR_RECORD_DELETED;
+}
+
+void table_status_by_account
+::make_row(PFS_account *pfs_account, const Status_variable *status_var)
+{
+ pfs_optimistic_state lock;
+ m_row_exists= false;
+ pfs_account->m_lock.begin_optimistic_lock(&lock);
+
+ if (m_row.m_account.make_row(pfs_account))
+ return;
+
+ m_row.m_variable_name.make_row(status_var->m_name, status_var->m_name_length);
+ m_row.m_variable_value.make_row(status_var);
+
+ if (!pfs_account->m_lock.end_optimistic_lock(&lock))
+ return;
+
+ m_row_exists= true;
+}
+
+int table_status_by_account
+::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 0: /* USER */
+ case 1: /* HOST */
+ m_row.m_account.set_field(f->field_index, f);
+ break;
+ case 2: /* VARIABLE_NAME */
+ set_field_varchar_utf8(f, m_row.m_variable_name.m_str, m_row.m_variable_name.m_length);
+ break;
+ case 3: /* VARIABLE_VALUE */
+ m_row.m_variable_value.set_field(f);
+ break;
+ default:
+ DBUG_ASSERT(false);
+ }
+ }
+ }
+
+ return 0;
+}
+
diff --git a/storage/perfschema/table_status_by_account.h b/storage/perfschema/table_status_by_account.h
new file mode 100644
index 00000000000..401a184d8f1
--- /dev/null
+++ b/storage/perfschema/table_status_by_account.h
@@ -0,0 +1,156 @@
+/* Copyright (c) 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#ifndef TABLE_STATUS_BY_ACCOUNT_H
+#define TABLE_STATUS_BY_ACCOUNT_H
+
+/**
+ @file storage/perfschema/table_status_by_account.h
+ Table STATUS_BY_ACCOUNT (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "pfs_instr_class.h"
+#include "pfs_instr.h"
+#include "pfs_account.h"
+#include "pfs_account.h"
+#include "pfs_host.h"
+#include "table_helper.h"
+#include "pfs_variable.h"
+#include "pfs_buffer_container.h"
+
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+/**
+ A row of table
+ PERFORMANCE_SCHEMA.STATUS_BY_ACCOUNT.
+*/
+struct row_status_by_account
+{
+ /** Column USER, HOST. */
+ PFS_account_row m_account;
+ /** Column VARIABLE_NAME. */
+ PFS_variable_name_row m_variable_name;
+ /** Column VARIABLE_VALUE. */
+ PFS_variable_value_row m_variable_value;
+};
+
+/**
+ Position of a cursor on
+ PERFORMANCE_SCHEMA.STATUS_BY_ACCOUNT.
+ Index 1 on account (0 based)
+ Index 2 on status variable (0 based)
+*/
+struct pos_status_by_account
+: public PFS_double_index
+{
+ pos_status_by_account()
+ : PFS_double_index(0, 0)
+ {}
+
+ inline void reset(void)
+ {
+ m_index_1= 0;
+ m_index_2= 0;
+ }
+
+ inline bool has_more_account(void)
+ { return (m_index_1 < global_account_container.get_row_count()); }
+
+ inline void next_account(void)
+ {
+ m_index_1++;
+ m_index_2= 0;
+ }
+};
+
+/**
+ Store and retrieve table state information for queries that reinstantiate
+ the table object.
+*/
+class table_status_by_account_context : public PFS_table_context
+{
+public:
+ table_status_by_account_context(ulonglong current_version, bool restore) :
+ PFS_table_context(current_version, global_account_container.get_row_count(), restore, THR_PFS_SBH) { }
+};
+
+/** Table PERFORMANCE_SCHEMA.STATUS_BY_ACCOUNT. */
+class table_status_by_account : public PFS_engine_table
+{
+ typedef pos_status_by_account pos_t;
+
+public:
+ /** Table share */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static int delete_all_rows();
+ static ha_rows get_row_count();
+
+ virtual int rnd_init(bool scan);
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+protected:
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+ table_status_by_account();
+
+public:
+ ~table_status_by_account()
+ {}
+
+protected:
+ int materialize(PFS_thread *pfs_thread);
+ void make_row(PFS_account *pfs_account, const Status_variable *status_var);
+
+private:
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /** Fields definition. */
+ static TABLE_FIELD_DEF m_field_def;
+
+ /** Status variable cache for one account. */
+ PFS_status_variable_cache m_status_cache;
+
+ /** Current row. */
+ row_status_by_account m_row;
+ /** True if the current row exists. */
+ bool m_row_exists;
+ /** Current position. */
+ pos_t m_pos;
+ /** Next position. */
+ pos_t m_next_pos;
+
+ /** Table context with global status array version and map of materialized threads. */
+ table_status_by_account_context *m_context;
+};
+
+/** @} */
+#endif
diff --git a/storage/perfschema/table_status_by_host.cc b/storage/perfschema/table_status_by_host.cc
new file mode 100644
index 00000000000..cd41fcaa469
--- /dev/null
+++ b/storage/perfschema/table_status_by_host.cc
@@ -0,0 +1,245 @@
+/* Copyright (c) 2015, 2016, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/**
+ @file storage/perfschema/table_status_by_host.cc
+ Table STATUS_BY_HOST (implementation).
+*/
+
+#include "my_global.h"
+#include "table_status_by_host.h"
+#include "my_thread.h"
+#include "pfs_instr_class.h"
+#include "pfs_column_types.h"
+#include "pfs_column_values.h"
+#include "pfs_global.h"
+#include "pfs_account.h"
+
+THR_LOCK table_status_by_host::m_table_lock;
+
+PFS_engine_table_share
+table_status_by_host::m_share=
+{
+ { C_STRING_WITH_LEN("status_by_host") },
+ &pfs_truncatable_acl,
+ table_status_by_host::create,
+ NULL, /* write_row */
+ table_status_by_host::delete_all_rows,
+ table_status_by_host::get_row_count,
+ sizeof(pos_t),
+ &m_table_lock,
+ { C_STRING_WITH_LEN("CREATE TABLE status_by_host("
+ "HOST CHAR(60) collate utf8_bin default null,"
+ "VARIABLE_NAME VARCHAR(64) not null,"
+ "VARIABLE_VALUE VARCHAR(1024))") },
+ false /* perpetual */
+};
+
+PFS_engine_table*
+table_status_by_host::create(void)
+{
+ return new table_status_by_host();
+}
+
+int table_status_by_host::delete_all_rows(void)
+{
+ mysql_mutex_lock(&LOCK_status);
+ reset_status_by_thread();
+ reset_status_by_account();
+ reset_status_by_host();
+ mysql_mutex_unlock(&LOCK_status);
+ return 0;
+}
+
+ha_rows table_status_by_host::get_row_count(void)
+{
+ mysql_mutex_lock(&LOCK_status);
+ size_t status_var_count= all_status_vars.elements;
+ mysql_mutex_unlock(&LOCK_status);
+ return (global_host_container.get_row_count() * status_var_count);
+}
+
+table_status_by_host::table_status_by_host()
+ : PFS_engine_table(&m_share, &m_pos),
+ m_status_cache(true), m_row_exists(false), m_pos(), m_next_pos()
+{}
+
+void table_status_by_host::reset_position(void)
+{
+ m_pos.reset();
+ m_next_pos.reset();
+}
+
+int table_status_by_host::rnd_init(bool scan)
+{
+ if (show_compatibility_56)
+ return 0;
+
+ /*
+ Build array of SHOW_VARs from the global status array prior to materializing
+ threads in rnd_next() or rnd_pos().
+ */
+ m_status_cache.initialize_client_session();
+
+ /* Use the current number of status variables to detect changes. */
+ ulonglong status_version= m_status_cache.get_status_array_version();
+
+ /*
+ The table context holds the current version of the global status array
+ and a record of which hosts were materialized. If scan == true, then
+ allocate a new context from mem_root and store in TLS. If scan == false,
+ then restore from TLS.
+ */
+ m_context= (table_status_by_host_context *)current_thd->alloc(sizeof(table_status_by_host_context));
+ new(m_context) table_status_by_host_context(status_version, !scan);
+ return 0;
+}
+
+int table_status_by_host::rnd_next(void)
+{
+ if (show_compatibility_56)
+ return HA_ERR_END_OF_FILE;
+
+ /* If status array changes, exit with warning. */ // TODO: Issue warning
+ if (!m_context->versions_match())
+ return HA_ERR_END_OF_FILE;
+
+ /*
+ For each user, build a cache of status variables using totals from all
+ threads associated with the host.
+ */
+ bool has_more_host= true;
+
+ for (m_pos.set_at(&m_next_pos);
+ has_more_host;
+ m_pos.next_host())
+ {
+ PFS_host *pfs_host= global_host_container.get(m_pos.m_index_1, &has_more_host);
+
+ if (m_status_cache.materialize_host(pfs_host) == 0)
+ {
+ /* Mark this host as materialized. */
+ m_context->set_item(m_pos.m_index_1);
+
+ /* Get the next status variable. */
+ const Status_variable *stat_var= m_status_cache.get(m_pos.m_index_2);
+ if (stat_var != NULL)
+ {
+ make_row(pfs_host, stat_var);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+ }
+ }
+ return HA_ERR_END_OF_FILE;
+}
+
+int
+table_status_by_host::rnd_pos(const void *pos)
+{
+ if (show_compatibility_56)
+ return 0;
+
+ /* If status array changes, exit with warning. */ // TODO: Issue warning
+ if (!m_context->versions_match())
+ return HA_ERR_END_OF_FILE;
+
+ set_position(pos);
+ DBUG_ASSERT(m_pos.m_index_1 < global_host_container.get_row_count());
+
+ PFS_host *pfs_host= global_host_container.get(m_pos.m_index_1);
+
+ /*
+ Only materialize threads that were previously materialized by rnd_next().
+ If a host cannot be rematerialized, then do nothing.
+ */
+ if (m_context->is_item_set(m_pos.m_index_1) &&
+ m_status_cache.materialize_host(pfs_host) == 0)
+ {
+ const Status_variable *stat_var= m_status_cache.get(m_pos.m_index_2);
+ if (stat_var != NULL)
+ {
+ make_row(pfs_host, stat_var);
+ return 0;
+ }
+ }
+ return HA_ERR_RECORD_DELETED;
+}
+
+void table_status_by_host
+::make_row(PFS_host *pfs_host, const Status_variable *status_var)
+{
+ pfs_optimistic_state lock;
+ m_row_exists= false;
+ pfs_host->m_lock.begin_optimistic_lock(&lock);
+
+ if (m_row.m_host.make_row(pfs_host))
+ return;
+
+ m_row.m_variable_name.make_row(status_var->m_name, status_var->m_name_length);
+ m_row.m_variable_value.make_row(status_var);
+
+ if (!pfs_host->m_lock.end_optimistic_lock(&lock))
+ return;
+
+ m_row_exists= true;
+}
+
+int table_status_by_host
+::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 0: /* HOST */
+ m_row.m_host.set_field(f);
+ break;
+ case 1: /* VARIABLE_NAME */
+ set_field_varchar_utf8(f, m_row.m_variable_name.m_str, m_row.m_variable_name.m_length);
+ break;
+ case 2: /* VARIABLE_VALUE */
+ m_row.m_variable_value.set_field(f);
+ break;
+ default:
+ DBUG_ASSERT(false);
+ }
+ }
+ }
+
+ return 0;
+}
+
diff --git a/storage/perfschema/table_status_by_host.h b/storage/perfschema/table_status_by_host.h
new file mode 100644
index 00000000000..e4c6bf256ef
--- /dev/null
+++ b/storage/perfschema/table_status_by_host.h
@@ -0,0 +1,154 @@
+/* Copyright (c) 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#ifndef TABLE_STATUS_BY_HOST_H
+#define TABLE_STATUS_BY_HOST_H
+
+/**
+ @file storage/perfschema/table_status_by_host.h
+ Table STATUS_BY_HOST (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "pfs_instr_class.h"
+#include "pfs_instr.h"
+#include "pfs_host.h"
+#include "table_helper.h"
+#include "pfs_variable.h"
+#include "pfs_buffer_container.h"
+
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+/**
+ A row of table
+ PERFORMANCE_SCHEMA.STATUS_BY_HOST.
+*/
+struct row_status_by_host
+{
+ /** Column HOST */
+ PFS_host_row m_host;
+ /** Column VARIABLE_NAME. */
+ PFS_variable_name_row m_variable_name;
+ /** Column VARIABLE_VALUE. */
+ PFS_variable_value_row m_variable_value;
+};
+
+/**
+ Position of a cursor on
+ PERFORMANCE_SCHEMA.STATUS_BY_HOST.
+ Index 1 on host (0 based)
+ Index 2 on status variable (0 based)
+*/
+struct pos_status_by_host
+: public PFS_double_index
+{
+ pos_status_by_host()
+ : PFS_double_index(0, 0)
+ {}
+
+ inline void reset(void)
+ {
+ m_index_1= 0;
+ m_index_2= 0;
+ }
+
+ inline bool has_more_host(void)
+ { return (m_index_1 < global_host_container.get_row_count()); }
+
+ inline void next_host(void)
+ {
+ m_index_1++;
+ m_index_2= 0;
+ }
+};
+
+/**
+ Store and retrieve table state information for queries that reinstantiate
+ the table object.
+*/
+class table_status_by_host_context : public PFS_table_context
+{
+public:
+ table_status_by_host_context(ulonglong current_version, bool restore) :
+ PFS_table_context(current_version, global_host_container.get_row_count(), restore, THR_PFS_SBH) { }
+};
+
+/** Table PERFORMANCE_SCHEMA.STATUS_BY_HOST. */
+class table_status_by_host : public PFS_engine_table
+{
+ typedef pos_status_by_host pos_t;
+
+public:
+ /** Table share */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static int delete_all_rows();
+ static ha_rows get_row_count();
+
+ virtual int rnd_init(bool scan);
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+protected:
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+ table_status_by_host();
+
+public:
+ ~table_status_by_host()
+ {}
+
+protected:
+ int materialize(PFS_thread *thread);
+ void make_row(PFS_host *pfs_host, const Status_variable *status_var);
+
+private:
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /** Fields definition. */
+ static TABLE_FIELD_DEF m_field_def;
+
+ /** Status variable cache for one host. */
+ PFS_status_variable_cache m_status_cache;
+
+ /** Current row. */
+ row_status_by_host m_row;
+ /** True if the current row exists. */
+ bool m_row_exists;
+ /** Current position. */
+ pos_t m_pos;
+ /** Next position. */
+ pos_t m_next_pos;
+
+ /** Table context with global status array version and map of materialized threads. */
+ table_status_by_host_context *m_context;
+};
+
+/** @} */
+#endif
diff --git a/storage/perfschema/table_status_by_thread.cc b/storage/perfschema/table_status_by_thread.cc
new file mode 100644
index 00000000000..d9af7e49aa4
--- /dev/null
+++ b/storage/perfschema/table_status_by_thread.cc
@@ -0,0 +1,239 @@
+/* Copyright (c) 2015, 2016, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/**
+ @file storage/perfschema/table_status_by_thread.cc
+ Table STATUS_BY_THREAD (implementation).
+*/
+
+#include "my_global.h"
+#include "table_status_by_thread.h"
+#include "my_thread.h"
+#include "pfs_instr_class.h"
+#include "pfs_column_types.h"
+#include "pfs_column_values.h"
+#include "pfs_global.h"
+
+THR_LOCK table_status_by_thread::m_table_lock;
+
+PFS_engine_table_share
+table_status_by_thread::m_share=
+{
+ { C_STRING_WITH_LEN("status_by_thread") },
+ &pfs_truncatable_acl,
+ table_status_by_thread::create,
+ NULL, /* write_row */
+ table_status_by_thread::delete_all_rows,
+ table_status_by_thread::get_row_count,
+ sizeof(pos_t),
+ &m_table_lock,
+ { C_STRING_WITH_LEN("CREATE TABLE status_by_thread("
+ "THREAD_ID BIGINT unsigned not null,"
+ "VARIABLE_NAME VARCHAR(64) not null,"
+ "VARIABLE_VALUE VARCHAR(1024))") },
+ false /* perpetual */
+};
+
+PFS_engine_table*
+table_status_by_thread::create(void)
+{
+ return new table_status_by_thread();
+}
+
+int table_status_by_thread::delete_all_rows(void)
+{
+ /* Lock required to aggregate to global_status_vars. */
+ mysql_mutex_lock(&LOCK_status);
+
+ reset_status_by_thread();
+
+ mysql_mutex_unlock(&LOCK_status);
+ return 0;
+}
+
+ha_rows table_status_by_thread::get_row_count(void)
+{
+ mysql_mutex_lock(&LOCK_status);
+ size_t status_var_count= all_status_vars.elements;
+ mysql_mutex_unlock(&LOCK_status);
+ return (global_thread_container.get_row_count() * status_var_count);
+}
+
+table_status_by_thread::table_status_by_thread()
+ : PFS_engine_table(&m_share, &m_pos),
+ m_status_cache(true), m_row_exists(false), m_pos(), m_next_pos()
+{}
+
+void table_status_by_thread::reset_position(void)
+{
+ m_pos.reset();
+ m_next_pos.reset();
+}
+
+int table_status_by_thread::rnd_init(bool scan)
+{
+ if (show_compatibility_56)
+ return 0;
+
+ /*
+ Build array of SHOW_VARs from the global status array prior to materializing
+ threads in rnd_next() or rnd_pos().
+ */
+ m_status_cache.initialize_session();
+
+ /* Record the current number of status variables to detect subsequent changes. */
+ ulonglong status_version= m_status_cache.get_status_array_version();
+
+ /*
+ The table context holds the current version of the global status array
+ and a record of which threads were materialized. If scan == true, then
+ allocate a new context from mem_root and store in TLS. If scan == false,
+ then restore from TLS.
+ */
+ m_context= (table_status_by_thread_context *)current_thd->alloc(sizeof(table_status_by_thread_context));
+ new(m_context) table_status_by_thread_context(status_version, !scan);
+ return 0;
+}
+
+int table_status_by_thread::rnd_next(void)
+{
+ if (show_compatibility_56)
+ return HA_ERR_END_OF_FILE;
+
+ /* If global status array changes, exit with warning. */ // TODO: Issue warning
+ if (!m_context->versions_match())
+ return HA_ERR_END_OF_FILE;
+
+ bool has_more_thread= true;
+
+ for (m_pos.set_at(&m_next_pos);
+ has_more_thread;
+ m_pos.next_thread())
+ {
+ PFS_thread *pfs_thread= global_thread_container.get(m_pos.m_index_1, &has_more_thread);
+ if (m_status_cache.materialize_session(pfs_thread) == 0)
+ {
+ /* Mark this thread as materialized. */
+ m_context->set_item(m_pos.m_index_1);
+ const Status_variable *stat_var= m_status_cache.get(m_pos.m_index_2);
+ if (stat_var != NULL)
+ {
+ make_row(pfs_thread, stat_var);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+ }
+ }
+ return HA_ERR_END_OF_FILE;
+}
+
+int
+table_status_by_thread::rnd_pos(const void *pos)
+{
+ if (show_compatibility_56)
+ return HA_ERR_RECORD_DELETED;
+
+ /* If global status array has changed, do nothing. */
+ if (!m_context->versions_match())
+ return HA_ERR_RECORD_DELETED;
+
+ set_position(pos);
+ DBUG_ASSERT(m_pos.m_index_1 < global_thread_container.get_row_count());
+
+ PFS_thread *pfs_thread= global_thread_container.get(m_pos.m_index_1);
+ /*
+ Only materialize threads that were previously materialized by rnd_next().
+ If a thread cannot be rematerialized, then do nothing.
+ */
+ if (m_context->is_item_set(m_pos.m_index_1) &&
+ m_status_cache.materialize_session(pfs_thread) == 0)
+ {
+ const Status_variable *stat_var= m_status_cache.get(m_pos.m_index_2);
+ if (stat_var != NULL)
+ {
+ make_row(pfs_thread, stat_var);
+ return 0;
+ }
+ }
+ return HA_ERR_RECORD_DELETED;
+}
+
+void table_status_by_thread
+::make_row(PFS_thread *thread, const Status_variable *status_var)
+{
+ pfs_optimistic_state lock;
+ m_row_exists= false;
+ if (status_var->is_null())
+ return;
+
+ /* Protect this reader against a thread termination */
+ thread->m_lock.begin_optimistic_lock(&lock);
+
+ m_row.m_thread_internal_id= thread->m_thread_internal_id;
+ m_row.m_variable_name.make_row(status_var->m_name, status_var->m_name_length);
+ m_row.m_variable_value.make_row(status_var);
+
+ if (!thread->m_lock.end_optimistic_lock(&lock))
+ return;
+
+ m_row_exists= true;
+}
+
+int table_status_by_thread
+::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 0: /* THREAD_ID */
+ set_field_ulonglong(f, m_row.m_thread_internal_id);
+ break;
+ case 1: /* VARIABLE_NAME */
+ set_field_varchar_utf8(f, m_row.m_variable_name.m_str, m_row.m_variable_name.m_length);
+ break;
+ case 2: /* VARIABLE_VALUE */
+ m_row.m_variable_value.set_field(f);
+ break;
+ default:
+ DBUG_ASSERT(false);
+ }
+ }
+ }
+
+ return 0;
+}
+
diff --git a/storage/perfschema/table_status_by_thread.h b/storage/perfschema/table_status_by_thread.h
new file mode 100644
index 00000000000..f8de21dc41e
--- /dev/null
+++ b/storage/perfschema/table_status_by_thread.h
@@ -0,0 +1,151 @@
+/* Copyright (c) 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#ifndef TABLE_STATUS_BY_THREAD_H
+#define TABLE_STATUS_BY_THREAD_H
+
+/**
+ @file storage/perfschema/table_status_by_thread.h
+ Table STATUS_BY_THREAD (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "pfs_instr_class.h"
+#include "pfs_instr.h"
+#include "table_helper.h"
+#include "pfs_variable.h"
+#include "pfs_buffer_container.h"
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+/**
+ A row of table
+ PERFORMANCE_SCHEMA.STATUS_BY_THREAD.
+*/
+struct row_status_by_thread
+{
+ /** Column THREAD_ID. */
+ ulonglong m_thread_internal_id;
+ /** Column VARIABLE_NAME. */
+ PFS_variable_name_row m_variable_name;
+ /** Column VARIABLE_VALUE. */
+ PFS_variable_value_row m_variable_value;
+};
+
+/**
+ Position of a cursor on
+ PERFORMANCE_SCHEMA.STATUS_BY_THREAD.
+ Index 1 on thread (0 based)
+ Index 2 on status variable (0 based)
+*/
+struct pos_status_by_thread
+: public PFS_double_index
+{
+ pos_status_by_thread()
+ : PFS_double_index(0, 0)
+ {}
+
+ inline void reset(void)
+ {
+ m_index_1= 0;
+ m_index_2= 0;
+ }
+
+ inline bool has_more_thread(void)
+ { return (m_index_1 < global_thread_container.get_row_count()); }
+
+ inline void next_thread(void)
+ {
+ m_index_1++;
+ m_index_2= 0;
+ }
+};
+
+/**
+ Store and retrieve table state information for queries that reinstantiate
+ the table object.
+*/
+class table_status_by_thread_context : public PFS_table_context
+{
+public:
+ table_status_by_thread_context(ulonglong current_version, bool restore) :
+ PFS_table_context(current_version, global_thread_container.get_row_count(), restore, THR_PFS_SBT) { }
+};
+
+/** Table PERFORMANCE_SCHEMA.STATUS_BY_THREAD. */
+class table_status_by_thread : public PFS_engine_table
+{
+ typedef pos_status_by_thread pos_t;
+
+public:
+ /** Table share */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static int delete_all_rows();
+ static ha_rows get_row_count();
+
+ virtual int rnd_init(bool scan);
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+protected:
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+ table_status_by_thread();
+
+public:
+ ~table_status_by_thread()
+ {}
+
+protected:
+ int materialize(PFS_thread *thread);
+ void make_row(PFS_thread *thread, const Status_variable *status_var);
+
+private:
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /** Fields definition. */
+ static TABLE_FIELD_DEF m_field_def;
+
+ /** Current THD variables. */
+ PFS_status_variable_cache m_status_cache;
+ /** Current row. */
+ row_status_by_thread m_row;
+ /** True if the current row exists. */
+ bool m_row_exists;
+ /** Current position. */
+ pos_t m_pos;
+ /** Next position. */
+ pos_t m_next_pos;
+
+ /** Table context with global status array version and map of materialized threads. */
+ table_status_by_thread_context *m_context;
+};
+
+/** @} */
+#endif
diff --git a/storage/perfschema/table_status_by_user.cc b/storage/perfschema/table_status_by_user.cc
new file mode 100644
index 00000000000..921a72247b6
--- /dev/null
+++ b/storage/perfschema/table_status_by_user.cc
@@ -0,0 +1,246 @@
+/* Copyright (c) 2015, 2016, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/**
+ @file storage/perfschema/table_status_by_user.cc
+ Table STATUS_BY_USER (implementation).
+*/
+
+#include "my_global.h"
+#include "table_status_by_user.h"
+#include "my_thread.h"
+#include "pfs_instr_class.h"
+#include "pfs_column_types.h"
+#include "pfs_column_values.h"
+#include "pfs_global.h"
+#include "pfs_account.h"
+#include "pfs_visitor.h"
+
+THR_LOCK table_status_by_user::m_table_lock;
+
+PFS_engine_table_share
+table_status_by_user::m_share=
+{
+ { C_STRING_WITH_LEN("status_by_user") },
+ &pfs_truncatable_acl,
+ table_status_by_user::create,
+ NULL, /* write_row */
+ table_status_by_user::delete_all_rows,
+ table_status_by_user::get_row_count,
+ sizeof(pos_t),
+ &m_table_lock,
+ { C_STRING_WITH_LEN("CREATE TABLE status_by_user("
+ "USER CHAR(32) collate utf8_bin default null,"
+ "VARIABLE_NAME VARCHAR(64) not null,"
+ "VARIABLE_VALUE VARCHAR(1024))") },
+ false /* perpetual */
+};
+
+PFS_engine_table*
+table_status_by_user::create(void)
+{
+ return new table_status_by_user();
+}
+
+int table_status_by_user::delete_all_rows(void)
+{
+ mysql_mutex_lock(&LOCK_status);
+ reset_status_by_thread();
+ reset_status_by_account();
+ reset_status_by_user();
+ mysql_mutex_unlock(&LOCK_status);
+ return 0;
+}
+
+ha_rows table_status_by_user::get_row_count(void)
+{
+ mysql_mutex_lock(&LOCK_status);
+ size_t status_var_count= all_status_vars.elements;
+ mysql_mutex_unlock(&LOCK_status);
+ return (global_user_container.get_row_count() * status_var_count);
+}
+
+table_status_by_user::table_status_by_user()
+ : PFS_engine_table(&m_share, &m_pos),
+ m_status_cache(true), m_row_exists(false), m_pos(), m_next_pos()
+{}
+
+void table_status_by_user::reset_position(void)
+{
+ m_pos.reset();
+ m_next_pos.reset();
+}
+
+int table_status_by_user::rnd_init(bool scan)
+{
+ if (show_compatibility_56)
+ return 0;
+
+ /*
+ Build array of SHOW_VARs from the global status array prior to materializing
+ threads in rnd_next() or rnd_pos().
+ */
+ m_status_cache.initialize_client_session();
+
+ /* Use the current number of status variables to detect changes. */
+ ulonglong status_version= m_status_cache.get_status_array_version();
+
+ /*
+ The table context holds the current version of the global status array
+ and a record of which users were materialized. If scan == true, then
+ allocate a new context from mem_root and store in TLS. If scan == false,
+ then restore from TLS.
+ */
+ m_context= (table_status_by_user_context *)current_thd->alloc(sizeof(table_status_by_user_context));
+ new(m_context) table_status_by_user_context(status_version, !scan);
+ return 0;
+}
+
+int table_status_by_user::rnd_next(void)
+{
+ if (show_compatibility_56)
+ return HA_ERR_END_OF_FILE;
+
+ /* If status array changes, exit with warning. */ // TODO: Issue warning
+ if (!m_context->versions_match())
+ return HA_ERR_END_OF_FILE;
+
+ /*
+ For each user, build a cache of status variables using totals from all
+ threads associated with the user.
+ */
+ bool has_more_user= true;
+
+ for (m_pos.set_at(&m_next_pos);
+ has_more_user;
+ m_pos.next_user())
+ {
+ PFS_user *pfs_user= global_user_container.get(m_pos.m_index_1, &has_more_user);
+
+ if (m_status_cache.materialize_user(pfs_user) == 0)
+ {
+ /* Mark this user as materialized. */
+ m_context->set_item(m_pos.m_index_1);
+
+ /* Get the next status variable. */
+ const Status_variable *stat_var= m_status_cache.get(m_pos.m_index_2);
+ if (stat_var != NULL)
+ {
+ make_row(pfs_user, stat_var);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+ }
+ }
+ return HA_ERR_END_OF_FILE;
+}
+
+int
+table_status_by_user::rnd_pos(const void *pos)
+{
+ if (show_compatibility_56)
+ return HA_ERR_RECORD_DELETED;
+
+ /* If status array changes, exit with warning. */ // TODO: Issue warning
+ if (!m_context->versions_match())
+ return HA_ERR_END_OF_FILE;
+
+ set_position(pos);
+ DBUG_ASSERT(m_pos.m_index_1 < global_user_container.get_row_count());
+
+ PFS_user *pfs_user= global_user_container.get(m_pos.m_index_1);
+
+ /*
+ Only materialize threads that were previously materialized by rnd_next().
+ If a user cannot be rematerialized, then do nothing.
+ */
+ if (m_context->is_item_set(m_pos.m_index_1) &&
+ m_status_cache.materialize_user(pfs_user) == 0)
+ {
+ const Status_variable *stat_var= m_status_cache.get(m_pos.m_index_2);
+ if (stat_var != NULL)
+ {
+ make_row(pfs_user, stat_var);
+ return 0;
+ }
+ }
+ return HA_ERR_RECORD_DELETED;
+}
+
+void table_status_by_user
+::make_row(PFS_user *user, const Status_variable *status_var)
+{
+ pfs_optimistic_state lock;
+ m_row_exists= false;
+ user->m_lock.begin_optimistic_lock(&lock);
+
+ if (m_row.m_user.make_row(user))
+ return;
+
+ m_row.m_variable_name.make_row(status_var->m_name, status_var->m_name_length);
+ m_row.m_variable_value.make_row(status_var);
+
+ if (!user->m_lock.end_optimistic_lock(&lock))
+ return;
+
+ m_row_exists= true;
+}
+
+int table_status_by_user
+::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 0: /* USER */
+ m_row.m_user.set_field(f);
+ break;
+ case 1: /* VARIABLE_NAME */
+ set_field_varchar_utf8(f, m_row.m_variable_name.m_str, m_row.m_variable_name.m_length);
+ break;
+ case 2: /* VARIABLE_VALUE */
+ m_row.m_variable_value.set_field(f);
+ break;
+ default:
+ DBUG_ASSERT(false);
+ }
+ }
+ }
+
+ return 0;
+}
+
diff --git a/storage/perfschema/table_status_by_user.h b/storage/perfschema/table_status_by_user.h
new file mode 100644
index 00000000000..6b4a67b4e3f
--- /dev/null
+++ b/storage/perfschema/table_status_by_user.h
@@ -0,0 +1,153 @@
+/* Copyright (c) 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#ifndef TABLE_STATUS_BY_USER_H
+#define TABLE_STATUS_BY_USER_H
+
+/**
+ @file storage/perfschema/table_status_by_user.h
+ Table STATUS_BY_USER (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "pfs_instr_class.h"
+#include "pfs_instr.h"
+#include "pfs_user.h"
+#include "table_helper.h"
+#include "pfs_variable.h"
+#include "pfs_buffer_container.h"
+
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+/**
+ A row of table
+ PERFORMANCE_SCHEMA.STATUS_BY_USER.
+*/
+struct row_status_by_user
+{
+ /** Column USER */
+ PFS_user_row m_user;
+ /** Column VARIABLE_NAME. */
+ PFS_variable_name_row m_variable_name;
+ /** Column VARIABLE_VALUE. */
+ PFS_variable_value_row m_variable_value;
+};
+
+/**
+ Position of a cursor on
+ PERFORMANCE_SCHEMA.STATUS_BY_USER.
+ Index 1 on user (0 based)
+ Index 2 on status variable (0 based)
+*/
+struct pos_status_by_user
+: public PFS_double_index
+{
+ pos_status_by_user()
+ : PFS_double_index(0, 0)
+ {}
+
+ inline void reset(void)
+ {
+ m_index_1= 0;
+ m_index_2= 0;
+ }
+
+ inline bool has_more_user(void)
+ { return (m_index_1 < global_user_container.get_row_count()); }
+
+ inline void next_user(void)
+ {
+ m_index_1++;
+ m_index_2= 0;
+ }
+};
+
+/**
+ Store and retrieve table state information for queries that reinstantiate
+ the table object.
+*/
+class table_status_by_user_context : public PFS_table_context
+{
+public:
+ table_status_by_user_context(ulonglong current_version, bool restore) :
+ PFS_table_context(current_version, global_user_container.get_row_count(), restore, THR_PFS_SBU) { }
+};
+
+/** Table PERFORMANCE_SCHEMA.STATUS_BY_USER. */
+class table_status_by_user : public PFS_engine_table
+{
+ typedef pos_status_by_user pos_t;
+
+public:
+ /** Table share */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static int delete_all_rows();
+ static ha_rows get_row_count();
+
+ virtual int rnd_init(bool scan);
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+protected:
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+ table_status_by_user();
+
+public:
+ ~table_status_by_user() { }
+
+protected:
+ int materialize(PFS_thread *thread);
+ void make_row(PFS_user *user, const Status_variable *status_var);
+
+private:
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /** Fields definition. */
+ static TABLE_FIELD_DEF m_field_def;
+
+ /** Status variable cache for one user. */
+ PFS_status_variable_cache m_status_cache;
+
+ /** Current row. */
+ row_status_by_user m_row;
+ /** True if the current row exists. */
+ bool m_row_exists;
+ /** Current position. */
+ pos_t m_pos;
+ /** Next position. */
+ pos_t m_next_pos;
+
+ /** Table context with global status array version and map of materialized threads. */
+ table_status_by_user_context *m_context;
+};
+
+/** @} */
+#endif
diff --git a/storage/perfschema/table_sync_instances.cc b/storage/perfschema/table_sync_instances.cc
index f0c7800d24a..5b9f90c1092 100644
--- a/storage/perfschema/table_sync_instances.cc
+++ b/storage/perfschema/table_sync_instances.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -27,12 +27,14 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_instr.h"
#include "pfs_column_types.h"
#include "pfs_column_values.h"
#include "table_sync_instances.h"
#include "pfs_global.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
THR_LOCK table_mutex_instances::m_table_lock;
@@ -41,17 +43,17 @@ table_mutex_instances::m_share=
{
{ C_STRING_WITH_LEN("mutex_instances") },
&pfs_readonly_acl,
- &table_mutex_instances::create,
+ table_mutex_instances::create,
NULL, /* write_row */
NULL, /* delete_all_rows */
- NULL, /* get_row_count */
- 1000, /* records */
+ table_mutex_instances::get_row_count,
sizeof(PFS_simple_index),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE mutex_instances("
"NAME VARCHAR(128) not null,"
"OBJECT_INSTANCE_BEGIN BIGINT unsigned not null,"
- "LOCKED_BY_THREAD_ID BIGINT unsigned)") }
+ "LOCKED_BY_THREAD_ID BIGINT unsigned)") },
+ false /* perpetual */
};
PFS_engine_table* table_mutex_instances::create(void)
@@ -59,6 +61,12 @@ PFS_engine_table* table_mutex_instances::create(void)
return new table_mutex_instances();
}
+ha_rows
+table_mutex_instances::get_row_count(void)
+{
+ return global_mutex_container.get_row_count();
+}
+
table_mutex_instances::table_mutex_instances()
: PFS_engine_table(&m_share, &m_pos),
m_row_exists(false), m_pos(0), m_next_pos(0)
@@ -74,15 +82,14 @@ int table_mutex_instances::rnd_next(void)
{
PFS_mutex *pfs;
- for (m_pos.set_at(&m_next_pos); m_pos.m_index < mutex_max; m_pos.next())
+ m_pos.set_at(&m_next_pos);
+ PFS_mutex_iterator it= global_mutex_container.iterate(m_pos.m_index);
+ pfs= it.scan_next(& m_pos.m_index);
+ if (pfs != NULL)
{
- pfs= &mutex_array[m_pos.m_index];
- if (pfs->m_lock.is_populated())
- {
- make_row(pfs);
- m_next_pos.set_after(&m_pos);
- return 0;
- }
+ make_row(pfs);
+ m_next_pos.set_after(&m_pos);
+ return 0;
}
return HA_ERR_END_OF_FILE;
@@ -93,9 +100,9 @@ int table_mutex_instances::rnd_pos(const void *pos)
PFS_mutex *pfs;
set_position(pos);
- DBUG_ASSERT(m_pos.m_index < mutex_max);
- pfs= &mutex_array[m_pos.m_index];
- if (pfs->m_lock.is_populated())
+
+ pfs= global_mutex_container.get(m_pos.m_index);
+ if (pfs != NULL)
{
make_row(pfs);
return 0;
@@ -106,7 +113,7 @@ int table_mutex_instances::rnd_pos(const void *pos)
void table_mutex_instances::make_row(PFS_mutex *pfs)
{
- pfs_lock lock;
+ pfs_optimistic_state lock;
PFS_mutex_class *safe_class;
m_row_exists= false;
@@ -184,18 +191,18 @@ table_rwlock_instances::m_share=
{
{ C_STRING_WITH_LEN("rwlock_instances") },
&pfs_readonly_acl,
- &table_rwlock_instances::create,
+ table_rwlock_instances::create,
NULL, /* write_row */
NULL, /* delete_all_rows */
- NULL, /* get_row_count */
- 1000, /* records */
+ table_rwlock_instances::get_row_count,
sizeof(PFS_simple_index),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE rwlock_instances("
"NAME VARCHAR(128) not null,"
"OBJECT_INSTANCE_BEGIN BIGINT unsigned not null,"
"WRITE_LOCKED_BY_THREAD_ID BIGINT unsigned,"
- "READ_LOCKED_BY_COUNT INTEGER unsigned not null)") }
+ "READ_LOCKED_BY_COUNT INTEGER unsigned not null)") },
+ false /* perpetual */
};
PFS_engine_table* table_rwlock_instances::create(void)
@@ -203,6 +210,12 @@ PFS_engine_table* table_rwlock_instances::create(void)
return new table_rwlock_instances();
}
+ha_rows
+table_rwlock_instances::get_row_count(void)
+{
+ return global_rwlock_container.get_row_count();
+}
+
table_rwlock_instances::table_rwlock_instances()
: PFS_engine_table(&m_share, &m_pos),
m_row_exists(false), m_pos(0), m_next_pos(0)
@@ -218,15 +231,14 @@ int table_rwlock_instances::rnd_next(void)
{
PFS_rwlock *pfs;
- for (m_pos.set_at(&m_next_pos); m_pos.m_index < rwlock_max; m_pos.next())
+ m_pos.set_at(&m_next_pos);
+ PFS_rwlock_iterator it= global_rwlock_container.iterate(m_pos.m_index);
+ pfs= it.scan_next(& m_pos.m_index);
+ if (pfs != NULL)
{
- pfs= &rwlock_array[m_pos.m_index];
- if (pfs->m_lock.is_populated())
- {
- make_row(pfs);
- m_next_pos.set_after(&m_pos);
- return 0;
- }
+ make_row(pfs);
+ m_next_pos.set_after(&m_pos);
+ return 0;
}
return HA_ERR_END_OF_FILE;
@@ -237,9 +249,9 @@ int table_rwlock_instances::rnd_pos(const void *pos)
PFS_rwlock *pfs;
set_position(pos);
- DBUG_ASSERT(m_pos.m_index < rwlock_max);
- pfs= &rwlock_array[m_pos.m_index];
- if (pfs->m_lock.is_populated())
+
+ pfs= global_rwlock_container.get(m_pos.m_index);
+ if (pfs != NULL)
{
make_row(pfs);
return 0;
@@ -250,7 +262,7 @@ int table_rwlock_instances::rnd_pos(const void *pos)
void table_rwlock_instances::make_row(PFS_rwlock *pfs)
{
- pfs_lock lock;
+ pfs_optimistic_state lock;
PFS_rwlock_class *safe_class;
m_row_exists= false;
@@ -335,16 +347,16 @@ table_cond_instances::m_share=
{
{ C_STRING_WITH_LEN("cond_instances") },
&pfs_readonly_acl,
- &table_cond_instances::create,
+ table_cond_instances::create,
NULL, /* write_row */
NULL, /* delete_all_rows */
- NULL, /* get_row_count */
- 1000, /* records */
+ table_cond_instances::get_row_count,
sizeof(PFS_simple_index),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE cond_instances("
"NAME VARCHAR(128) not null,"
- "OBJECT_INSTANCE_BEGIN BIGINT unsigned not null)") }
+ "OBJECT_INSTANCE_BEGIN BIGINT unsigned not null)") },
+ false /* perpetual */
};
PFS_engine_table* table_cond_instances::create(void)
@@ -352,6 +364,12 @@ PFS_engine_table* table_cond_instances::create(void)
return new table_cond_instances();
}
+ha_rows
+table_cond_instances::get_row_count(void)
+{
+ return global_cond_container.get_row_count();
+}
+
table_cond_instances::table_cond_instances()
: PFS_engine_table(&m_share, &m_pos),
m_row_exists(false), m_pos(0), m_next_pos(0)
@@ -367,15 +385,14 @@ int table_cond_instances::rnd_next(void)
{
PFS_cond *pfs;
- for (m_pos.set_at(&m_next_pos); m_pos.m_index < cond_max; m_pos.next())
+ m_pos.set_at(&m_next_pos);
+ PFS_cond_iterator it= global_cond_container.iterate(m_pos.m_index);
+ pfs= it.scan_next(& m_pos.m_index);
+ if (pfs != NULL)
{
- pfs= &cond_array[m_pos.m_index];
- if (pfs->m_lock.is_populated())
- {
- make_row(pfs);
- m_next_pos.set_after(&m_pos);
- return 0;
- }
+ make_row(pfs);
+ m_next_pos.set_after(&m_pos);
+ return 0;
}
return HA_ERR_END_OF_FILE;
@@ -386,9 +403,9 @@ int table_cond_instances::rnd_pos(const void *pos)
PFS_cond *pfs;
set_position(pos);
- DBUG_ASSERT(m_pos.m_index < cond_max);
- pfs= &cond_array[m_pos.m_index];
- if (pfs->m_lock.is_populated())
+
+ pfs= global_cond_container.get(m_pos.m_index);
+ if (pfs != NULL)
{
make_row(pfs);
return 0;
@@ -399,7 +416,7 @@ int table_cond_instances::rnd_pos(const void *pos)
void table_cond_instances::make_row(PFS_cond *pfs)
{
- pfs_lock lock;
+ pfs_optimistic_state lock;
PFS_cond_class *safe_class;
m_row_exists= false;
diff --git a/storage/perfschema/table_sync_instances.h b/storage/perfschema/table_sync_instances.h
index 6f7e1bf5523..6cf8f0f3669 100644
--- a/storage/perfschema/table_sync_instances.h
+++ b/storage/perfschema/table_sync_instances.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -62,6 +62,7 @@ public:
/** Table share. */
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
+ static ha_rows get_row_count();
virtual int rnd_next();
virtual int rnd_pos(const void *pos);
@@ -119,6 +120,7 @@ public:
/** Table share */
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
+ static ha_rows get_row_count();
virtual int rnd_next();
virtual int rnd_pos(const void *pos);
@@ -170,6 +172,7 @@ public:
/** Table share. */
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
+ static ha_rows get_row_count();
virtual int rnd_next();
virtual int rnd_pos(const void *pos);
diff --git a/storage/perfschema/table_table_handles.cc b/storage/perfschema/table_table_handles.cc
new file mode 100644
index 00000000000..ab6ed357687
--- /dev/null
+++ b/storage/perfschema/table_table_handles.cc
@@ -0,0 +1,214 @@
+/* Copyright (c) 2012, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+
+/**
+ @file storage/perfschema/table_table_handles.cc
+ Table TABLE_TABLE_HANDLES (implementation).
+*/
+
+#include "my_global.h"
+#include "my_thread.h"
+#include "pfs_instr_class.h"
+#include "pfs_column_types.h"
+#include "pfs_column_values.h"
+#include "table_table_handles.h"
+#include "pfs_global.h"
+#include "pfs_stat.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
+
+THR_LOCK table_table_handles::m_table_lock;
+
+PFS_engine_table_share
+table_table_handles::m_share=
+{
+ { C_STRING_WITH_LEN("table_handles") },
+ &pfs_readonly_acl,
+ table_table_handles::create,
+ NULL, /* write_row */
+ NULL, /* delete_all_rows */
+ table_table_handles::get_row_count,
+ sizeof(PFS_simple_index),
+ &m_table_lock,
+ { C_STRING_WITH_LEN("CREATE TABLE table_handles("
+ "OBJECT_TYPE VARCHAR(64) not null,"
+ "OBJECT_SCHEMA VARCHAR(64) not null,"
+ "OBJECT_NAME VARCHAR(64) not null,"
+ "OBJECT_INSTANCE_BEGIN BIGINT unsigned not null,"
+ "OWNER_THREAD_ID BIGINT unsigned,"
+ "OWNER_EVENT_ID BIGINT unsigned,"
+ "INTERNAL_LOCK VARCHAR(64),"
+ "EXTERNAL_LOCK VARCHAR(64))") },
+ false /* perpetual */
+};
+
+PFS_engine_table*
+table_table_handles::create(void)
+{
+ return new table_table_handles();
+}
+
+ha_rows
+table_table_handles::get_row_count(void)
+{
+ return global_table_container.get_row_count();
+}
+
+table_table_handles::table_table_handles()
+ : PFS_engine_table(&m_share, &m_pos),
+ m_row_exists(false), m_pos(0), m_next_pos(0)
+{}
+
+void table_table_handles::reset_position(void)
+{
+ m_pos.m_index= 0;
+ m_next_pos.m_index= 0;
+}
+
+int table_table_handles::rnd_init(bool scan)
+{
+ return 0;
+}
+
+int table_table_handles::rnd_next(void)
+{
+ PFS_table *pfs;
+
+ m_pos.set_at(&m_next_pos);
+ PFS_table_iterator it= global_table_container.iterate(m_pos.m_index);
+ pfs= it.scan_next(& m_pos.m_index);
+ if (pfs != NULL)
+ {
+ make_row(pfs);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+
+ return HA_ERR_END_OF_FILE;
+}
+
+int
+table_table_handles::rnd_pos(const void *pos)
+{
+ PFS_table *pfs;
+
+ set_position(pos);
+
+ pfs= global_table_container.get(m_pos.m_index);
+ if (pfs != NULL)
+ {
+ make_row(pfs);
+ return 0;
+ }
+
+ return HA_ERR_RECORD_DELETED;
+}
+
+void table_table_handles::make_row(PFS_table *table)
+{
+ pfs_optimistic_state lock;
+ PFS_table_share *share;
+ PFS_thread *thread;
+
+ m_row_exists= false;
+
+ table->m_lock.begin_optimistic_lock(&lock);
+
+ share= sanitize_table_share(table->m_share);
+ if (share == NULL)
+ return;
+
+ if (m_row.m_object.make_row(share))
+ return;
+
+ m_row.m_identity= table->m_identity;
+
+ thread= sanitize_thread(table->m_thread_owner);
+ if (thread != NULL)
+ {
+ m_row.m_owner_thread_id= thread->m_thread_internal_id;
+ m_row.m_owner_event_id= table->m_owner_event_id;
+ }
+ else
+ {
+ m_row.m_owner_thread_id= 0;
+ m_row.m_owner_event_id= 0;
+ }
+
+ m_row.m_internal_lock= table->m_internal_lock;
+ m_row.m_external_lock= table->m_external_lock;
+
+ if (! table->m_lock.end_optimistic_lock(&lock))
+ return;
+
+ m_row_exists= true;
+}
+
+int table_table_handles::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 0: /* OBJECT_TYPE */
+ case 1: /* SCHEMA_NAME */
+ case 2: /* OBJECT_NAME */
+ m_row.m_object.set_field(f->field_index, f);
+ break;
+ case 3: /* OBJECT_INSTANCE_BEGIN */
+ set_field_ulonglong(f, (intptr) m_row.m_identity);
+ break;
+ case 4: /* OWNER_THREAD_ID */
+ set_field_ulonglong(f, m_row.m_owner_thread_id);
+ break;
+ case 5: /* OWNER_EVENT_ID */
+ set_field_ulonglong(f, m_row.m_owner_event_id);
+ break;
+ case 6: /* INTERNAL_LOCK */
+ set_field_lock_type(f, m_row.m_internal_lock);
+ break;
+ case 7: /* EXTERNAL_LOCK */
+ set_field_lock_type(f, m_row.m_external_lock);
+ break;
+ default:
+ DBUG_ASSERT(false);
+ }
+ }
+ }
+
+ return 0;
+}
+
diff --git a/storage/perfschema/table_table_handles.h b/storage/perfschema/table_table_handles.h
new file mode 100644
index 00000000000..0f1f76f4846
--- /dev/null
+++ b/storage/perfschema/table_table_handles.h
@@ -0,0 +1,108 @@
+/* Copyright (c) 2012, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+
+#ifndef TABLE_TABLE_HANDLES_H
+#define TABLE_TABLE_HANDLES_H
+
+/**
+ @file storage/perfschema/table_table_handles.h
+ Table TABLE_HANDLES (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "pfs_instr_class.h"
+#include "pfs_instr.h"
+#include "table_helper.h"
+
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+/**
+ A row of table
+ PERFORMANCE_SCHEMA.TABLE_HANDLES.
+*/
+struct row_table_handles
+{
+ /** Column OBJECT_TYPE, SCHEMA_NAME, OBJECT_NAME. */
+ PFS_object_row m_object;
+ /** Column OBJECT_INSTANCE_BEGIN. */
+ const void *m_identity;
+ /** Column OWNER_THREAD_ID. */
+ ulonglong m_owner_thread_id;
+ /** Column OWNER_EVENT_ID. */
+ ulonglong m_owner_event_id;
+ /** Column INTERNAL_LOCK. */
+ PFS_TL_LOCK_TYPE m_internal_lock;
+ /** Column EXTERNAL_LOCK. */
+ PFS_TL_LOCK_TYPE m_external_lock;
+};
+
+/** Table PERFORMANCE_SCHEMA.TABLE_HANDLES. */
+class table_table_handles : public PFS_engine_table
+{
+public:
+ /** Table share */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static ha_rows get_row_count();
+
+ virtual int rnd_init(bool scan);
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+protected:
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+
+ table_table_handles();
+
+public:
+ ~table_table_handles()
+ {}
+
+protected:
+ void make_row(PFS_table *table);
+
+private:
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /** Fields definition. */
+ static TABLE_FIELD_DEF m_field_def;
+
+ /** Current row. */
+ row_table_handles m_row;
+ /** True is the current row exists. */
+ bool m_row_exists;
+ /** Current position. */
+ PFS_simple_index m_pos;
+ /** Next position. */
+ PFS_simple_index m_next_pos;
+};
+
+/** @} */
+#endif
diff --git a/storage/perfschema/table_threads.cc b/storage/perfschema/table_threads.cc
index b396db1a814..6d83b6531b6 100644
--- a/storage/perfschema/table_threads.cc
+++ b/storage/perfschema/table_threads.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -21,12 +21,40 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "table_threads.h"
#include "sql_parse.h"
#include "pfs_instr_class.h"
#include "pfs_instr.h"
+static const LEX_CSTRING vio_type_names[] =
+{
+ { STRING_WITH_LEN("Error") }, // cannot happen
+ { STRING_WITH_LEN("TCP/IP") },
+ { STRING_WITH_LEN("Socket") },
+ { STRING_WITH_LEN("Named Pipe") },
+ { STRING_WITH_LEN("SSL/TLS") },
+ { STRING_WITH_LEN("Shared Memory") }
+};
+
+static void get_vio_type_name(enum enum_vio_type vio_type, const char **str, int *len)
+{
+ int index;
+
+ if ((vio_type >= FIRST_VIO_TYPE) && (vio_type <= LAST_VIO_TYPE))
+ {
+ index= vio_type;
+ }
+ else
+ {
+ index= 0;
+ }
+ *str= vio_type_names[index].str;
+ *len= vio_type_names[index].length;
+ return;
+}
+
+
THR_LOCK table_threads::m_table_lock;
PFS_engine_table_share
@@ -34,11 +62,10 @@ table_threads::m_share=
{
{ C_STRING_WITH_LEN("threads") },
&pfs_updatable_acl,
- &table_threads::create,
+ table_threads::create,
NULL, /* write_row */
NULL, /* delete_all_rows */
- NULL, /* get_row_count */
- 1000, /* records */
+ cursor_by_thread::get_row_count,
sizeof(PFS_simple_index), /* ref length */
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE threads("
@@ -46,7 +73,7 @@ table_threads::m_share=
"NAME VARCHAR(128) not null,"
"TYPE VARCHAR(10) not null,"
"PROCESSLIST_ID BIGINT unsigned,"
- "PROCESSLIST_USER VARCHAR(16),"
+ "PROCESSLIST_USER VARCHAR(" USERNAME_CHAR_LENGTH_STR "),"
"PROCESSLIST_HOST VARCHAR(60),"
"PROCESSLIST_DB VARCHAR(64),"
"PROCESSLIST_COMMAND VARCHAR(16),"
@@ -55,7 +82,11 @@ table_threads::m_share=
"PROCESSLIST_INFO LONGTEXT,"
"PARENT_THREAD_ID BIGINT unsigned,"
"ROLE VARCHAR(64),"
- "INSTRUMENTED ENUM ('YES', 'NO') not null)") }
+ "INSTRUMENTED ENUM ('YES', 'NO') not null,"
+ "HISTORY ENUM ('YES', 'NO') not null,"
+ "CONNECTION_TYPE VARCHAR(16)"
+ "THREAD_OS_ID BIGINT unsigned)") },
+ false /* perpetual */
};
PFS_engine_table* table_threads::create()
@@ -70,9 +101,9 @@ table_threads::table_threads()
void table_threads::make_row(PFS_thread *pfs)
{
- pfs_lock lock;
- pfs_lock session_lock;
- pfs_lock stmt_lock;
+ pfs_optimistic_state lock;
+ pfs_optimistic_state session_lock;
+ pfs_optimistic_state stmt_lock;
PFS_stage_class *stage_class;
PFS_thread_class *safe_class;
@@ -88,6 +119,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_processlist_id= pfs->m_processlist_id;
+ m_row.m_thread_os_id= pfs->m_thread_os_id;
m_row.m_name= safe_class->m_name;
m_row.m_name_length= safe_class->m_name_length;
@@ -165,8 +197,12 @@ void table_threads::make_row(PFS_thread *pfs)
{
m_row.m_processlist_state_length= 0;
}
+ m_row.m_connection_type = pfs->m_connection_type;
- m_row.m_enabled_ptr= &pfs->m_enabled;
+
+ m_row.m_enabled= pfs->m_enabled;
+ m_row.m_history= pfs->m_history;
+ m_row.m_psi= pfs;
if (pfs->m_lock.end_optimistic_lock(& lock))
m_row_exists= true;
@@ -178,6 +214,8 @@ int table_threads::read_row_values(TABLE *table,
bool read_all)
{
Field *f;
+ const char *str= NULL;
+ int len= 0;
if (unlikely(! m_row_exists))
return HA_ERR_RECORD_DELETED;
@@ -250,23 +288,16 @@ int table_threads::read_row_values(TABLE *table,
f->set_null();
break;
case 9: /* PROCESSLIST_STATE */
+ /* This column's datatype is declared as varchar(64). Thread's state
+ message cannot be more than 64 characters. Otherwise, we will end up
+ in 'data truncated' warning/error (depends sql_mode setting) when
+ server is updating this column for those threads. To prevent this
+ kind of issue, an assert is added.
+ */
+ DBUG_ASSERT(m_row.m_processlist_state_length <= f->char_length());
if (m_row.m_processlist_state_length > 0)
- {
- /* This column's datatype is declared as varchar(64). But in current
- code, there are few process state messages which are greater than
- 64 characters(Eg:stage_slave_has_read_all_relay_log).
- In those cases, we will end up in 'data truncated'
- warning/error (depends sql_mode setting) when server is updating
- this column for those threads. Since 5.6 is GAed, neither the
- metadata of this column can be changed, nor those state messages.
- So server will silently truncate the state message to 64 characters
- if it is longer. In Upper versions(5.7+), these state messages are
- changed to less than or equal to 64 characters.
- */
set_field_varchar_utf8(f, m_row.m_processlist_state_ptr,
- MY_MIN(m_row.m_processlist_state_length,
- f->char_length()));
- }
+ m_row.m_processlist_state_length);
else
f->set_null();
break;
@@ -287,7 +318,23 @@ int table_threads::read_row_values(TABLE *table,
f->set_null();
break;
case 13: /* INSTRUMENTED */
- set_field_enum(f, (*m_row.m_enabled_ptr) ? ENUM_YES : ENUM_NO);
+ set_field_enum(f, m_row.m_enabled ? ENUM_YES : ENUM_NO);
+ break;
+ case 14: /* HISTORY */
+ set_field_enum(f, m_row.m_history ? ENUM_YES : ENUM_NO);
+ break;
+ case 15: /* CONNECTION_TYPE */
+ get_vio_type_name(m_row.m_connection_type, & str, & len);
+ if (len > 0)
+ set_field_varchar_utf8(f, str, len);
+ else
+ f->set_null();
+ break;
+ case 16: /* THREAD_OS_ID */
+ if (m_row.m_thread_os_id > 0)
+ set_field_ulonglong(f, m_row.m_thread_os_id);
+ else
+ f->set_null();
break;
default:
DBUG_ASSERT(false);
@@ -327,8 +374,15 @@ int table_threads::update_row_values(TABLE *table,
return HA_ERR_WRONG_COMMAND;
case 13: /* INSTRUMENTED */
value= (enum_yes_no) get_field_enum(f);
- *m_row.m_enabled_ptr= (value == ENUM_YES) ? true : false;
+ m_row.m_psi->set_enabled((value == ENUM_YES) ? true : false);
break;
+ case 14: /* HISTORY */
+ value= (enum_yes_no) get_field_enum(f);
+ m_row.m_psi->set_history((value == ENUM_YES) ? true : false);
+ break;
+ case 15: /* CONNECTION_TYPE */
+ case 16: /* THREAD_OS_ID */
+ return HA_ERR_WRONG_COMMAND;
default:
DBUG_ASSERT(false);
}
diff --git a/storage/perfschema/table_threads.h b/storage/perfschema/table_threads.h
index 841b8102bca..88302ea61de 100644
--- a/storage/perfschema/table_threads.h
+++ b/storage/perfschema/table_threads.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2015, 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, version 2.0,
@@ -70,10 +70,18 @@ struct row_threads
const char* m_processlist_info_ptr;
/** Length in bytes of @c m_processlist_info_ptr. */
uint m_processlist_info_length;
- /** Column INSTRUMENTED. */
- bool *m_enabled_ptr;
+ /** Column INSTRUMENTED (read). */
+ bool m_enabled;
+ /** Column HISTORY (read). */
+ bool m_history;
+ /** INSTRUMENTED and HISTORY (write). */
+ PFS_thread *m_psi;
/** Column PARENT_THREAD_ID. */
ulonglong m_parent_thread_internal_id;
+ /** Column CONNECTION_TYPE. */
+ enum_vio_type m_connection_type;
+ /** Column THREAD_OS_ID. */
+ my_thread_os_id_t m_thread_os_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 b49e9280469..a1a7343e65b 100644
--- a/storage/perfschema/table_tiws_by_index_usage.cc
+++ b/storage/perfschema/table_tiws_by_index_usage.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -26,13 +26,15 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_instr_class.h"
#include "pfs_column_types.h"
#include "pfs_column_values.h"
#include "table_tiws_by_index_usage.h"
#include "pfs_global.h"
#include "pfs_visitor.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
THR_LOCK table_tiws_by_index_usage::m_table_lock;
@@ -44,8 +46,7 @@ table_tiws_by_index_usage::m_share=
table_tiws_by_index_usage::create,
NULL, /* write_row */
table_tiws_by_index_usage::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ table_tiws_by_index_usage::get_row_count,
sizeof(pos_tiws_by_index_usage),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE table_io_waits_summary_by_index_usage("
@@ -87,7 +88,8 @@ table_tiws_by_index_usage::m_share=
"SUM_TIMER_DELETE BIGINT unsigned not null,"
"MIN_TIMER_DELETE BIGINT unsigned not null,"
"AVG_TIMER_DELETE BIGINT unsigned not null,"
- "MAX_TIMER_DELETE BIGINT unsigned not null)") }
+ "MAX_TIMER_DELETE BIGINT unsigned not null)") },
+ false /* perpetual */
};
PFS_engine_table*
@@ -104,6 +106,12 @@ table_tiws_by_index_usage::delete_all_rows(void)
return 0;
}
+ha_rows
+table_tiws_by_index_usage::get_row_count(void)
+{
+ return global_table_share_index_container.get_row_count();
+}
+
table_tiws_by_index_usage::table_tiws_by_index_usage()
: PFS_engine_table(&m_share, &m_pos),
m_row_exists(false), m_pos(), m_next_pos()
@@ -124,27 +132,31 @@ int table_tiws_by_index_usage::rnd_init(bool scan)
int table_tiws_by_index_usage::rnd_next(void)
{
PFS_table_share *table_share;
+ bool has_more_table= true;
for (m_pos.set_at(&m_next_pos);
- m_pos.has_more_table();
+ has_more_table;
m_pos.next_table())
{
- table_share= &table_share_array[m_pos.m_index_1];
- if (table_share->m_lock.is_populated())
+ table_share= global_table_share_container.get(m_pos.m_index_1, & has_more_table);
+ if (table_share != NULL)
{
- uint safe_key_count= sanitize_index_count(table_share->m_key_count);
- if (m_pos.m_index_2 < safe_key_count)
+ if (table_share->m_enabled)
{
- 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_INDEXES)
- {
- 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;
+ 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_INDEXES)
+ {
+ 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;
+ }
}
}
}
@@ -159,40 +171,58 @@ table_tiws_by_index_usage::rnd_pos(const void *pos)
set_position(pos);
- table_share= &table_share_array[m_pos.m_index_1];
- if (table_share->m_lock.is_populated())
+ table_share= global_table_share_container.get(m_pos.m_index_1);
+ if (table_share != NULL)
{
- 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_INDEXES)
+ if (table_share->m_enabled)
{
- make_row(table_share, m_pos.m_index_2);
- return 0;
+ 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_INDEXES)
+ {
+ make_row(table_share, m_pos.m_index_2);
+ return 0;
+ }
}
}
return HA_ERR_RECORD_DELETED;
}
-void table_tiws_by_index_usage::make_row(PFS_table_share *share, uint index)
+void table_tiws_by_index_usage::make_row(PFS_table_share *pfs_share,
+ uint index)
{
- pfs_lock lock;
+ PFS_table_share_index *pfs_index;
+ pfs_optimistic_state lock;
- m_row_exists= false;
+ DBUG_ASSERT(index <= MAX_INDEXES);
- share->m_lock.begin_optimistic_lock(&lock);
+ m_row_exists= false;
- if (m_row.m_index.make_row(share, index))
- return;
+ pfs_share->m_lock.begin_optimistic_lock(&lock);
PFS_index_io_stat_visitor visitor;
- PFS_object_iterator::visit_table_indexes(share, index, & visitor);
+ PFS_object_iterator::visit_table_indexes(pfs_share, index, & visitor);
+
+ if (! visitor.m_stat.m_has_data)
+ {
+ pfs_index= pfs_share->find_index_stat(index);
+ if (pfs_index == NULL)
+ return;
+ }
+ else
+ {
+ pfs_index= pfs_share->find_index_stat(index);
+ }
+
+ if (m_row.m_index.make_row(pfs_share, pfs_index, index))
+ return;
- if (! share->m_lock.end_optimistic_lock(&lock))
+ if (! pfs_share->m_lock.end_optimistic_lock(&lock))
return;
m_row_exists= true;
diff --git a/storage/perfschema/table_tiws_by_index_usage.h b/storage/perfschema/table_tiws_by_index_usage.h
index a284bc7f0bc..cc6ee5ebfe7 100644
--- a/storage/perfschema/table_tiws_by_index_usage.h
+++ b/storage/perfschema/table_tiws_by_index_usage.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -54,7 +54,7 @@ struct row_tiws_by_index_usage
/**
Position of a cursor on
PERFORMANCE_SCHEMA.TABLE_IO_WAIT_SUMMARY_BY_INDEX.
- Index 1 on table_share_array (0 based)
+ Index 1 on global_table_share_container (0 based)
Index 2 on index (0 based)
*/
struct pos_tiws_by_index_usage : public PFS_double_index
@@ -69,11 +69,6 @@ struct pos_tiws_by_index_usage : public PFS_double_index
m_index_2= 0;
}
- inline bool has_more_table(void)
- {
- return (m_index_1 < table_share_max);
- }
-
inline void next_table(void)
{
m_index_1++;
@@ -89,6 +84,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_init(bool scan);
virtual int rnd_next();
diff --git a/storage/perfschema/table_tiws_by_table.cc b/storage/perfschema/table_tiws_by_table.cc
index db00fd2409e..abd45a7bf3a 100644
--- a/storage/perfschema/table_tiws_by_table.cc
+++ b/storage/perfschema/table_tiws_by_table.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -26,13 +26,15 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_instr_class.h"
#include "pfs_column_types.h"
#include "pfs_column_values.h"
#include "table_tiws_by_table.h"
#include "pfs_global.h"
#include "pfs_visitor.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
THR_LOCK table_tiws_by_table::m_table_lock;
@@ -44,8 +46,7 @@ table_tiws_by_table::m_share=
table_tiws_by_table::create,
NULL, /* write_row */
table_tiws_by_table::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ table_tiws_by_table::get_row_count,
sizeof(PFS_simple_index),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE table_io_waits_summary_by_table("
@@ -86,7 +87,8 @@ table_tiws_by_table::m_share=
"SUM_TIMER_DELETE BIGINT unsigned not null,"
"MIN_TIMER_DELETE BIGINT unsigned not null,"
"AVG_TIMER_DELETE BIGINT unsigned not null,"
- "MAX_TIMER_DELETE BIGINT unsigned not null)") }
+ "MAX_TIMER_DELETE BIGINT unsigned not null)") },
+ false /* perpetual */
};
PFS_engine_table*
@@ -103,6 +105,12 @@ table_tiws_by_table::delete_all_rows(void)
return 0;
}
+ha_rows
+table_tiws_by_table::get_row_count(void)
+{
+ return global_table_share_container.get_row_count();
+}
+
table_tiws_by_table::table_tiws_by_table()
: PFS_engine_table(&m_share, &m_pos),
m_row_exists(false), m_pos(0), m_next_pos(0)
@@ -122,20 +130,23 @@ int table_tiws_by_table::rnd_init(bool scan)
int table_tiws_by_table::rnd_next(void)
{
- PFS_table_share *table_share;
+ PFS_table_share *pfs;
- for (m_pos.set_at(&m_next_pos);
- m_pos.m_index < table_share_max;
- m_pos.m_index++)
+ m_pos.set_at(&m_next_pos);
+ PFS_table_share_iterator it= global_table_share_container.iterate(m_pos.m_index);
+ do
{
- table_share= &table_share_array[m_pos.m_index];
- if (table_share->m_lock.is_populated())
+ pfs= it.scan_next(& m_pos.m_index);
+ if (pfs != NULL)
{
- make_row(table_share);
- m_next_pos.set_after(&m_pos);
- return 0;
+ if (pfs->m_enabled)
+ {
+ make_row(pfs);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
}
- }
+ } while (pfs != NULL);
return HA_ERR_END_OF_FILE;
}
@@ -143,15 +154,18 @@ int table_tiws_by_table::rnd_next(void)
int
table_tiws_by_table::rnd_pos(const void *pos)
{
- PFS_table_share *table_share;
+ PFS_table_share *pfs;
set_position(pos);
- table_share= &table_share_array[m_pos.m_index];
- if (table_share->m_lock.is_populated())
+ pfs= global_table_share_container.get(m_pos.m_index);
+ if (pfs != NULL)
{
- make_row(table_share);
- return 0;
+ if (pfs->m_enabled)
+ {
+ make_row(pfs);
+ return 0;
+ }
}
return HA_ERR_RECORD_DELETED;
@@ -159,7 +173,7 @@ table_tiws_by_table::rnd_pos(const void *pos)
void table_tiws_by_table::make_row(PFS_table_share *share)
{
- pfs_lock lock;
+ pfs_optimistic_state lock;
m_row_exists= false;
diff --git a/storage/perfschema/table_tiws_by_table.h b/storage/perfschema/table_tiws_by_table.h
index 7427ca797fa..4100a99156b 100644
--- a/storage/perfschema/table_tiws_by_table.h
+++ b/storage/perfschema/table_tiws_by_table.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -59,6 +59,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_init(bool scan);
virtual int rnd_next();
diff --git a/storage/perfschema/table_tlws_by_table.cc b/storage/perfschema/table_tlws_by_table.cc
index d802127d10d..0b0758469d7 100644
--- a/storage/perfschema/table_tlws_by_table.cc
+++ b/storage/perfschema/table_tlws_by_table.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -26,13 +26,15 @@
*/
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "pfs_instr_class.h"
#include "pfs_column_types.h"
#include "pfs_column_values.h"
#include "table_tlws_by_table.h"
#include "pfs_global.h"
#include "pfs_visitor.h"
+#include "pfs_buffer_container.h"
+#include "field.h"
THR_LOCK table_tlws_by_table::m_table_lock;
@@ -44,8 +46,7 @@ table_tlws_by_table::m_share=
table_tlws_by_table::create,
NULL, /* write_row */
table_tlws_by_table::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ table_tlws_by_table::get_row_count,
sizeof(PFS_simple_index),
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE table_lock_waits_summary_by_table("
@@ -102,11 +103,6 @@ table_tlws_by_table::m_share=
"MIN_TIMER_WRITE_CONCURRENT_INSERT BIGINT unsigned not null,"
"AVG_TIMER_WRITE_CONCURRENT_INSERT BIGINT unsigned not null,"
"MAX_TIMER_WRITE_CONCURRENT_INSERT BIGINT unsigned not null,"
- "COUNT_WRITE_DELAYED BIGINT unsigned not null,"
- "SUM_TIMER_WRITE_DELAYED BIGINT unsigned not null,"
- "MIN_TIMER_WRITE_DELAYED BIGINT unsigned not null,"
- "AVG_TIMER_WRITE_DELAYED BIGINT unsigned not null,"
- "MAX_TIMER_WRITE_DELAYED BIGINT unsigned not null,"
"COUNT_WRITE_LOW_PRIORITY BIGINT unsigned not null,"
"SUM_TIMER_WRITE_LOW_PRIORITY BIGINT unsigned not null,"
"MIN_TIMER_WRITE_LOW_PRIORITY BIGINT unsigned not null,"
@@ -121,7 +117,8 @@ table_tlws_by_table::m_share=
"SUM_TIMER_WRITE_EXTERNAL BIGINT unsigned not null,"
"MIN_TIMER_WRITE_EXTERNAL BIGINT unsigned not null,"
"AVG_TIMER_WRITE_EXTERNAL BIGINT unsigned not null,"
- "MAX_TIMER_WRITE_EXTERNAL BIGINT unsigned not null)") }
+ "MAX_TIMER_WRITE_EXTERNAL BIGINT unsigned not null)") },
+ false /* perpetual */
};
PFS_engine_table*
@@ -138,6 +135,12 @@ table_tlws_by_table::delete_all_rows(void)
return 0;
}
+ha_rows
+table_tlws_by_table::get_row_count(void)
+{
+ return global_table_share_container.get_row_count();
+}
+
table_tlws_by_table::table_tlws_by_table()
: PFS_engine_table(&m_share, &m_pos),
m_row_exists(false), m_pos(0), m_next_pos(0)
@@ -157,20 +160,23 @@ int table_tlws_by_table::rnd_init(bool scan)
int table_tlws_by_table::rnd_next(void)
{
- PFS_table_share *table_share;
+ PFS_table_share *pfs;
- for (m_pos.set_at(&m_next_pos);
- m_pos.m_index < table_share_max;
- m_pos.m_index++)
+ m_pos.set_at(&m_next_pos);
+ PFS_table_share_iterator it= global_table_share_container.iterate(m_pos.m_index);
+ do
{
- table_share= &table_share_array[m_pos.m_index];
- if (table_share->m_lock.is_populated())
+ pfs= it.scan_next(& m_pos.m_index);
+ if (pfs != NULL)
{
- make_row(table_share);
- m_next_pos.set_after(&m_pos);
- return 0;
+ if (pfs->m_enabled)
+ {
+ make_row(pfs);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
}
- }
+ } while (pfs != NULL);
return HA_ERR_END_OF_FILE;
}
@@ -178,15 +184,18 @@ int table_tlws_by_table::rnd_next(void)
int
table_tlws_by_table::rnd_pos(const void *pos)
{
- PFS_table_share *table_share;
+ PFS_table_share *pfs;
set_position(pos);
- table_share= &table_share_array[m_pos.m_index];
- if (table_share->m_lock.is_populated())
+ pfs= global_table_share_container.get(m_pos.m_index);
+ if (pfs != NULL)
{
- make_row(table_share);
- return 0;
+ if (pfs->m_enabled)
+ {
+ make_row(pfs);
+ return 0;
+ }
}
return HA_ERR_RECORD_DELETED;
@@ -194,7 +203,7 @@ table_tlws_by_table::rnd_pos(const void *pos)
void table_tlws_by_table::make_row(PFS_table_share *share)
{
- pfs_lock lock;
+ pfs_optimistic_state lock;
m_row_exists= false;
@@ -396,67 +405,51 @@ int table_tlws_by_table::read_row_values(TABLE *table,
set_field_ulonglong(f, m_row.m_stat.m_write_concurrent_insert.m_max);
break;
- case 53: /* COUNT_WRITE_DELAYED */
- set_field_ulonglong(f, m_row.m_stat.m_write_delayed.m_count);
- break;
- case 54: /* SUM_TIMER_WRITE_DELAYED */
- set_field_ulonglong(f, m_row.m_stat.m_write_delayed.m_sum);
- break;
- case 55: /* MIN_TIMER_WRITE_DELAYED */
- set_field_ulonglong(f, m_row.m_stat.m_write_delayed.m_min);
- break;
- case 56: /* AVG_TIMER_WRITE_DELAYED */
- set_field_ulonglong(f, m_row.m_stat.m_write_delayed.m_avg);
- break;
- case 57: /* MAX_TIMER_WRITE_DELAYED */
- set_field_ulonglong(f, m_row.m_stat.m_write_delayed.m_max);
- break;
-
- case 58: /* COUNT_WRITE_LOW_PRIORITY */
+ case 53: /* COUNT_WRITE_LOW_PRIORITY */
set_field_ulonglong(f, m_row.m_stat.m_write_low_priority.m_count);
break;
- case 59: /* SUM_TIMER_WRITE_LOW_PRIORITY */
+ case 54: /* SUM_TIMER_WRITE_LOW_PRIORITY */
set_field_ulonglong(f, m_row.m_stat.m_write_low_priority.m_sum);
break;
- case 60: /* MIN_TIMER_WRITE_LOW_PRIORITY */
+ case 55: /* MIN_TIMER_WRITE_LOW_PRIORITY */
set_field_ulonglong(f, m_row.m_stat.m_write_low_priority.m_min);
break;
- case 61: /* AVG_TIMER_WRITE_LOW_PRIORITY */
+ case 56: /* AVG_TIMER_WRITE_LOW_PRIORITY */
set_field_ulonglong(f, m_row.m_stat.m_write_low_priority.m_avg);
break;
- case 62: /* MAX_TIMER_WRITE_LOW_PRIORITY */
+ case 57: /* MAX_TIMER_WRITE_LOW_PRIORITY */
set_field_ulonglong(f, m_row.m_stat.m_write_low_priority.m_max);
break;
- case 63: /* COUNT_WRITE_NORMAL */
+ case 58: /* COUNT_WRITE_NORMAL */
set_field_ulonglong(f, m_row.m_stat.m_write_normal.m_count);
break;
- case 64: /* SUM_TIMER_WRITE_NORMAL */
+ case 59: /* SUM_TIMER_WRITE_NORMAL */
set_field_ulonglong(f, m_row.m_stat.m_write_normal.m_sum);
break;
- case 65: /* MIN_TIMER_WRITE_NORMAL */
+ case 60: /* MIN_TIMER_WRITE_NORMAL */
set_field_ulonglong(f, m_row.m_stat.m_write_normal.m_min);
break;
- case 66: /* AVG_TIMER_WRITE_NORMAL */
+ case 61: /* AVG_TIMER_WRITE_NORMAL */
set_field_ulonglong(f, m_row.m_stat.m_write_normal.m_avg);
break;
- case 67: /* MAX_TIMER_WRITE_NORMAL */
+ case 62: /* MAX_TIMER_WRITE_NORMAL */
set_field_ulonglong(f, m_row.m_stat.m_write_normal.m_max);
break;
- case 68: /* COUNT_WRITE_EXTERNAL */
+ case 63: /* COUNT_WRITE_EXTERNAL */
set_field_ulonglong(f, m_row.m_stat.m_write_external.m_count);
break;
- case 69: /* SUM_TIMER_WRITE_EXTERNAL */
+ case 64: /* SUM_TIMER_WRITE_EXTERNAL */
set_field_ulonglong(f, m_row.m_stat.m_write_external.m_sum);
break;
- case 70: /* MIN_TIMER_WRITE_EXTERNAL */
+ case 65: /* MIN_TIMER_WRITE_EXTERNAL */
set_field_ulonglong(f, m_row.m_stat.m_write_external.m_min);
break;
- case 71: /* AVG_TIMER_WRITE_EXTERNAL */
+ case 66: /* AVG_TIMER_WRITE_EXTERNAL */
set_field_ulonglong(f, m_row.m_stat.m_write_external.m_avg);
break;
- case 72: /* MAX_TIMER_WRITE_EXTERNAL */
+ case 67: /* MAX_TIMER_WRITE_EXTERNAL */
set_field_ulonglong(f, m_row.m_stat.m_write_external.m_max);
break;
diff --git a/storage/perfschema/table_tlws_by_table.h b/storage/perfschema/table_tlws_by_table.h
index b5872a07762..7cc4b666908 100644
--- a/storage/perfschema/table_tlws_by_table.h
+++ b/storage/perfschema/table_tlws_by_table.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2015, 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, version 2.0,
@@ -59,6 +59,7 @@ public:
static PFS_engine_table_share m_share;
static PFS_engine_table* create();
static int delete_all_rows();
+ static ha_rows get_row_count();
virtual int rnd_init(bool scan);
virtual int rnd_next();
diff --git a/storage/perfschema/table_users.cc b/storage/perfschema/table_users.cc
index 883ebd36633..734ff7a4e51 100644
--- a/storage/perfschema/table_users.cc
+++ b/storage/perfschema/table_users.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, 2015, 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, version 2.0,
@@ -21,13 +21,16 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
#include "my_global.h"
-#include "my_pthread.h"
+#include "my_thread.h"
#include "table_users.h"
#include "pfs_instr_class.h"
#include "pfs_instr.h"
#include "pfs_account.h"
#include "pfs_user.h"
#include "pfs_visitor.h"
+#include "pfs_memory.h"
+#include "pfs_status.h"
+#include "field.h"
THR_LOCK table_users::m_table_lock;
@@ -36,17 +39,17 @@ table_users::m_share=
{
{ C_STRING_WITH_LEN("users") },
&pfs_truncatable_acl,
- &table_users::create,
+ table_users::create,
NULL, /* write_row */
table_users::delete_all_rows,
- NULL, /* get_row_count */
- 1000, /* records */
+ cursor_by_user::get_row_count,
sizeof(PFS_simple_index), /* ref length */
&m_table_lock,
{ C_STRING_WITH_LEN("CREATE TABLE users("
- "USER CHAR(16) collate utf8_bin default null,"
+ "USER CHAR(" USERNAME_CHAR_LENGTH_STR ") collate utf8_bin default null,"
"CURRENT_CONNECTIONS bigint not null,"
- "TOTAL_CONNECTIONS bigint not null)") }
+ "TOTAL_CONNECTIONS bigint not null)") },
+ false /* perpetual */
};
PFS_engine_table* table_users::create()
@@ -66,6 +69,15 @@ table_users::delete_all_rows(void)
reset_events_statements_by_thread();
reset_events_statements_by_account();
reset_events_statements_by_user();
+ reset_events_transactions_by_thread();
+ reset_events_transactions_by_account();
+ reset_events_transactions_by_user();
+ reset_memory_by_thread();
+ reset_memory_by_account();
+ reset_memory_by_user();
+ reset_status_by_thread();
+ reset_status_by_account();
+ reset_status_by_user();
purge_all_account();
purge_all_user();
return 0;
@@ -78,7 +90,7 @@ table_users::table_users()
void table_users::make_row(PFS_user *pfs)
{
- pfs_lock lock;
+ pfs_optimistic_state lock;
m_row_exists= false;
pfs->m_lock.begin_optimistic_lock(&lock);
@@ -87,7 +99,11 @@ void table_users::make_row(PFS_user *pfs)
return;
PFS_connection_stat_visitor visitor;
- PFS_connection_iterator::visit_user(pfs, true, true, & visitor);
+ PFS_connection_iterator::visit_user(pfs,
+ true, /* accounts */
+ true, /* threads */
+ false, /* THDs */
+ & visitor);
if (! pfs->m_lock.end_optimistic_lock(& lock))
return;
diff --git a/storage/perfschema/table_users.h b/storage/perfschema/table_users.h
index 912f0f43714..1c3cc647a9d 100644
--- a/storage/perfschema/table_users.h
+++ b/storage/perfschema/table_users.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, 2015, 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, version 2.0,
diff --git a/storage/perfschema/table_uvar_by_thread.cc b/storage/perfschema/table_uvar_by_thread.cc
new file mode 100644
index 00000000000..724fc9271d1
--- /dev/null
+++ b/storage/perfschema/table_uvar_by_thread.cc
@@ -0,0 +1,329 @@
+/* Copyright (c) 2013, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/**
+ @file storage/perfschema/table_uvar_by_thread.cc
+ Table USER_VARIABLES_BY_THREAD (implementation).
+*/
+
+#include "my_global.h"
+#include "my_thread.h"
+#include "pfs_instr_class.h"
+#include "pfs_column_types.h"
+#include "pfs_column_values.h"
+#include "table_uvar_by_thread.h"
+#include "pfs_global.h"
+#include "pfs_visitor.h"
+#include "pfs_buffer_container.h"
+
+/* Iteration on THD from the sql layer. */
+#include "sql_class.h"
+//#include "mysqld_thd_manager.h"
+
+class Find_thd_user_var //: public Find_THD_Impl
+{
+public:
+ Find_thd_user_var(THD *unsafe_thd)
+ : m_unsafe_thd(unsafe_thd)
+ {}
+
+ virtual bool operator()(THD *thd)
+ {
+ if (thd != m_unsafe_thd)
+ return false;
+
+ if (thd->user_vars.records == 0)
+ return false;
+
+ mysql_mutex_lock(&thd->LOCK_thd_data);
+ return true;
+ }
+
+private:
+ THD *m_unsafe_thd;
+};
+
+void User_variables::materialize(PFS_thread *pfs, THD *thd)
+{
+ reset();
+
+ m_pfs= pfs;
+ m_thread_internal_id= pfs->m_thread_internal_id;
+ m_array.reserve(thd->user_vars.records);
+
+ user_var_entry *sql_uvar;
+
+ uint index= 0;
+ User_variable empty;
+
+ /* Protects thd->user_vars. */
+ mysql_mutex_assert_owner(&thd->LOCK_thd_data);
+
+ for (;;)
+ {
+ sql_uvar= reinterpret_cast<user_var_entry*> (my_hash_element(& thd->user_vars, index));
+ if (sql_uvar == NULL)
+ break;
+
+ /*
+ m_array is a container of objects (not pointers)
+
+ Naive code can:
+ - build locally a new entry
+ - add it to the container
+ but this causes useless object construction, destruction, and deep copies.
+
+ What we do here:
+ - add a dummy (empty) entry
+ - the container does a deep copy on something empty,
+ so that there is nothing to copy.
+ - get a reference to the entry added in the container
+ - complete -- in place -- the entry initialization
+ */
+ m_array.push(empty);
+ User_variable & pfs_uvar= *m_array.back();
+
+ /* Copy VARIABLE_NAME */
+ const char *name= sql_uvar->name.str;
+ size_t name_length= sql_uvar->name.length;
+ DBUG_ASSERT(name_length <= sizeof(pfs_uvar.m_name));
+ pfs_uvar.m_name.make_row(name, name_length);
+
+ /* Copy VARIABLE_VALUE */
+ bool null_value;
+ String *str_value;
+ String str_buffer;
+ uint decimals= 0;
+ str_value= sql_uvar->val_str(& null_value, & str_buffer, decimals);
+ if (str_value != NULL)
+ {
+ pfs_uvar.m_value.make_row(str_value->ptr(), str_value->length());
+ }
+ else
+ {
+ pfs_uvar.m_value.make_row(NULL, 0);
+ }
+
+ index++;
+ }
+}
+
+THR_LOCK table_uvar_by_thread::m_table_lock;
+
+PFS_engine_table_share
+table_uvar_by_thread::m_share=
+{
+ { C_STRING_WITH_LEN("user_variables_by_thread") },
+ &pfs_readonly_acl,
+ table_uvar_by_thread::create,
+ NULL, /* write_row */
+ NULL, /* delete_all_rows */
+ table_uvar_by_thread::get_row_count,
+ sizeof(pos_t),
+ &m_table_lock,
+ { C_STRING_WITH_LEN("CREATE TABLE user_variables_by_thread("
+ "THREAD_ID BIGINT unsigned not null,"
+ "VARIABLE_NAME VARCHAR(64) not null,"
+ "VARIABLE_VALUE LONGBLOB)") },
+ false /* perpetual */
+};
+
+PFS_engine_table*
+table_uvar_by_thread::create(void)
+{
+ return new table_uvar_by_thread();
+}
+
+ha_rows
+table_uvar_by_thread::get_row_count(void)
+{
+ /*
+ This is an estimate only, not a hard limit.
+ The row count is given as a multiple of thread_max,
+ so that a join between:
+ - table performance_schema.threads
+ - table performance_schema.user_variables_by_thread
+ will still evaluate relative table sizes correctly
+ when deciding a join order.
+ */
+ return global_thread_container.get_row_count() * 10;
+}
+
+table_uvar_by_thread::table_uvar_by_thread()
+ : PFS_engine_table(&m_share, &m_pos),
+ m_row_exists(false), m_pos(), m_next_pos()
+{}
+
+void table_uvar_by_thread::reset_position(void)
+{
+ m_pos.reset();
+ m_next_pos.reset();
+}
+
+int table_uvar_by_thread::rnd_next(void)
+{
+ PFS_thread *thread;
+ bool has_more_thread= true;
+
+ for (m_pos.set_at(&m_next_pos);
+ has_more_thread;
+ m_pos.next_thread())
+ {
+ thread= global_thread_container.get(m_pos.m_index_1, & has_more_thread);
+ if (thread != NULL)
+ {
+ if (materialize(thread) == 0)
+ {
+ const User_variable *uvar= m_THD_cache.get(m_pos.m_index_2);
+ if (uvar != NULL)
+ {
+ make_row(thread, uvar);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+ }
+ }
+ }
+
+ return HA_ERR_END_OF_FILE;
+}
+
+int
+table_uvar_by_thread::rnd_pos(const void *pos)
+{
+ PFS_thread *thread;
+
+ set_position(pos);
+
+ thread= global_thread_container.get(m_pos.m_index_1);
+ if (thread != NULL)
+ {
+ if (materialize(thread) == 0)
+ {
+ const User_variable *uvar= m_THD_cache.get(m_pos.m_index_2);
+ if (uvar != NULL)
+ {
+ make_row(thread, uvar);
+ return 0;
+ }
+ }
+ }
+
+ return HA_ERR_RECORD_DELETED;
+}
+
+int table_uvar_by_thread::materialize(PFS_thread *thread)
+{
+ if (m_THD_cache.is_materialized(thread))
+ return 0;
+
+ if (! thread->m_lock.is_populated())
+ return 1;
+
+ THD *unsafe_thd= thread->m_thd;
+ if (unsafe_thd == NULL)
+ return 1;
+
+ Find_thd_user_var finder(unsafe_thd);
+ THD *safe_thd= NULL;//Global_THD_manager::get_instance()->find_thd(&finder);
+ if (safe_thd == NULL)
+ return 1;
+
+ m_THD_cache.materialize(thread, safe_thd);
+ mysql_mutex_unlock(&safe_thd->LOCK_thd_data);
+ return 0;
+}
+
+void table_uvar_by_thread
+::make_row(PFS_thread *thread, const User_variable *uvar)
+{
+ pfs_optimistic_state lock;
+ m_row_exists= false;
+
+ /* Protect this reader against a thread termination */
+ thread->m_lock.begin_optimistic_lock(&lock);
+
+ m_row.m_thread_internal_id= thread->m_thread_internal_id;
+
+ /* uvar is materialized, pointing to it directly. */
+ m_row.m_variable_name= & uvar->m_name;
+ m_row.m_variable_value= & uvar->m_value;
+
+ if (! thread->m_lock.end_optimistic_lock(&lock))
+ return;
+
+ m_row_exists= true;
+}
+
+int table_uvar_by_thread
+::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;
+
+ DBUG_ASSERT(m_row.m_variable_name != NULL);
+ DBUG_ASSERT(m_row.m_variable_value != NULL);
+
+ for (; (f= *fields) ; fields++)
+ {
+ if (read_all || bitmap_is_set(table->read_set, f->field_index))
+ {
+ switch(f->field_index)
+ {
+ case 0: /* THREAD_ID */
+ set_field_ulonglong(f, m_row.m_thread_internal_id);
+ break;
+ case 1: /* VARIABLE_NAME */
+ set_field_varchar_utf8(f,
+ m_row.m_variable_name->m_str,
+ m_row.m_variable_name->m_length);
+ break;
+ case 2: /* VARIABLE_VALUE */
+ if (m_row.m_variable_value->get_value_length() > 0)
+ {
+ set_field_blob(f,
+ m_row.m_variable_value->get_value(),
+ m_row.m_variable_value->get_value_length());
+ }
+ else
+ {
+ f->set_null();
+ }
+ break;
+ default:
+ DBUG_ASSERT(false);
+ }
+ }
+ }
+
+ return 0;
+}
+
diff --git a/storage/perfschema/table_uvar_by_thread.h b/storage/perfschema/table_uvar_by_thread.h
new file mode 100644
index 00000000000..8d7beace481
--- /dev/null
+++ b/storage/perfschema/table_uvar_by_thread.h
@@ -0,0 +1,193 @@
+/* Copyright (c) 2013, 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#ifndef TABLE_UVAR_BY_THREAD_H
+#define TABLE_UVAR_BY_THREAD_H
+
+/**
+ @file storage/perfschema/table_uvar_by_thread.h
+ Table USER_VARIABLES_BY_THREAD (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "pfs_instr_class.h"
+#include "pfs_instr.h"
+#include "table_helper.h"
+
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+struct User_variable
+{
+public:
+ User_variable()
+ {}
+
+ User_variable(const User_variable& uv)
+ : m_name(uv.m_name), m_value(uv.m_value)
+ {}
+
+ ~User_variable()
+ {}
+
+ PFS_variable_name_row m_name;
+ PFS_user_variable_value_row m_value;
+};
+
+class User_variables
+{
+ typedef Dynamic_array<User_variable> User_variable_array;
+
+public:
+ User_variables()
+ : m_pfs(NULL), m_thread_internal_id(0), m_array(PSI_INSTRUMENT_MEM)
+ {
+ }
+
+ void reset()
+ {
+ m_pfs= NULL;
+ m_thread_internal_id= 0;
+ m_array.clear();
+ }
+
+ void materialize(PFS_thread *pfs, THD *thd);
+
+ bool is_materialized(PFS_thread *pfs)
+ {
+ DBUG_ASSERT(pfs != NULL);
+ if (m_pfs != pfs)
+ return false;
+ if (m_thread_internal_id != pfs->m_thread_internal_id)
+ return false;
+ return true;
+ }
+
+ const User_variable *get(uint index) const
+ {
+ if (index >= m_array.elements())
+ return NULL;
+
+ const User_variable *p= & m_array.at(index);
+ return p;
+ }
+
+private:
+ PFS_thread *m_pfs;
+ ulonglong m_thread_internal_id;
+ User_variable_array m_array;
+};
+
+/**
+ A row of table
+ PERFORMANCE_SCHEMA.USER_VARIABLES_BY_THREAD.
+*/
+struct row_uvar_by_thread
+{
+ /** Column THREAD_ID. */
+ ulonglong m_thread_internal_id;
+ /** Column VARIABLE_NAME. */
+ const PFS_variable_name_row *m_variable_name;
+ /** Column VARIABLE_VALUE. */
+ const PFS_user_variable_value_row *m_variable_value;
+};
+
+/**
+ Position of a cursor on
+ PERFORMANCE_SCHEMA.USER_VARIABLES_BY_THREAD.
+ Index 1 on thread (0 based)
+ Index 2 on user variable (0 based)
+*/
+struct pos_uvar_by_thread
+: public PFS_double_index
+{
+ pos_uvar_by_thread()
+ : PFS_double_index(0, 0)
+ {}
+
+ inline void reset(void)
+ {
+ m_index_1= 0;
+ m_index_2= 0;
+ }
+
+ inline void next_thread(void)
+ {
+ m_index_1++;
+ m_index_2= 0;
+ }
+};
+
+/** Table PERFORMANCE_SCHEMA.USER_VARIABLES_BY_THREAD. */
+class table_uvar_by_thread : public PFS_engine_table
+{
+ typedef pos_uvar_by_thread pos_t;
+
+public:
+ /** Table share */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static ha_rows get_row_count();
+
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+protected:
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+
+ table_uvar_by_thread();
+
+public:
+ ~table_uvar_by_thread()
+ { m_THD_cache.reset(); }
+
+protected:
+ int materialize(PFS_thread *thread);
+ void make_row(PFS_thread *thread, const User_variable *uvar);
+
+private:
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /** Fields definition. */
+ static TABLE_FIELD_DEF m_field_def;
+
+ /** Current THD user variables. */
+ User_variables m_THD_cache;
+ /** Current row. */
+ row_uvar_by_thread m_row;
+ /** True is the current row exists. */
+ bool m_row_exists;
+ /** Current position. */
+ pos_t m_pos;
+ /** Next position. */
+ pos_t m_next_pos;
+};
+
+/** @} */
+#endif
diff --git a/storage/perfschema/table_variables_by_thread.cc b/storage/perfschema/table_variables_by_thread.cc
new file mode 100644
index 00000000000..0e1c1021635
--- /dev/null
+++ b/storage/perfschema/table_variables_by_thread.cc
@@ -0,0 +1,229 @@
+/* Copyright (c) 2015, 2018, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/**
+ @file storage/perfschema/table_variables_by_thread.cc
+ Table VARIABLES_BY_THREAD (implementation).
+*/
+
+#include "my_global.h"
+#include "table_variables_by_thread.h"
+#include "my_thread.h"
+#include "pfs_instr_class.h"
+#include "pfs_column_types.h"
+#include "pfs_column_values.h"
+#include "pfs_global.h"
+
+THR_LOCK table_variables_by_thread::m_table_lock;
+
+PFS_engine_table_share
+table_variables_by_thread::m_share=
+{
+ { C_STRING_WITH_LEN("variables_by_thread") },
+ &pfs_readonly_acl,
+ table_variables_by_thread::create,
+ NULL, /* write_row */
+ NULL, /* delete_all_rows */
+ table_variables_by_thread::get_row_count,
+ sizeof(pos_t),
+ &m_table_lock,
+ { C_STRING_WITH_LEN("CREATE TABLE user_variables_by_thread("
+ "THREAD_ID BIGINT unsigned not null,"
+ "VARIABLE_NAME VARCHAR(64) not null,"
+ "VARIABLE_VALUE LONGBLOB)") },
+ true /* perpetual */
+};
+
+PFS_engine_table*
+table_variables_by_thread::create(void)
+{
+ return new table_variables_by_thread();
+}
+
+ha_rows table_variables_by_thread::get_row_count(void)
+{
+ mysql_mutex_lock(&LOCK_plugin_delete);
+ mysql_rwlock_rdlock(&LOCK_system_variables_hash);
+ ulong system_var_count= get_system_variable_hash_records();
+ mysql_rwlock_unlock(&LOCK_system_variables_hash);
+ mysql_mutex_unlock(&LOCK_plugin_delete);
+ return (global_thread_container.get_row_count() * system_var_count);
+}
+
+table_variables_by_thread::table_variables_by_thread()
+ : PFS_engine_table(&m_share, &m_pos),
+ m_sysvar_cache(true), m_row_exists(false), m_pos(), m_next_pos(), m_context(NULL)
+{}
+
+void table_variables_by_thread::reset_position(void)
+{
+ m_pos.reset();
+ m_next_pos.reset();
+}
+
+int table_variables_by_thread::rnd_init(bool scan)
+{
+ /*
+ Build array of SHOW_VARs from system variable hash prior to materializing
+ threads in rnd_next() or rnd_pos().
+ */
+ m_sysvar_cache.initialize_session();
+
+ /* Record the version of the system variable hash. */
+ ulonglong hash_version= m_sysvar_cache.get_sysvar_hash_version();
+
+ /*
+ The table context holds the current version of the system variable hash and
+ a record of which threads were materialized.
+ If scan == true, then allocate a new context from mem_root and store in TLS.
+ If scan == false, then restore from TLS.
+ */
+ m_context= (table_variables_by_thread_context *)current_thd->alloc(sizeof(table_variables_by_thread_context));
+ new(m_context) table_variables_by_thread_context(hash_version, !scan);
+ return 0;
+}
+
+int table_variables_by_thread::rnd_next(void)
+{
+ /* If system variable hash changes, exit with warning. */ // TODO: Issue warning
+ if (!m_context->versions_match())
+ return HA_ERR_END_OF_FILE;
+
+ bool has_more_thread= true;
+
+ for (m_pos.set_at(&m_next_pos);
+ has_more_thread;
+ m_pos.next_thread())
+ {
+ PFS_thread *pfs_thread= global_thread_container.get(m_pos.m_index_1, &has_more_thread);
+
+ /* Materialize all variables for the current thread. Assign a dedicated mem_root. */
+ if (m_sysvar_cache.materialize_session(pfs_thread, true) == 0)
+ {
+ /* Mark this thread as materialized. */
+ m_context->set_item(m_pos.m_index_1);
+
+ const System_variable *system_var= m_sysvar_cache.get(m_pos.m_index_2);
+ if (system_var != NULL)
+ {
+ make_row(pfs_thread, system_var);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+ }
+ }
+ return HA_ERR_END_OF_FILE;
+}
+
+int
+table_variables_by_thread::rnd_pos(const void *pos)
+{
+ /* If system variable hash changes, do nothing. */
+ if (!m_context->versions_match())
+ return HA_ERR_RECORD_DELETED;
+
+ set_position(pos);
+ DBUG_ASSERT(m_pos.m_index_1 < global_thread_container.get_row_count());
+
+ PFS_thread *pfs_thread= global_thread_container.get(m_pos.m_index_1);
+ /*
+ Only materialize threads that were previously materialized by rnd_next().
+ If a thread cannot be rematerialized, then do nothing.
+ Only materialize the requested system variable to avoid repeated
+ materialization of each thread, such as with ORDER BY variable_name.
+ */
+ if (m_context->is_item_set(m_pos.m_index_1) &&
+ /* Materialize only the requested variable. */
+ m_sysvar_cache.materialize_session(pfs_thread, m_pos.m_index_2) == 0)
+ {
+ /* Get the first (and only) element from the cache. */
+ const System_variable *system_var= m_sysvar_cache.get();
+ if (system_var != NULL)
+ {
+ make_row(pfs_thread, system_var);
+ m_next_pos.set_after(&m_pos);
+ return 0;
+ }
+ }
+ return HA_ERR_RECORD_DELETED;
+}
+
+void table_variables_by_thread
+::make_row(PFS_thread *thread, const System_variable *system_var)
+{
+ pfs_optimistic_state lock;
+ m_row_exists= false;
+ if (system_var->is_null() || system_var->is_ignored())
+ return;
+
+ /* Protect this reader against a thread termination */
+ thread->m_lock.begin_optimistic_lock(&lock);
+
+ m_row.m_thread_internal_id= thread->m_thread_internal_id;
+ m_row.m_variable_name.make_row(system_var->m_name, system_var->m_name_length);
+ m_row.m_variable_value.make_row(system_var);
+
+ if (!thread->m_lock.end_optimistic_lock(&lock))
+ return;
+
+ m_row_exists= true;
+}
+
+int table_variables_by_thread
+::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 0: /* THREAD_ID */
+ set_field_ulonglong(f, m_row.m_thread_internal_id);
+ break;
+ case 1: /* VARIABLE_NAME */
+ set_field_varchar_utf8(f, m_row.m_variable_name.m_str, m_row.m_variable_name.m_length);
+ break;
+ case 2: /* VARIABLE_VALUE */
+ m_row.m_variable_value.set_field(f);
+ break;
+ default:
+ DBUG_ASSERT(false);
+ }
+ }
+ }
+
+ return 0;
+}
+
diff --git a/storage/perfschema/table_variables_by_thread.h b/storage/perfschema/table_variables_by_thread.h
new file mode 100644
index 00000000000..d628707f9b4
--- /dev/null
+++ b/storage/perfschema/table_variables_by_thread.h
@@ -0,0 +1,151 @@
+/* Copyright (c) 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#ifndef TABLE_VARIABLES_BY_THREAD_H
+#define TABLE_VARIABLES_BY_THREAD_H
+
+/**
+ @file storage/perfschema/table_variables_by_thread.h
+ Table VARIABLES_BY_THREAD (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "pfs_instr_class.h"
+#include "pfs_instr.h"
+#include "table_helper.h"
+#include "pfs_variable.h"
+#include "pfs_buffer_container.h"
+
+/**
+ @addtogroup Performance_schema_tables
+ @{
+*/
+
+/**
+ A row of table
+ PERFORMANCE_SCHEMA.VARIABLES_BY_THREAD.
+*/
+struct row_variables_by_thread
+{
+ /** Column THREAD_ID. */
+ ulonglong m_thread_internal_id;
+ /** Column VARIABLE_NAME. */
+ PFS_variable_name_row m_variable_name;
+ /** Column VARIABLE_VALUE. */
+ PFS_variable_value_row m_variable_value;
+};
+
+/**
+ Position of a cursor on
+ PERFORMANCE_SCHEMA.VARIABLES_BY_THREAD.
+ Index 1 on thread (0 based)
+ Index 2 on system variable (0 based)
+*/
+struct pos_variables_by_thread
+: public PFS_double_index
+{
+ pos_variables_by_thread()
+ : PFS_double_index(0, 0)
+ {}
+
+ inline void reset(void)
+ {
+ m_index_1= 0;
+ m_index_2= 0;
+ }
+
+ inline bool has_more_thread(void)
+ { return (m_index_1 < global_thread_container.get_row_count()); }
+
+ inline void next_thread(void)
+ {
+ m_index_1++;
+ m_index_2= 0;
+ }
+};
+
+/**
+ Store and retrieve table state information during queries that reinstantiate
+ the table object.
+*/
+class table_variables_by_thread_context : public PFS_table_context
+{
+public:
+ table_variables_by_thread_context(ulonglong hash_version, bool restore) :
+ PFS_table_context(hash_version, global_thread_container.get_row_count(), restore, THR_PFS_VBT) { }
+};
+
+/** Table PERFORMANCE_SCHEMA.VARIABLES_BY_THREAD. */
+class table_variables_by_thread : public PFS_engine_table
+{
+ typedef pos_variables_by_thread pos_t;
+
+public:
+ /** Table share */
+ static PFS_engine_table_share m_share;
+ static PFS_engine_table* create();
+ static ha_rows get_row_count();
+
+ virtual int rnd_init(bool scan);
+ virtual int rnd_next();
+ virtual int rnd_pos(const void *pos);
+ virtual void reset_position(void);
+
+protected:
+ virtual int read_row_values(TABLE *table,
+ unsigned char *buf,
+ Field **fields,
+ bool read_all);
+ table_variables_by_thread();
+
+public:
+ ~table_variables_by_thread()
+ {}
+
+protected:
+ int materialize(PFS_thread *thread);
+ void make_row(PFS_thread *thread, const System_variable *system_var);
+
+private:
+ /** Table share lock. */
+ static THR_LOCK m_table_lock;
+ /** Fields definition. */
+ static TABLE_FIELD_DEF m_field_def;
+
+ /** Current THD variables. */
+ PFS_system_variable_cache m_sysvar_cache;
+ /** Current row. */
+ row_variables_by_thread m_row;
+ /** True if the current row exists. */
+ bool m_row_exists;
+ /** Current position. */
+ pos_t m_pos;
+ /** Next position. */
+ pos_t m_next_pos;
+
+ /** Table context with system variable hash version and map of materialized threads. */
+ table_variables_by_thread_context *m_context;
+};
+
+/** @} */
+#endif
diff --git a/storage/perfschema/unittest/CMakeLists.txt b/storage/perfschema/unittest/CMakeLists.txt
index 7b8c906a4e6..1bba2673a1a 100644
--- a/storage/perfschema/unittest/CMakeLists.txt
+++ b/storage/perfschema/unittest/CMakeLists.txt
@@ -35,5 +35,6 @@ ADD_CONVENIENCE_LIBRARY(pfs_server_stubs pfs_server_stubs.cc)
ADD_DEPENDENCIES(pfs_server_stubs GenError)
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 pfs_misc
+ pfs_account-oom pfs_host-oom pfs_timer pfs_user-oom pfs_noop pfs
+ pfs_misc
EXT "cc" LINK_LIBRARIES perfschema mysys pfs_server_stubs)
diff --git a/storage/perfschema/unittest/pfs-t.cc b/storage/perfschema/unittest/pfs-t.cc
index f5f38367691..43d9d8d233d 100644
--- a/storage/perfschema/unittest/pfs-t.cc
+++ b/storage/perfschema/unittest/pfs-t.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2017, 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, version 2.0,
@@ -21,11 +21,12 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
#include <my_global.h>
-#include <my_pthread.h>
+#include <my_thread.h>
#include <pfs_server.h>
#include <pfs_instr_class.h>
#include <pfs_instr.h>
#include <pfs_global.h>
+#include <pfs_buffer_container.h>
#include <tap.h>
#include <string.h>
@@ -33,6 +34,7 @@
#include "stub_print_error.h"
#include "stub_pfs_defaults.h"
+#include "stub_global_status_var.h"
void unload_performance_schema();
@@ -48,30 +50,30 @@ void setup_thread(PSI_thread *t, bool enabled)
PFS_file* lookup_file_by_name(const char* name)
{
- uint i;
PFS_file *pfs;
size_t len= strlen(name);
size_t dirlen;
const char *filename;
- size_t filename_length;;
+ size_t filename_length;
- for (i= 0; i < file_max; i++)
+ PFS_file_iterator it= global_file_container.iterate();
+ pfs= it.scan_next();
+
+ while (pfs != NULL)
{
- pfs= & file_array[i];
- if (pfs->m_lock.is_populated())
- {
- /*
- When a file "foo" is instrumented, the name is normalized
- to "/path/to/current/directory/foo", so we remove the
- directory name here to find it back.
- */
- dirlen= dirname_length(pfs->m_filename);
- filename= pfs->m_filename + dirlen;
- filename_length= pfs->m_filename_length - dirlen;
- if ((len == filename_length) &&
- (strncmp(name, filename, filename_length) == 0))
- return pfs;
- }
+ /*
+ When a file "foo" is instrumented, the name is normalized
+ to "/path/to/current/directory/foo", so we remove the
+ directory name here to find it back.
+ */
+ dirlen= dirname_length(pfs->m_filename);
+ filename= pfs->m_filename + dirlen;
+ filename_length= pfs->m_filename_length - dirlen;
+ if ((len == filename_length) &&
+ (strncmp(name, filename, filename_length) == 0))
+ return pfs;
+
+ pfs= it.scan_next();
}
return NULL;
@@ -118,10 +120,24 @@ void test_bootstrap()
param.m_statement_class_sizing= 0;
param.m_events_statements_history_sizing= 0;
param.m_events_statements_history_long_sizing= 0;
+ param.m_events_transactions_history_sizing= 0;
+ param.m_events_transactions_history_long_sizing= 0;
param.m_digest_sizing= 0;
param.m_session_connect_attrs_sizing= 0;
+ param.m_program_sizing= 0;
+ param.m_statement_stack_sizing= 0;
+ param.m_memory_class_sizing= 0;
+ param.m_metadata_lock_sizing= 0;
param.m_max_digest_length= 0;
+ param.m_max_sql_text_length= 0;
+
+ param.m_hints.m_table_definition_cache = 100;
+ param.m_hints.m_table_open_cache = 100;
+ param.m_hints.m_max_connections = 100;
+ param.m_hints.m_open_files_limit = 100;
+ param.m_hints.m_max_prepared_stmt_count= 100;
+ pre_initialize_performance_schema();
boot= initialize_performance_schema(& param);
ok(boot != NULL, "boot");
ok(boot->get_interface != NULL, "boot->get_interface");
@@ -143,7 +159,7 @@ void test_bootstrap()
*/
PSI * load_perfschema()
{
- void *psi;
+ PSI *psi;
PSI_bootstrap *boot;
PFS_global_param param;
@@ -177,13 +193,27 @@ PSI * load_perfschema()
param.m_statement_class_sizing= 0;
param.m_events_statements_history_sizing= 0;
param.m_events_statements_history_long_sizing= 0;
+ param.m_events_transactions_history_sizing= 0;
+ param.m_events_transactions_history_long_sizing= 0;
param.m_digest_sizing= 0;
param.m_session_connect_attrs_sizing= 0;
+ param.m_program_sizing= 0;
+ param.m_statement_stack_sizing= 10;
+ param.m_memory_class_sizing= 10;
+ param.m_metadata_lock_sizing= 10;
param.m_max_digest_length= 0;
+ param.m_max_sql_text_length= 1000;
+
+ param.m_hints.m_table_definition_cache = 100;
+ param.m_hints.m_table_open_cache = 100;
+ param.m_hints.m_max_connections = 100;
+ param.m_hints.m_open_files_limit = 100;
+ param.m_hints.m_max_prepared_stmt_count= 100;
+ pre_initialize_performance_schema();
/* test_bootstrap() covered this, assuming it just works */
boot= initialize_performance_schema(& param);
- psi= boot->get_interface(PSI_VERSION_1);
+ psi= (PSI *)boot->get_interface(PSI_VERSION_1);
/* Reset every consumer to a known state */
flag_global_instrumentation= true;
@@ -335,6 +365,20 @@ void test_bad_registration()
ok(dummy_rwlock_key == 0, "zero key");
dummy_rwlock_key= 9999;
+ PSI_rwlock_info bad_rwlock_2_sx[]=
+ {
+ { & dummy_rwlock_key,
+ /* 109 chars name */
+ "12345678901234567890123456789012345678901234567890"
+ "12345678901234567890123456789012345678901234567890"
+ "123456789",
+ PSI_RWLOCK_FLAG_SX}
+ };
+
+ psi->register_rwlock("Y", bad_rwlock_2_sx, 1);
+ ok(dummy_rwlock_key == 0, "zero key SX");
+
+ dummy_rwlock_key= 9999;
PSI_rwlock_info bad_rwlock_3[]=
{
{ & dummy_rwlock_key,
@@ -351,6 +395,23 @@ void test_bad_registration()
psi->register_rwlock("X", bad_rwlock_3, 1);
ok(dummy_rwlock_key == 2, "assigned key");
+ dummy_rwlock_key= 9999;
+ PSI_rwlock_info bad_rwlock_3_sx[]=
+ {
+ { & dummy_rwlock_key,
+ /* 108 chars name */
+ "12345678901234567890123456789012345678901234567890"
+ "12345678901234567890123456789012345678901234567890"
+ "12345678",
+ PSI_RWLOCK_FLAG_SX}
+ };
+
+ psi->register_rwlock("YY", bad_rwlock_3_sx, 1);
+ ok(dummy_rwlock_key == 0, "zero key SX");
+
+ psi->register_rwlock("Y", bad_rwlock_3_sx, 1);
+ ok(dummy_rwlock_key == 3, "assigned key SX");
+
/*
Test that length('wait/synch/cond/' (16) + category + '/' (1)) < 32
--> category can be up to 14 chars for a cond.
@@ -698,23 +759,27 @@ void test_init_disabled()
socket_class_A= find_socket_class(socket_key_A);
ok(socket_class_A != NULL, "socket class A");
- /* Pretend thread T-1 is running, and disabled, with thread_instrumentation */
+ /*
+ Pretend thread T-1 is running, and disabled, with thread_instrumentation.
+ Disabled instruments are still created so they can be enabled later.
+ */
+
/* ------------------------------------------------------------------------ */
psi->set_thread(thread_1);
setup_thread(thread_1, false);
- /* disabled M-A + disabled T-1: no instrumentation */
+ /* disabled M-A + disabled T-1: instrumentation */
mutex_class_A->m_enabled= false;
mutex_A1= psi->init_mutex(mutex_key_A, NULL);
- ok(mutex_A1 == NULL, "mutex_A1 not instrumented");
+ ok(mutex_A1 != NULL, "mutex_A1 disabled, instrumented");
/* enabled M-A + disabled T-1: instrumentation (for later) */
mutex_class_A->m_enabled= true;
mutex_A1= psi->init_mutex(mutex_key_A, NULL);
- ok(mutex_A1 != NULL, "mutex_A1 instrumented");
+ ok(mutex_A1 != NULL, "mutex_A1 enabled, instrumented");
/* broken key + disabled T-1: no instrumentation */
@@ -728,13 +793,13 @@ void test_init_disabled()
rwlock_class_A->m_enabled= false;
rwlock_A1= psi->init_rwlock(rwlock_key_A, NULL);
- ok(rwlock_A1 == NULL, "rwlock_A1 not instrumented");
+ ok(rwlock_A1 != NULL, "rwlock_A1 disabled, instrumented");
/* enabled RW-A + disabled T-1: instrumentation (for later) */
rwlock_class_A->m_enabled= true;
rwlock_A1= psi->init_rwlock(rwlock_key_A, NULL);
- ok(rwlock_A1 != NULL, "rwlock_A1 instrumented");
+ ok(rwlock_A1 != NULL, "rwlock_A1 enabled, instrumented");
/* broken key + disabled T-1: no instrumentation */
@@ -748,13 +813,13 @@ void test_init_disabled()
cond_class_A->m_enabled= false;
cond_A1= psi->init_cond(cond_key_A, NULL);
- ok(cond_A1 == NULL, "cond_A1 not instrumented");
+ ok(cond_A1 != NULL, "cond_A1 disabled, instrumented");
/* enabled C-A + disabled T-1: instrumentation (for later) */
cond_class_A->m_enabled= true;
cond_A1= psi->init_cond(cond_key_A, NULL);
- ok(cond_A1 != NULL, "cond_A1 instrumented");
+ ok(cond_A1 != NULL, "cond_A1 enabled, instrumented");
/* broken key + disabled T-1: no instrumentation */
@@ -783,22 +848,22 @@ void test_init_disabled()
file_class_A->m_enabled= true;
psi->create_file(0, "foo", (File) 12);
file_A1= lookup_file_by_name("foo");
- ok(file_A1 == NULL, "not instrumented");
+ ok(file_A1 == NULL, "file_A1 not instrumented");
psi->create_file(99, "foo", (File) 12);
file_A1= lookup_file_by_name("foo");
- ok(file_A1 == NULL, "not instrumented");
+ ok(file_A1 == NULL, "file_A1 not instrumented");
/* disabled S-A + disabled T-1: no instrumentation */
socket_class_A->m_enabled= false;
socket_A1= psi->init_socket(socket_key_A, NULL, NULL, 0);
- ok(socket_A1 == NULL, "socket_A1 not instrumented");
+ ok(socket_A1 != NULL, "socket_A1 disabled, 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, NULL, 0);
- ok(socket_A1 != NULL, "socket_A1 instrumented");
+ ok(socket_A1 != NULL, "socket_A1 enabled, instrumented");
/* broken key + disabled T-1: no instrumentation */
@@ -807,7 +872,7 @@ void test_init_disabled()
ok(socket_A1 == NULL, "socket key 0 not instrumented");
socket_A1= psi->init_socket(99, NULL, NULL, 0);
ok(socket_A1 == NULL, "broken socket key not instrumented");
-
+
/* Pretend thread T-1 is enabled */
/* ----------------------------- */
@@ -817,85 +882,85 @@ void test_init_disabled()
mutex_class_A->m_enabled= false;
mutex_A1= psi->init_mutex(mutex_key_A, NULL);
- ok(mutex_A1 == NULL, "not instrumented");
+ ok(mutex_A1 != NULL, "mutex_A1 disabled, instrumented");
/* enabled M-A + enabled T-1: instrumentation */
mutex_class_A->m_enabled= true;
mutex_A1= psi->init_mutex(mutex_key_A, NULL);
- ok(mutex_A1 != NULL, "instrumented");
+ ok(mutex_A1 != NULL, "mutex_A1 enabled, instrumented");
psi->destroy_mutex(mutex_A1);
/* broken key + enabled T-1: no instrumentation */
mutex_class_A->m_enabled= true;
mutex_A1= psi->init_mutex(0, NULL);
- ok(mutex_A1 == NULL, "not instrumented");
+ ok(mutex_A1 == NULL, "mutex_A1 not instrumented");
mutex_A1= psi->init_mutex(99, NULL);
- ok(mutex_A1 == NULL, "not instrumented");
+ ok(mutex_A1 == NULL, "mutex_A1 not instrumented");
/* disabled RW-A + enabled T-1: no instrumentation */
rwlock_class_A->m_enabled= false;
rwlock_A1= psi->init_rwlock(rwlock_key_A, NULL);
- ok(rwlock_A1 == NULL, "not instrumented");
+ ok(rwlock_A1 != NULL, "rwlock_A1 disabled, instrumented");
/* enabled RW-A + enabled T-1: instrumentation */
rwlock_class_A->m_enabled= true;
rwlock_A1= psi->init_rwlock(rwlock_key_A, NULL);
- ok(rwlock_A1 != NULL, "instrumented");
+ ok(rwlock_A1 != NULL, "rwlock_A1 enabled, instrumented");
psi->destroy_rwlock(rwlock_A1);
/* broken key + enabled T-1: no instrumentation */
rwlock_class_A->m_enabled= true;
rwlock_A1= psi->init_rwlock(0, NULL);
- ok(rwlock_A1 == NULL, "not instrumented");
+ ok(rwlock_A1 == NULL, "rwlock_A1 not instrumented");
rwlock_A1= psi->init_rwlock(99, NULL);
- ok(rwlock_A1 == NULL, "not instrumented");
+ ok(rwlock_A1 == NULL, "rwlock_A1 not instrumented");
/* disabled C-A + enabled T-1: no instrumentation */
cond_class_A->m_enabled= false;
cond_A1= psi->init_cond(cond_key_A, NULL);
- ok(cond_A1 == NULL, "not instrumented");
+ ok(cond_A1 != NULL, "cond_A1 disabled, instrumented");
/* enabled C-A + enabled T-1: instrumentation */
cond_class_A->m_enabled= true;
cond_A1= psi->init_cond(cond_key_A, NULL);
- ok(cond_A1 != NULL, "instrumented");
+ ok(cond_A1 != NULL, "cond_A1 enabled, instrumented");
psi->destroy_cond(cond_A1);
/* broken key + enabled T-1: no instrumentation */
cond_class_A->m_enabled= true;
cond_A1= psi->init_cond(0, NULL);
- ok(cond_A1 == NULL, "not instrumented");
+ ok(cond_A1 == NULL, "cond_A1 not instrumented");
cond_A1= psi->init_cond(99, NULL);
- ok(cond_A1 == NULL, "not instrumented");
+ ok(cond_A1 == NULL, "cond_A1 not instrumented");
/* disabled F-A + enabled T-1: no instrumentation */
file_class_A->m_enabled= false;
psi->create_file(file_key_A, "foo", (File) 12);
file_A1= lookup_file_by_name("foo");
- ok(file_A1 == NULL, "not instrumented");
+ ok(file_A1 == NULL, "file_A1 not instrumented");
/* enabled F-A + open failed + enabled T-1: no instrumentation */
file_class_A->m_enabled= true;
psi->create_file(file_key_A, "foo", (File) -1);
file_A1= lookup_file_by_name("foo");
- ok(file_A1 == NULL, "not instrumented");
+ ok(file_A1 == NULL, "file_A1 not instrumented");
/* enabled F-A + out-of-descriptors + enabled T-1: no instrumentation */
file_class_A->m_enabled= true;
psi->create_file(file_key_A, "foo", (File) 65000);
file_A1= lookup_file_by_name("foo");
- ok(file_A1 == NULL, "not instrumented");
+ ok(file_A1 == NULL, "file_A1 not instrumented");
ok(file_handle_lost == 1, "lost a file handle");
file_handle_lost= 0;
@@ -920,22 +985,22 @@ void test_init_disabled()
/* disabled S-A + enabled T-1: no instrumentation */
socket_class_A->m_enabled= false;
- ok(socket_A1 == NULL, "not instrumented");
+ ok(socket_A1 == NULL, "socket_A1 not instrumented");
/* enabled S-A + enabled T-1: instrumentation */
socket_class_A->m_enabled= true;
socket_A1= psi->init_socket(socket_key_A, NULL, NULL, 0);
- ok(socket_A1 != NULL, "instrumented");
+ ok(socket_A1 != NULL, "socket_A1 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, NULL, 0);
- ok(socket_A1 == NULL, "not instrumented");
+ ok(socket_A1 == NULL, "socket_A1 not instrumented");
socket_A1= psi->init_socket(99, NULL, NULL, 0);
- ok(socket_A1 == NULL, "not instrumented");
+ ok(socket_A1 == NULL, "socket_A1 not instrumented");
/* Pretend the running thread is not instrumented */
/* ---------------------------------------------- */
@@ -946,13 +1011,13 @@ void test_init_disabled()
mutex_class_A->m_enabled= false;
mutex_A1= psi->init_mutex(mutex_key_A, NULL);
- ok(mutex_A1 == NULL, "mutex_A1 not instrumented");
+ ok(mutex_A1 != NULL, "mutex_A1 disabled, instrumented");
/* enabled M-A + unknown thread: instrumentation (for later) */
mutex_class_A->m_enabled= true;
mutex_A1= psi->init_mutex(mutex_key_A, NULL);
- ok(mutex_A1 != NULL, "mutex_A1 instrumented");
+ ok(mutex_A1 != NULL, "mutex_A1 enabled, instrumented");
/* broken key + unknown thread: no instrumentation */
@@ -966,13 +1031,13 @@ void test_init_disabled()
rwlock_class_A->m_enabled= false;
rwlock_A1= psi->init_rwlock(rwlock_key_A, NULL);
- ok(rwlock_A1 == NULL, "rwlock_A1 not instrumented");
+ ok(rwlock_A1 != NULL, "rwlock_A1 disabled, instrumented");
/* enabled RW-A + unknown thread: instrumentation (for later) */
rwlock_class_A->m_enabled= true;
rwlock_A1= psi->init_rwlock(rwlock_key_A, NULL);
- ok(rwlock_A1 != NULL, "rwlock_A1 instrumented");
+ ok(rwlock_A1 != NULL, "rwlock_A1 enabled, instrumented");
/* broken key + unknown thread: no instrumentation */
@@ -986,13 +1051,13 @@ void test_init_disabled()
cond_class_A->m_enabled= false;
cond_A1= psi->init_cond(cond_key_A, NULL);
- ok(cond_A1 == NULL, "cond_A1 not instrumented");
+ ok(cond_A1 != NULL, "cond_A1 disabled, instrumented");
/* enabled C-A + unknown thread: instrumentation (for later) */
cond_class_A->m_enabled= true;
cond_A1= psi->init_cond(cond_key_A, NULL);
- ok(cond_A1 != NULL, "cond_A1 instrumented");
+ ok(cond_A1 != NULL, "cond_A1 enabled, instrumented");
/* broken key + unknown thread: no instrumentation */
@@ -1007,14 +1072,14 @@ void test_init_disabled()
file_class_A->m_enabled= false;
psi->create_file(file_key_A, "foo", (File) 12);
file_A1= lookup_file_by_name("foo");
- ok(file_A1 == NULL, "not instrumented");
+ ok(file_A1 == NULL, "file_A1 not instrumented");
/* enabled F-A + unknown thread: no instrumentation */
file_class_A->m_enabled= true;
psi->create_file(file_key_A, "foo", (File) 12);
file_A1= lookup_file_by_name("foo");
- ok(file_A1 == NULL, "not instrumented");
+ ok(file_A1 == NULL, "file_A1 not instrumented");
/* broken key + unknown thread: no instrumentation */
@@ -1030,13 +1095,13 @@ void test_init_disabled()
socket_class_A->m_enabled= false;
socket_A1= psi->init_socket(socket_key_A, NULL, NULL, 0);
- ok(socket_A1 == NULL, "socket_A1 not instrumented");
+ ok(socket_A1 != NULL, "socket_A1 disabled, instrumented");
/* enabled S-A + unknown thread: instrumentation (for later) */
socket_class_A->m_enabled= true;
socket_A1= psi->init_socket(socket_key_A, NULL, NULL, 0);
- ok(socket_A1 != NULL, "socket_A1 instrumented");
+ ok(socket_A1 != NULL, "socket_A1 enabled, instrumented");
/* broken key + unknown thread: no instrumentation */
@@ -1521,7 +1586,7 @@ 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 */
+ /* NOTE: Need to add 4 to each index: table io, table lock, idle, metadata lock */
/* Per mutex info waits should be at [0..9] */
param.m_mutex_class_sizing= 10;
@@ -1546,9 +1611,16 @@ void test_event_name_index()
param.m_statement_class_sizing= 0;
param.m_events_statements_history_sizing= 0;
param.m_events_statements_history_long_sizing= 0;
+ param.m_events_transactions_history_sizing= 0;
+ param.m_events_transactions_history_long_sizing= 0;
param.m_digest_sizing= 0;
param.m_session_connect_attrs_sizing= 0;
+ param.m_program_sizing= 0;
+ param.m_statement_stack_sizing= 10;
+ param.m_memory_class_sizing= 12;
+ param.m_metadata_lock_sizing= 10;
param.m_max_digest_length= 0;
+ param.m_max_sql_text_length= 1000;
param.m_mutex_sizing= 0;
param.m_rwlock_sizing= 0;
@@ -1563,6 +1635,13 @@ void test_event_name_index()
param.m_setup_actor_sizing= 0;
param.m_setup_object_sizing= 0;
+ param.m_hints.m_table_definition_cache = 100;
+ param.m_hints.m_table_open_cache = 100;
+ param.m_hints.m_max_connections = 100;
+ param.m_hints.m_open_files_limit = 100;
+ param.m_hints.m_max_prepared_stmt_count= 100;
+
+ pre_initialize_performance_schema();
boot= initialize_performance_schema(& param);
ok(boot != NULL, "bootstrap");
psi= (PSI*) boot->get_interface(PSI_VERSION_1);
@@ -1580,10 +1659,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 == 3, "index 3");
+ ok(mutex_class->m_event_name_index == 4, "index 4");
mutex_class= find_mutex_class(dummy_mutex_key_2);
ok(mutex_class != NULL, "mutex class 2");
- ok(mutex_class->m_event_name_index == 4, "index 4");
+ ok(mutex_class->m_event_name_index == 5, "index 5");
PFS_rwlock_class *rwlock_class;
PSI_rwlock_key dummy_rwlock_key_1;
@@ -1597,10 +1676,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 == 13, "index 13");
+ ok(rwlock_class->m_event_name_index == 14, "index 14");
rwlock_class= find_rwlock_class(dummy_rwlock_key_2);
ok(rwlock_class != NULL, "rwlock class 2");
- ok(rwlock_class->m_event_name_index == 14, "index 14");
+ ok(rwlock_class->m_event_name_index == 15, "index 15");
PFS_cond_class *cond_class;
PSI_cond_key dummy_cond_key_1;
@@ -1614,10 +1693,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 == 33, "index 33");
+ ok(cond_class->m_event_name_index == 34, "index 34");
cond_class= find_cond_class(dummy_cond_key_2);
ok(cond_class != NULL, "cond class 2");
- ok(cond_class->m_event_name_index == 34, "index 34");
+ ok(cond_class->m_event_name_index == 35, "index 35");
PFS_file_class *file_class;
PSI_file_key dummy_file_key_1;
@@ -1631,10 +1710,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 == 73, "index 73");
+ ok(file_class->m_event_name_index == 74, "index 74");
file_class= find_file_class(dummy_file_key_2);
ok(file_class != NULL, "file class 2");
- ok(file_class->m_event_name_index == 74, "index 74");
+ ok(file_class->m_event_name_index == 75, "index 75");
PFS_socket_class *socket_class;
PSI_socket_key dummy_socket_key_1;
@@ -1648,14 +1727,162 @@ 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 == 153, "index 153");
+ ok(socket_class->m_event_name_index == 154, "index 154");
socket_class= find_socket_class(dummy_socket_key_2);
ok(socket_class != NULL, "socket class 2");
- ok(socket_class->m_event_name_index == 154, "index 154");
+ ok(socket_class->m_event_name_index == 155, "index 155");
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
+ ok(wait_class_max= 314, "314 event names"); // 4 global classes
+
+ shutdown_performance_schema();
+}
+
+void test_memory_instruments()
+{
+ PSI *psi;
+ PSI_thread *owner;
+
+ diag("test_memory_instruments");
+
+ psi= load_perfschema();
+
+ PSI_memory_key memory_key_A;
+ PSI_memory_info all_memory[]=
+ {
+ { & memory_key_A, "M-A", 0}
+ };
+
+ PSI_thread_key thread_key_1;
+ PSI_thread_info all_thread[]=
+ {
+ { & thread_key_1, "T-1", 0}
+ };
+
+ psi->register_memory("test", all_memory, 1);
+ psi->register_thread("test", all_thread, 1);
+
+ PFS_memory_class *memory_class_A;
+ PSI_thread *thread_1;
+ PSI_memory_key key;
+
+ /* Preparation */
+
+ thread_1= psi->new_thread(thread_key_1, NULL, 0);
+ ok(thread_1 != NULL, "T-1");
+ psi->set_thread_id(thread_1, 1);
+
+ memory_class_A= find_memory_class(memory_key_A);
+ ok(memory_class_A != NULL, "memory info A");
+
+ /* Pretend thread T-1 is running, and enabled */
+ /* ------------------------------------------ */
+
+ psi->set_thread(thread_1);
+ setup_thread(thread_1, true);
+
+ /* Enable all instruments */
+
+ memory_class_A->m_enabled= true;
+
+ /* for coverage, need to print stats collected. */
+
+ key= psi->memory_alloc(memory_key_A, 100, & owner);
+ ok(key == memory_key_A, "alloc memory info A");
+ key= psi->memory_realloc(memory_key_A, 100, 200, & owner);
+ ok(key == memory_key_A, "realloc memory info A");
+ key= psi->memory_realloc(memory_key_A, 200, 300, & owner);
+ ok(key == memory_key_A, "realloc up memory info A");
+ key= psi->memory_realloc(memory_key_A, 300, 50, & owner);
+ ok(key == memory_key_A, "realloc down memory info A");
+ psi->memory_free(memory_key_A, 50, owner);
+
+ /* Use global instrumentation only */
+ /* ------------------------------- */
+
+ flag_thread_instrumentation= false;
+
+ key= psi->memory_alloc(memory_key_A, 100, & owner);
+ ok(key == memory_key_A, "alloc memory info A");
+ key= psi->memory_realloc(memory_key_A, 100, 200, & owner);
+ ok(key == memory_key_A, "realloc memory info A");
+ key= psi->memory_realloc(memory_key_A, 200, 300, & owner);
+ ok(key == memory_key_A, "realloc up memory info A");
+ key= psi->memory_realloc(memory_key_A, 300, 50, & owner);
+ ok(key == memory_key_A, "realloc down memory info A");
+ psi->memory_free(memory_key_A, 50, owner);
+
+ /* Garbage, for robustness */
+ /* ----------------------- */
+
+ key= psi->memory_alloc(9999, 100, & owner);
+ ok(key == PSI_NOT_INSTRUMENTED, "alloc with unknown key");
+ key= psi->memory_realloc(PSI_NOT_INSTRUMENTED, 100, 200, & owner);
+ ok(key == PSI_NOT_INSTRUMENTED, "realloc with unknown key");
+ psi->memory_free(PSI_NOT_INSTRUMENTED, 200, owner);
+
+ shutdown_performance_schema();
+}
+
+void test_leaks()
+{
+ PSI_bootstrap *boot;
+ PFS_global_param param;
+
+ /* Allocate everything, to make sure cleanup does not forget anything. */
+
+ memset(& param, 0xFF, sizeof(param));
+ param.m_enabled= true;
+ param.m_mutex_class_sizing= 10;
+ param.m_rwlock_class_sizing= 10;
+ param.m_cond_class_sizing= 10;
+ param.m_thread_class_sizing= 10;
+ param.m_table_share_sizing= 10;
+ param.m_file_class_sizing= 10;
+ param.m_socket_class_sizing= 10;
+ param.m_mutex_sizing= 1000;
+ param.m_rwlock_sizing= 1000;
+ param.m_cond_sizing= 1000;
+ param.m_thread_sizing= 1000;
+ param.m_table_sizing= 1000;
+ param.m_file_sizing= 1000;
+ param.m_file_handle_sizing= 1000;
+ param.m_socket_sizing= 1000;
+ param.m_events_waits_history_sizing= 10;
+ param.m_events_waits_history_long_sizing= 1000;
+ param.m_setup_actor_sizing= 1000;
+ param.m_setup_object_sizing= 1000;
+ param.m_host_sizing= 1000;
+ param.m_user_sizing= 1000;
+ param.m_account_sizing= 1000;
+ param.m_stage_class_sizing= 10;
+ param.m_events_stages_history_sizing= 10;
+ param.m_events_stages_history_long_sizing= 1000;
+ param.m_statement_class_sizing= 10;
+ param.m_events_statements_history_sizing= 10;
+ param.m_events_statements_history_long_sizing= 1000;
+ param.m_session_connect_attrs_sizing= 1000;
+ param.m_memory_class_sizing= 10;
+ param.m_metadata_lock_sizing= 1000;
+ param.m_digest_sizing= 1000;
+ param.m_program_sizing= 1000;
+ param.m_statement_stack_sizing= 10;
+ param.m_max_digest_length= 1000;
+ param.m_max_sql_text_length= 1000;
+
+ param.m_hints.m_table_definition_cache = 100;
+ param.m_hints.m_table_open_cache = 100;
+ param.m_hints.m_max_connections = 100;
+ param.m_hints.m_open_files_limit = 100;
+ param.m_hints.m_max_prepared_stmt_count= 100;
+
+ pre_initialize_performance_schema();
+ boot= initialize_performance_schema(& param);
+ ok(boot != NULL, "bootstrap");
+ shutdown_performance_schema();
+
+ /* Leaks will be reported with valgrind */
}
void do_all_tests()
@@ -1668,11 +1895,13 @@ void do_all_tests()
test_locker_disabled();
test_file_instrumentation_leak();
test_event_name_index();
+ test_memory_instruments();
+ test_leaks();
}
int main(int argc, char **argv)
{
- plan(216);
+ plan(232);
MY_INIT(argv[0]);
do_all_tests();
my_end(0);
diff --git a/storage/perfschema/unittest/pfs_account-oom-t.cc b/storage/perfschema/unittest/pfs_account-oom-t.cc
index 1ca66445e0c..185b0a6594c 100644
--- a/storage/perfschema/unittest/pfs_account-oom-t.cc
+++ b/storage/perfschema/unittest/pfs_account-oom-t.cc
@@ -21,87 +21,142 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
#include <my_global.h>
-#include <my_pthread.h>
+#include <my_thread.h>
#include <pfs_instr.h>
#include <pfs_stat.h>
#include <pfs_global.h>
+#include <pfs_defaults.h>
+#include <pfs_user.h>
+#include <pfs_host.h>
#include <pfs_account.h>
+#include <pfs_buffer_container.h>
#include <tap.h>
#include "stub_pfs_global.h"
+#include "stub_global_status_var.h"
#include <string.h> /* memset */
-void test_oom()
-{
- int rc;
- PFS_global_param param;
-
- memset(& param, 0xFF, sizeof(param));
- param.m_enabled= true;
- param.m_mutex_class_sizing= 0;
- param.m_rwlock_class_sizing= 0;
- param.m_cond_class_sizing= 0;
- param.m_thread_class_sizing= 10;
- param.m_table_share_sizing= 0;
- param.m_file_class_sizing= 0;
- param.m_mutex_sizing= 0;
- param.m_rwlock_sizing= 0;
- param.m_cond_sizing= 0;
- param.m_thread_sizing= 1000;
- param.m_table_sizing= 0;
- param.m_file_sizing= 0;
- param.m_file_handle_sizing= 0;
- param.m_events_waits_history_sizing= 10;
- param.m_events_waits_history_long_sizing= 0;
- param.m_setup_actor_sizing= 0;
- param.m_setup_object_sizing= 0;
- param.m_host_sizing= 0;
- param.m_user_sizing= 0;
- param.m_account_sizing= 1000;
- param.m_stage_class_sizing= 50;
- param.m_events_stages_history_sizing= 0;
- param.m_events_stages_history_long_sizing= 0;
- 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 */
+PFS_thread pfs_thread;
+void initialize_performance_schema_helper(PFS_global_param *param)
+{
stub_alloc_always_fails= false;
stub_alloc_fails_after_count= 1000;
- init_event_name_sizing(& param);
- rc= init_stage_class(param.m_stage_class_sizing);
- ok(rc == 0, "init stage class");
- rc= init_statement_class(param.m_statement_class_sizing);
- ok(rc == 0, "init statement class");
+ param->m_enabled= true;
+ param->m_thread_class_sizing= 10;
+ param->m_thread_sizing= 1000;
+ param->m_account_sizing= 1000;
+ transaction_class_max= 0;
+
+ pfs_thread.m_account_hash_pins= NULL;
+
+ init_event_name_sizing(param);
+ init_sync_class(param->m_mutex_class_sizing, param->m_rwlock_class_sizing, param->m_cond_class_sizing);
+ init_thread_class(param->m_thread_class_sizing);
+ init_table_share(param->m_table_share_sizing);
+ init_table_share_lock_stat(param->m_table_lock_stat_sizing);
+ init_table_share_index_stat(param->m_index_stat_sizing);
+ init_file_class(param->m_file_class_sizing);
+ init_stage_class(param->m_stage_class_sizing);
+ init_statement_class(param->m_statement_class_sizing);
+ init_socket_class(param->m_socket_class_sizing);
+ init_memory_class(param->m_memory_class_sizing);
+ init_instruments(param);
+ init_events_waits_history_long(param->m_events_waits_history_long_sizing);
+ init_events_stages_history_long(param->m_events_stages_history_long_sizing);
+ init_events_statements_history_long(param->m_events_statements_history_long_sizing);
+ init_events_transactions_history_long(param->m_events_transactions_history_long_sizing);
+ init_file_hash(param);
+ init_table_share_hash(param);
+ init_setup_actor(param);
+ init_setup_actor_hash(param);
+ init_setup_object(param);
+ init_setup_object_hash(param);
+ init_host(param);
+ init_host_hash(param);
+ init_user(param);
+ init_user_hash(param);
+ init_account(param);
+ init_account_hash(param);
+ init_digest(param);
+ init_digest_hash(param);
+ init_program(param);
+ init_program_hash(param);
+ init_prepared_stmt(param);
+ pfs_initialized= true;
+}
+
+void test_oom()
+{
+ PFS_global_param param;
+ PFS_account *pfs_account;
+ const char *username= "username";
+ const char *hostname= "hostname";
- /* Tests */
+ uint user_len= (uint)strlen(username);
+ uint host_len= (uint)strlen(hostname);
+ /* Account. */
+ memset(&param, 0, sizeof(param));
+ initialize_performance_schema_helper(&param);
stub_alloc_fails_after_count= 1;
- rc= init_account(& param);
- ok(rc == 1, "oom (account)");
- cleanup_account();
-
+ pfs_account= find_or_create_account(&pfs_thread, username, user_len, hostname, host_len);
+ ok(pfs_account == NULL, "oom (account)");
+ ok(global_account_container.m_lost == 1, "lost (account)");
+ shutdown_performance_schema();
+
+ /* Account waits. */
+ memset(&param, 0, sizeof(param));
+ param.m_mutex_class_sizing= 10;
+ initialize_performance_schema_helper(&param);
stub_alloc_fails_after_count= 2;
- rc= init_account(& param);
- ok(rc == 1, "oom (account waits)");
- cleanup_account();
+ pfs_account= find_or_create_account(&pfs_thread, username, user_len, hostname, host_len);
+ ok(pfs_account == NULL, "oom (account waits)");
+ ok(global_account_container.m_lost == 1, "lost (account waits)");
+ shutdown_performance_schema();
- stub_alloc_fails_after_count= 3;
- rc= init_account(& param);
- ok(rc == 1, "oom (account stages)");
- cleanup_account();
- stub_alloc_fails_after_count= 4;
- rc= init_account(& param);
- ok(rc == 1, "oom (account statements)");
- cleanup_account();
-
- cleanup_statement_class();
- cleanup_stage_class();
+ /* Account stages. */
+ memset(&param, 0, sizeof(param));
+ param.m_stage_class_sizing= 10;
+ initialize_performance_schema_helper(&param);
+ stub_alloc_fails_after_count= 3;
+ pfs_account= find_or_create_account(&pfs_thread, username, user_len, hostname, host_len);
+ ok(pfs_account == NULL, "oom (account stages)");
+ ok(global_account_container.m_lost == 1, "lost (account stages)");
+ shutdown_performance_schema();
+
+ /* Account statements. */
+ memset(&param, 0, sizeof(param));
+ param.m_statement_class_sizing= 10;
+ initialize_performance_schema_helper(&param);
+ stub_alloc_fails_after_count= 3;
+ pfs_account= find_or_create_account(&pfs_thread, username, user_len, hostname, host_len);
+ ok(pfs_account == NULL, "oom (account statements)");
+ ok(global_account_container.m_lost == 1, "lost (account statements)");
+ shutdown_performance_schema();
+
+ /* Account transactions. */
+ memset(&param, 0, sizeof(param));
+ initialize_performance_schema_helper(&param);
+ transaction_class_max= 1;
+ stub_alloc_fails_after_count= 3;
+ pfs_account= find_or_create_account(&pfs_thread, username, user_len, hostname, host_len);
+ ok(pfs_account == NULL, "oom (account transactions)");
+ ok(global_account_container.m_lost == 1, "lost (account transactions)");
+ shutdown_performance_schema();
+
+ /* Account memory. */
+ memset(&param, 0, sizeof(param));
+ param.m_memory_class_sizing= 10;
+ initialize_performance_schema_helper(&param);
+ stub_alloc_fails_after_count= 3;
+ pfs_account= find_or_create_account(&pfs_thread, username, user_len, hostname, host_len);
+ ok(pfs_account == NULL, "oom (account memory)");
+ ok(global_account_container.m_lost == 1, "lost (account memory)");
+ shutdown_performance_schema();
}
void do_all_tests()
@@ -111,10 +166,9 @@ void do_all_tests()
int main(int, char **)
{
- plan(6);
+ plan(12);
MY_INIT("pfs_account-oom-t");
do_all_tests();
my_end(0);
return (exit_status());
}
-
diff --git a/storage/perfschema/unittest/pfs_connect_attr-t.cc b/storage/perfschema/unittest/pfs_connect_attr-t.cc
index 06b0f8ad014..b57ead3ec26 100644
--- a/storage/perfschema/unittest/pfs_connect_attr-t.cc
+++ b/storage/perfschema/unittest/pfs_connect_attr-t.cc
@@ -21,7 +21,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
#include <my_global.h>
-#include <my_pthread.h>
+#include <my_thread.h>
#include <pfs_server.h>
#include <pfs_instr_class.h>
#include <pfs_instr.h>
@@ -258,7 +258,7 @@ void test_utf8_parser_bad_encoding()
ptr= packet;
*ptr++= strlen(attr);
memcpy(ptr, attr, strlen(attr));
- ptr[0]= 0xFA; // invalid UTF-8 char
+ ptr[0]= (char)0xFA; // invalid UTF-8 char
ptr+= strlen(attr);
*ptr++= strlen(val);
memcpy(ptr, val, strlen(val));
diff --git a/storage/perfschema/unittest/pfs_host-oom-t.cc b/storage/perfschema/unittest/pfs_host-oom-t.cc
index 14af1af0352..e97a1170eb2 100644
--- a/storage/perfschema/unittest/pfs_host-oom-t.cc
+++ b/storage/perfschema/unittest/pfs_host-oom-t.cc
@@ -21,21 +21,26 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
#include <my_global.h>
-#include <my_pthread.h>
+#include <my_thread.h>
#include <pfs_instr.h>
#include <pfs_stat.h>
#include <pfs_global.h>
#include <pfs_host.h>
+#include <pfs_buffer_container.h>
#include <tap.h>
#include "stub_pfs_global.h"
+#include "stub_global_status_var.h"
#include <string.h> /* memset */
+extern struct PSI_bootstrap PFS_bootstrap;
+
void test_oom()
{
- int rc;
+ PSI *psi;
PFS_global_param param;
+ PSI_bootstrap *boot;
memset(& param, 0xFF, sizeof(param));
param.m_enabled= true;
@@ -45,6 +50,7 @@ void test_oom()
param.m_thread_class_sizing= 10;
param.m_table_share_sizing= 0;
param.m_file_class_sizing= 0;
+ param.m_socket_class_sizing= 0;
param.m_mutex_sizing= 0;
param.m_rwlock_sizing= 0;
param.m_cond_sizing= 0;
@@ -52,12 +58,13 @@ void test_oom()
param.m_table_sizing= 0;
param.m_file_sizing= 0;
param.m_file_handle_sizing= 0;
+ param.m_socket_sizing= 0;
param.m_events_waits_history_sizing= 10;
param.m_events_waits_history_long_sizing= 0;
param.m_setup_actor_sizing= 0;
param.m_setup_object_sizing= 0;
- param.m_host_sizing= 1000;
param.m_user_sizing= 0;
+ param.m_host_sizing= 1000;
param.m_account_sizing= 0;
param.m_stage_class_sizing= 50;
param.m_events_stages_history_sizing= 0;
@@ -65,43 +72,64 @@ 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_events_transactions_history_sizing= 0;
+ param.m_events_transactions_history_long_sizing= 0;
+ param.m_digest_sizing= 0;
param.m_session_connect_attrs_sizing= 0;
+ param.m_program_sizing= 0;
+ param.m_statement_stack_sizing= 0;
+ param.m_memory_class_sizing= 10;
+ param.m_metadata_lock_sizing= 0;
+ param.m_max_digest_length= 0;
+ param.m_max_sql_text_length= 0;
/* Setup */
stub_alloc_always_fails= false;
stub_alloc_fails_after_count= 1000;
- init_event_name_sizing(& param);
- rc= init_stage_class(param.m_stage_class_sizing);
- ok(rc == 0, "init stage class");
- rc= init_statement_class(param.m_statement_class_sizing);
- ok(rc == 0, "init statement class");
+ pre_initialize_performance_schema();
+ boot= initialize_performance_schema(&param);
+ psi= (PSI *)boot->get_interface(PSI_VERSION_1);
+
+ PSI_thread_key thread_key_1;
+ PSI_thread_info all_thread[]=
+ {
+ {&thread_key_1, "T-1", 0}
+ };
+ psi->register_thread("test", all_thread, 1);
+
+ PSI_thread *thread_1= psi->new_thread(thread_key_1, NULL, 0);
+ psi->set_thread(thread_1);
/* Tests */
- stub_alloc_fails_after_count= 1;
- rc= init_host(& param);
- ok(rc == 1, "oom (host)");
- cleanup_host();
+ int first_fail= 1;
+ stub_alloc_fails_after_count= first_fail;
+ psi->set_thread_account("", 0, "host1", 5);
+ ok(global_host_container.m_lost == 1, "oom (host)");
+
+ stub_alloc_fails_after_count= first_fail + 1;
+ psi->set_thread_account("", 0, "host2", 5);
+ ok(global_host_container.m_lost == 2, "oom (host waits)");
+
+ stub_alloc_fails_after_count= first_fail + 2;
+ psi->set_thread_account("", 0, "host3", 5);
+ ok(global_host_container.m_lost == 3, "oom (host stages)");
- stub_alloc_fails_after_count= 2;
- rc= init_host(& param);
- ok(rc == 1, "oom (host waits)");
- cleanup_host();
+ stub_alloc_fails_after_count= first_fail + 3;
+ psi->set_thread_account("", 0, "host4", 5);
+ ok(global_host_container.m_lost == 4, "oom (host statements)");
- stub_alloc_fails_after_count= 3;
- rc= init_host(& param);
- ok(rc == 1, "oom (host stages)");
- cleanup_host();
+ stub_alloc_fails_after_count= first_fail + 4;
+ psi->set_thread_account("", 0, "host5", 5);
+ ok(global_host_container.m_lost == 5, "oom (host transactions)");
- stub_alloc_fails_after_count= 4;
- rc= init_host(& param);
- ok(rc == 1, "oom (host statements)");
- cleanup_host();
+ stub_alloc_fails_after_count= first_fail + 5;
+ psi->set_thread_account("", 0, "host6", 5);
+ ok(global_host_container.m_lost == 6, "oom (host memory)");
- cleanup_statement_class();
- cleanup_stage_class();
+ shutdown_performance_schema();
}
void do_all_tests()
diff --git a/storage/perfschema/unittest/pfs_instr-oom-t.cc b/storage/perfschema/unittest/pfs_instr-oom-t.cc
index 231fd1e100b..9472d8aa001 100644
--- a/storage/perfschema/unittest/pfs_instr-oom-t.cc
+++ b/storage/perfschema/unittest/pfs_instr-oom-t.cc
@@ -18,46 +18,139 @@
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, Fifth Floor, Boston, MA 02110-1335 USA */
+ 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
#include <my_global.h>
-#include <my_pthread.h>
+#include <my_thread.h>
#include <pfs_instr.h>
#include <pfs_stat.h>
#include <pfs_global.h>
+#include <pfs_user.h>
+#include <pfs_host.h>
+#include <pfs_account.h>
#include <pfs_instr_class.h>
+#include <pfs_buffer_container.h>
#include <tap.h>
#include "stub_pfs_global.h"
+#include "stub_global_status_var.h"
#include <string.h> /* memset */
+extern struct PSI_bootstrap PFS_bootstrap;
+
+PSI_thread_key thread_key_1;
+PSI_thread_info all_thread[]=
+{
+ {&thread_key_1, "T-1", 0}
+};
+
+/** Simulate initialize_performance_schema(). */
+
+PSI * initialize_performance_schema_helper(PFS_global_param *param)
+{
+ PSI *psi;
+
+ stub_alloc_always_fails= false;
+ stub_alloc_fails_after_count= 1000;
+
+ param->m_enabled= true;
+ param->m_thread_class_sizing= 10;
+ param->m_thread_sizing= 1000;
+
+ pre_initialize_performance_schema();
+
+ init_event_name_sizing(param);
+ init_sync_class(param->m_mutex_class_sizing, param->m_rwlock_class_sizing, param->m_cond_class_sizing);
+ init_thread_class(param->m_thread_class_sizing);
+ init_table_share(param->m_table_share_sizing);
+ init_table_share_lock_stat(param->m_table_lock_stat_sizing);
+ init_table_share_index_stat(param->m_index_stat_sizing);
+ init_file_class(param->m_file_class_sizing);
+ init_stage_class(param->m_stage_class_sizing);
+ init_statement_class(param->m_statement_class_sizing);
+ init_socket_class(param->m_socket_class_sizing);
+ init_memory_class(param->m_memory_class_sizing);
+ init_instruments(param);
+ init_events_waits_history_long(param->m_events_waits_history_long_sizing);
+ init_events_stages_history_long(param->m_events_stages_history_long_sizing);
+ init_events_statements_history_long(param->m_events_statements_history_long_sizing);
+ init_events_transactions_history_long(param->m_events_transactions_history_long_sizing);
+ init_file_hash(param);
+ init_table_share_hash(param);
+ init_setup_actor(param);
+ init_setup_actor_hash(param);
+ init_setup_object(param);
+ init_setup_object_hash(param);
+ init_host(param);
+ init_host_hash(param);
+ init_user(param);
+ init_user_hash(param);
+ init_account(param);
+ init_account_hash(param);
+ init_digest(param);
+ init_digest_hash(param);
+ init_program(param);
+ init_program_hash(param);
+ init_prepared_stmt(param);
+ pfs_initialized= true;
+
+ PSI_bootstrap *boot= &PFS_bootstrap;
+ psi= (PSI *)boot->get_interface(PSI_VERSION_1);
+ psi->register_thread("test", all_thread, 1);
+ return (psi);
+}
+
void test_oom()
{
int rc;
+ PSI *psi;
PFS_global_param param;
- stub_alloc_always_fails= true;
+ stub_alloc_always_fails= false;
+ stub_alloc_fails_after_count= 1000;
+
+ PFS_mutex_class dummy_mutex_class;
+ PFS_rwlock_class dummy_rwlock_class;
+ PFS_cond_class dummy_cond_class;
+ PFS_thread_class dummy_thread_class;
+ PFS_file_class dummy_file_class;
+ PFS_socket_class dummy_socket_class;
+ PFS_table_share dummy_table_share;
+ PFS_mutex *mutex_1;
+ PFS_mutex *mutex_2;
+ PFS_rwlock *rwlock_1;
+ PFS_rwlock *rwlock_2;
+ PFS_cond *cond_1;
+ PFS_cond *cond_2;
+ PFS_thread *thread_1;
+ PFS_thread *thread_2;
+ PFS_file *file_1;
+ PFS_file *file_2;
+ PFS_socket *socket_1;
+ PFS_socket *socket_2;
+ PFS_table *table_1;
+ PFS_table *table_2;
memset(& param, 0xFF, sizeof(param));
param.m_enabled= true;
- param.m_mutex_class_sizing= 10;
- param.m_rwlock_class_sizing= 0;
- param.m_cond_class_sizing= 0;
- param.m_thread_class_sizing= 0;
- param.m_table_share_sizing= 0;
- param.m_file_class_sizing= 0;
- param.m_socket_class_sizing= 0;
- param.m_mutex_sizing= 1000;
- param.m_rwlock_sizing= 0;
- param.m_cond_sizing= 0;
- param.m_thread_sizing= 0;
- param.m_table_sizing= 0;
- param.m_file_sizing= 0;
- param.m_file_handle_sizing= 0;
- param.m_socket_sizing= 0;
- param.m_events_waits_history_sizing= 0;
- param.m_events_waits_history_long_sizing= 0;
+ param.m_mutex_class_sizing= 1;
+ param.m_rwlock_class_sizing= 1;
+ param.m_cond_class_sizing= 1;
+ param.m_thread_class_sizing= 1;
+ param.m_table_share_sizing= 1;
+ param.m_file_class_sizing= 1;
+ param.m_socket_class_sizing= 1;
+ param.m_mutex_sizing= 1;
+ param.m_rwlock_sizing= 1;
+ param.m_cond_sizing= 1;
+ param.m_thread_sizing= 1;
+ param.m_table_sizing= 1;
+ param.m_file_sizing= 1;
+ param.m_file_handle_sizing= 100;
+ param.m_socket_sizing= 2;
+ param.m_events_waits_history_sizing= 10;
+ param.m_events_waits_history_long_sizing= 10000;
param.m_setup_actor_sizing= 0;
param.m_setup_object_sizing= 0;
param.m_host_sizing= 0;
@@ -69,614 +162,285 @@ 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_events_transactions_history_sizing= 0;
+ param.m_events_transactions_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);
- ok(rc == 1, "oom (mutex)");
+ param.m_program_sizing= 0;
+ param.m_prepared_stmt_sizing= 0;
+ param.m_statement_stack_sizing= 0;
+ param.m_memory_class_sizing= 1;
+ param.m_metadata_lock_sizing= 0;
+ param.m_max_digest_length= 0;
+ param.m_max_sql_text_length= 0;
+
+ init_event_name_sizing(&param);
+ rc= init_instruments(&param);
+ ok(rc == 0, "instances init");
+
+ dummy_mutex_class.m_event_name_index= 0;
+ dummy_mutex_class.m_flags= 0;
+ dummy_mutex_class.m_enabled= true;
+ dummy_mutex_class.m_volatility= PSI_VOLATILITY_UNKNOWN;
+ dummy_rwlock_class.m_event_name_index= 1;
+ dummy_rwlock_class.m_flags= 0;
+ dummy_rwlock_class.m_enabled= true;
+ dummy_rwlock_class.m_volatility= PSI_VOLATILITY_UNKNOWN;
+ dummy_cond_class.m_event_name_index= 2;
+ dummy_cond_class.m_flags= 0;
+ dummy_cond_class.m_enabled= true;
+ dummy_cond_class.m_volatility = PSI_VOLATILITY_UNKNOWN;
+ dummy_file_class.m_event_name_index= 3;
+ dummy_file_class.m_flags= 0;
+ dummy_file_class.m_enabled= true;
+ dummy_file_class.m_volatility = PSI_VOLATILITY_UNKNOWN;
+ dummy_socket_class.m_event_name_index= 4;
+ dummy_socket_class.m_flags= 0;
+ dummy_socket_class.m_enabled= true;
+ dummy_socket_class.m_volatility = PSI_VOLATILITY_UNKNOWN;
+ dummy_table_share.m_enabled= true;
+ dummy_table_share.m_timed= true;
+
+ /* Create mutex. */
+ stub_alloc_always_fails= false;
+ mutex_1= create_mutex(&dummy_mutex_class, NULL);
+ ok(mutex_1 != NULL, "create mutex");
+ destroy_mutex(mutex_1);
cleanup_instruments();
- param.m_enabled= true;
- param.m_mutex_class_sizing= 0;
- param.m_rwlock_class_sizing= 10;
- param.m_cond_class_sizing= 0;
- param.m_thread_class_sizing= 0;
- param.m_table_share_sizing= 0;
- param.m_file_class_sizing= 0;
- param.m_socket_class_sizing= 0;
- param.m_mutex_sizing= 0;
- param.m_rwlock_sizing= 1000;
- param.m_cond_sizing= 0;
- param.m_thread_sizing= 0;
- param.m_table_sizing= 0;
- param.m_file_sizing= 0;
- param.m_file_handle_sizing= 0;
- param.m_socket_sizing= 0;
- param.m_events_waits_history_sizing= 0;
- param.m_events_waits_history_long_sizing= 0;
- param.m_setup_actor_sizing= 0;
- param.m_setup_object_sizing= 0;
- param.m_host_sizing= 0;
- param.m_user_sizing= 0;
- param.m_account_sizing= 0;
- param.m_stage_class_sizing= 0;
- param.m_events_stages_history_sizing= 0;
- param.m_events_stages_history_long_sizing= 0;
- 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);
- ok(rc == 1, "oom (rwlock)");
+ stub_alloc_always_fails= true;
+ mutex_2= create_mutex(&dummy_mutex_class, NULL);
+ ok(mutex_2 == NULL, "oom (create mutex)");
+
+ /* Create rwlock. */
+ stub_alloc_always_fails = false;
+ rc = init_instruments(&param);
+ ok(rc == 0, "instances init");
+ rwlock_1= create_rwlock(&dummy_rwlock_class, NULL);
+ ok(rwlock_1 != NULL, "create rwlock");
+ destroy_rwlock(rwlock_1);
cleanup_instruments();
- param.m_enabled= true;
- param.m_mutex_class_sizing= 0;
- param.m_rwlock_class_sizing= 0;
- param.m_cond_class_sizing= 10;
- param.m_thread_class_sizing= 0;
- param.m_table_share_sizing= 0;
- param.m_file_class_sizing= 0;
- param.m_socket_class_sizing= 0;
- param.m_mutex_sizing= 0;
- param.m_rwlock_sizing= 0;
- param.m_cond_sizing= 1000;
- param.m_thread_sizing= 0;
- param.m_table_sizing= 0;
- param.m_file_sizing= 0;
- param.m_file_handle_sizing= 0;
- param.m_socket_sizing= 0;
- param.m_events_waits_history_sizing= 0;
- param.m_events_waits_history_long_sizing= 0;
- param.m_setup_actor_sizing= 0;
- param.m_setup_object_sizing= 0;
- param.m_host_sizing= 0;
- param.m_user_sizing= 0;
- param.m_account_sizing= 0;
- param.m_stage_class_sizing= 0;
- param.m_events_stages_history_sizing= 0;
- param.m_events_stages_history_long_sizing= 0;
- 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);
- ok(rc == 1, "oom (cond)");
+ stub_alloc_always_fails= true;
+ rwlock_2= create_rwlock(&dummy_rwlock_class, NULL);
+ ok(rwlock_2 == NULL, "oom (create rwlock)");
+
+ /* Create cond. */
+ stub_alloc_always_fails = false;
+ rc = init_instruments(&param);
+ ok(rc == 0, "instances init");
+ cond_1= create_cond(&dummy_cond_class, NULL);
+ ok(cond_1 != NULL, "create cond");
+ destroy_cond(cond_1);
cleanup_instruments();
- param.m_enabled= true;
- param.m_mutex_class_sizing= 0;
- param.m_rwlock_class_sizing= 0;
- param.m_cond_class_sizing= 0;
- param.m_thread_class_sizing= 0;
- param.m_table_share_sizing= 0;
- param.m_file_class_sizing= 10;
- param.m_socket_class_sizing= 0;
- param.m_mutex_sizing= 0;
- param.m_rwlock_sizing= 0;
- param.m_cond_sizing= 0;
- param.m_thread_sizing= 0;
- param.m_table_sizing= 0;
- param.m_file_sizing= 1000;
- param.m_file_handle_sizing= 1000;
- param.m_socket_sizing= 0;
- param.m_events_waits_history_sizing= 0;
- param.m_events_waits_history_long_sizing= 0;
- param.m_setup_actor_sizing= 0;
- param.m_setup_object_sizing= 0;
- param.m_host_sizing= 0;
- param.m_user_sizing= 0;
- param.m_account_sizing= 0;
- param.m_stage_class_sizing= 0;
- param.m_events_stages_history_sizing= 0;
- param.m_events_stages_history_long_sizing= 0;
- 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_always_fails= true;
+ cond_2= create_cond(&dummy_cond_class, NULL);
+ ok(cond_2 == NULL, "oom (create cond)");
- init_event_name_sizing(& param);
- rc= init_instruments(& param);
- ok(rc == 1, "oom (file)");
- cleanup_instruments();
+ /* Create file. */
+ PFS_thread fake_thread;
+ rc = init_instruments(&param);
+ fake_thread.m_filename_hash_pins= NULL;
+ init_file_hash(&param);
- param.m_enabled= true;
- param.m_mutex_class_sizing= 0;
- param.m_rwlock_class_sizing= 0;
- param.m_cond_class_sizing= 0;
- param.m_thread_class_sizing= 0;
- param.m_table_share_sizing= 0;
- param.m_file_class_sizing= 0;
- param.m_mutex_sizing= 0;
- param.m_rwlock_sizing= 0;
- param.m_cond_sizing= 0;
- param.m_thread_sizing= 0;
- param.m_table_sizing= 0;
- param.m_file_sizing= 0;
- param.m_file_handle_sizing= 1000;
- param.m_events_waits_history_sizing= 0;
- param.m_events_waits_history_long_sizing= 0;
- param.m_setup_actor_sizing= 0;
- param.m_setup_object_sizing= 0;
- param.m_host_sizing= 0;
- param.m_user_sizing= 0;
- param.m_account_sizing= 0;
- param.m_stage_class_sizing= 0;
- param.m_events_stages_history_sizing= 0;
- param.m_events_stages_history_long_sizing= 0;
- 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_always_fails = true;
+ file_2 = find_or_create_file(&fake_thread, &dummy_file_class, "dummy", 5, true);
+ ok(file_2 == NULL, "oom (create file)");
- init_event_name_sizing(& param);
- rc= init_instruments(& param);
- ok(rc == 1, "oom (file handle)");
+ stub_alloc_always_fails= false;
+ file_1= find_or_create_file(&fake_thread, &dummy_file_class, "dummy", 5, true);
+ ok(file_1 != NULL, "create file");
+ release_file(file_1);
cleanup_instruments();
- param.m_enabled= true;
- param.m_mutex_class_sizing= 0;
- param.m_rwlock_class_sizing= 0;
- param.m_cond_class_sizing= 0;
- param.m_thread_class_sizing= 0;
- param.m_table_share_sizing= 10;
- param.m_file_class_sizing= 0;
- param.m_socket_class_sizing= 0;
- param.m_mutex_sizing= 0;
- param.m_rwlock_sizing= 0;
- param.m_cond_sizing= 0;
- param.m_thread_sizing= 0;
- param.m_table_sizing= 1000;
- param.m_file_sizing= 0;
- param.m_file_handle_sizing= 0;
- param.m_socket_sizing= 0;
- param.m_events_waits_history_sizing= 0;
- param.m_events_waits_history_long_sizing= 0;
- param.m_setup_actor_sizing= 0;
- param.m_setup_object_sizing= 0;
- param.m_host_sizing= 0;
- param.m_user_sizing= 0;
- param.m_account_sizing= 0;
- param.m_stage_class_sizing= 0;
- param.m_events_stages_history_sizing= 0;
- param.m_events_stages_history_long_sizing= 0;
- 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);
- ok(rc == 1, "oom (table)");
+ /* Create socket. */
+ stub_alloc_always_fails = false;
+ rc = init_instruments(&param);
+ ok(rc == 0, "instances init");
+ socket_1= create_socket(&dummy_socket_class, NULL, NULL, 0);
+ ok(socket_1 != NULL, "create socket");
+ destroy_socket(socket_1);
cleanup_instruments();
- param.m_enabled= true;
- param.m_mutex_class_sizing= 0;
- param.m_rwlock_class_sizing= 0;
- param.m_cond_class_sizing= 0;
- param.m_thread_class_sizing= 10;
- param.m_table_share_sizing= 0;
- param.m_file_class_sizing= 0;
- param.m_socket_class_sizing= 0;
- param.m_mutex_sizing= 0;
- param.m_rwlock_sizing= 0;
- param.m_cond_sizing= 0;
- param.m_thread_sizing= 1000;
- param.m_table_sizing= 0;
- param.m_file_sizing= 0;
- param.m_file_handle_sizing= 0;
- param.m_socket_sizing= 0;
- param.m_events_waits_history_sizing= 0;
- param.m_events_waits_history_long_sizing= 0;
- param.m_setup_actor_sizing= 0;
- param.m_setup_object_sizing= 0;
- param.m_host_sizing= 0;
- param.m_user_sizing= 0;
- param.m_account_sizing= 0;
- param.m_stage_class_sizing= 0;
- param.m_events_stages_history_sizing= 0;
- param.m_events_stages_history_long_sizing= 0;
- 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_always_fails= true;
+ socket_2= create_socket(&dummy_socket_class, NULL, NULL, 0);
+ ok(socket_2 == NULL, "oom (create socket)");
- init_event_name_sizing(& param);
- rc= init_instruments(& param);
- ok(rc == 1, "oom (thread)");
+ /* Create table. */
+ stub_alloc_always_fails= false;
+ rc = init_instruments(&param);
+ table_1= create_table(&dummy_table_share, &fake_thread, NULL);
+ ok(table_1 != NULL, "create table");
+ destroy_table(table_1);
cleanup_instruments();
+ stub_alloc_always_fails= true;
+ table_2= create_table(&dummy_table_share, &fake_thread, NULL);
+ ok(table_2 == NULL, "oom (create table)");
+
+ /* Create thread. */
stub_alloc_always_fails= false;
+ rc = init_instruments(&param);
+ thread_1= create_thread(&dummy_thread_class, NULL, 0);
+ ok(thread_1 != NULL, "create thread");
+ destroy_thread(thread_1);
+ cleanup_instruments();
- param.m_enabled= true;
- param.m_mutex_class_sizing= 0;
- param.m_rwlock_class_sizing= 0;
- param.m_cond_class_sizing= 0;
- param.m_thread_class_sizing= 10;
- param.m_table_share_sizing= 0;
- param.m_file_class_sizing= 0;
- param.m_socket_class_sizing= 0;
- param.m_mutex_sizing= 0;
- param.m_rwlock_sizing= 0;
- param.m_cond_sizing= 0;
- param.m_thread_sizing= 1000;
- param.m_table_sizing= 0;
- param.m_file_sizing= 0;
- param.m_file_handle_sizing= 0;
- param.m_socket_sizing= 0;
- param.m_events_waits_history_sizing= 10;
- param.m_events_waits_history_long_sizing= 0;
- param.m_setup_actor_sizing= 0;
- param.m_setup_object_sizing= 0;
- param.m_host_sizing= 0;
- param.m_user_sizing= 0;
- param.m_account_sizing= 0;
- param.m_stage_class_sizing= 0;
- param.m_events_stages_history_sizing= 0;
- param.m_events_stages_history_long_sizing= 0;
- 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_always_fails= true;
+ thread_2= create_thread(&dummy_thread_class, NULL, 0);
+ ok(thread_2 == NULL, "oom (create thread)");
- stub_alloc_fails_after_count= 2;
- init_event_name_sizing(& param);
- rc= init_instruments(& param);
- ok(rc == 1, "oom (thread waits history sizing)");
- cleanup_instruments();
+ PSI_thread *thread;
- param.m_enabled= true;
+ /* Per thread wait. */
+ memset(&param, 0, sizeof(param));
param.m_mutex_class_sizing= 50;
param.m_rwlock_class_sizing= 50;
param.m_cond_class_sizing= 50;
- param.m_thread_class_sizing= 10;
- param.m_table_share_sizing= 0;
param.m_file_class_sizing= 50;
param.m_socket_class_sizing= 0;
- param.m_mutex_sizing= 0;
- param.m_rwlock_sizing= 0;
- param.m_cond_sizing= 0;
- param.m_thread_sizing= 1000;
- param.m_table_sizing= 0;
- param.m_file_sizing= 0;
- param.m_file_handle_sizing= 0;
- param.m_socket_sizing= 0;
- param.m_events_waits_history_sizing= 0;
- param.m_events_waits_history_long_sizing= 0;
- param.m_setup_actor_sizing= 0;
- param.m_setup_object_sizing= 0;
- param.m_stage_class_sizing= 0;
- param.m_events_stages_history_sizing= 0;
- param.m_events_stages_history_long_sizing= 0;
- 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;
-
+ psi= initialize_performance_schema_helper(&param);
stub_alloc_fails_after_count= 2;
- init_event_name_sizing(& param);
- rc= init_instruments(& param);
- ok(rc == 1, "oom (per thread wait)");
+ thread= psi->new_thread(thread_key_1, NULL, 0);
+ ok(thread == NULL, "oom (per thread wait)");
cleanup_sync_class();
cleanup_thread_class();
cleanup_file_class();
cleanup_instruments();
+ /* Thread waits history sizing. */
+ memset(&param, 0, sizeof(param));
param.m_enabled= true;
- param.m_mutex_class_sizing= 0;
- param.m_rwlock_class_sizing= 0;
- param.m_cond_class_sizing= 0;
- param.m_thread_class_sizing= 0;
- param.m_table_share_sizing= 0;
- param.m_file_class_sizing= 0;
- param.m_socket_class_sizing= 10;
- param.m_mutex_sizing= 0;
- param.m_rwlock_sizing= 0;
- param.m_cond_sizing= 0;
- param.m_thread_sizing= 0;
- param.m_table_sizing= 0;
- param.m_file_sizing= 0;
- param.m_file_handle_sizing= 0;
- param.m_socket_sizing= 1000;
- param.m_events_waits_history_sizing= 0;
- param.m_events_waits_history_long_sizing= 0;
- param.m_setup_actor_sizing= 0;
- param.m_setup_object_sizing= 0;
-
- init_event_name_sizing(& param);
- rc= init_instruments(& param);
- ok(rc == 1, "oom (socket)");
+ param.m_events_waits_history_sizing= 10;
+ psi= initialize_performance_schema_helper(&param);
+ stub_alloc_fails_after_count= 3;
+ thread= psi->new_thread(thread_key_1, NULL, 0);
+ ok(thread == NULL, "oom (thread waits history sizing)");
+ cleanup_thread_class();
cleanup_instruments();
- param.m_host_sizing= 0;
- param.m_user_sizing= 0;
- param.m_account_sizing= 0;
- param.m_stage_class_sizing= 0;
- param.m_events_stages_history_sizing= 0;
- param.m_events_stages_history_long_sizing= 0;
- 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;
+ /* Per thread stages. */
+ memset(&param, 0, sizeof(param));
+ param.m_stage_class_sizing= 50;
+ psi= initialize_performance_schema_helper(&param);
+ stub_alloc_fails_after_count= 3;
+ thread= psi->new_thread(thread_key_1, NULL, 0);
+ ok(thread == NULL, "oom (per thread stages)");
- stub_alloc_fails_after_count= 1;
- init_event_name_sizing(& param);
- rc= init_instruments(& param);
- ok(rc == 1, "oom (per thread waits)");
+ cleanup_stage_class();
+ cleanup_thread_class();
cleanup_instruments();
+ cleanup_stage_class();
- param.m_enabled= true;
- param.m_mutex_class_sizing= 0;
- param.m_rwlock_class_sizing= 0;
- param.m_cond_class_sizing= 0;
- param.m_thread_class_sizing= 10;
- param.m_table_share_sizing= 0;
- param.m_file_class_sizing= 0;
- param.m_mutex_sizing= 0;
- param.m_rwlock_sizing= 0;
- param.m_cond_sizing= 0;
- param.m_thread_sizing= 1000;
- param.m_table_sizing= 0;
- param.m_file_sizing= 0;
- param.m_file_handle_sizing= 0;
- param.m_events_waits_history_sizing= 0;
- param.m_events_waits_history_long_sizing= 0;
- param.m_setup_actor_sizing= 0;
- param.m_setup_object_sizing= 0;
- param.m_host_sizing= 0;
- param.m_user_sizing= 0;
- param.m_account_sizing= 0;
- param.m_stage_class_sizing= 0;
+ /* Thread stages history sizing. */
+ memset(&param, 0, sizeof(param));
param.m_events_stages_history_sizing= 10;
- param.m_events_stages_history_long_sizing= 0;
- 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;
-
+ psi= initialize_performance_schema_helper(&param);
stub_alloc_fails_after_count= 3;
- init_event_name_sizing(& param);
- rc= init_instruments(& param);
- ok(rc == 1, "oom (thread stages history sizing)");
-
- cleanup_thread_class();
+ thread= psi->new_thread(thread_key_1, NULL, 0);
+ ok(thread == NULL, "oom (thread stages history sizing)");
+
cleanup_instruments();
+ cleanup_thread_class();
- param.m_enabled= true;
- param.m_mutex_class_sizing= 0;
- param.m_rwlock_class_sizing= 0;
- param.m_cond_class_sizing= 0;
- param.m_thread_class_sizing= 10;
- param.m_table_share_sizing= 0;
- param.m_file_class_sizing= 0;
- param.m_mutex_sizing= 0;
- param.m_rwlock_sizing= 0;
- param.m_cond_sizing= 0;
- param.m_thread_sizing= 1000;
- param.m_table_sizing= 0;
- param.m_file_sizing= 0;
- param.m_file_handle_sizing= 0;
- param.m_events_waits_history_sizing= 0;
- param.m_events_waits_history_long_sizing= 0;
- param.m_setup_actor_sizing= 0;
- param.m_setup_object_sizing= 0;
- param.m_host_sizing= 0;
- param.m_user_sizing= 0;
- param.m_account_sizing= 0;
+ /* Per thread statements. */
+ memset(&param, 0, sizeof(param));
param.m_stage_class_sizing= 50;
- param.m_events_stages_history_sizing= 0;
- param.m_events_stages_history_long_sizing= 0;
- 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;
+ psi= initialize_performance_schema_helper(&param);
+ init_statement_class(param.m_statement_class_sizing);
+ stub_alloc_fails_after_count= 3;
+ thread= psi->new_thread(thread_key_1, NULL, 0);
+ ok(thread == NULL, "oom (per thread statements)");
- stub_alloc_fails_after_count= 2;
- init_event_name_sizing(& param);
- rc= init_instruments(& param);
- ok(rc == 1, "oom (per thread stages)");
-
cleanup_stage_class();
+ cleanup_statement_class();
cleanup_thread_class();
cleanup_instruments();
- param.m_enabled= true;
- param.m_mutex_class_sizing= 0;
- param.m_rwlock_class_sizing= 0;
- param.m_cond_class_sizing= 0;
- param.m_thread_class_sizing= 10;
- param.m_table_share_sizing= 0;
- param.m_file_class_sizing= 0;
- param.m_mutex_sizing= 0;
- param.m_rwlock_sizing= 0;
- param.m_cond_sizing= 0;
- param.m_thread_sizing= 1000;
- param.m_table_sizing= 0;
- param.m_file_sizing= 0;
- param.m_file_handle_sizing= 0;
- param.m_events_waits_history_sizing= 0;
- param.m_events_waits_history_long_sizing= 0;
- param.m_setup_actor_sizing= 0;
- param.m_setup_object_sizing= 0;
- param.m_host_sizing= 0;
- param.m_user_sizing= 0;
- param.m_account_sizing= 0;
- param.m_stage_class_sizing= 0;
- param.m_events_stages_history_sizing= 0;
- param.m_events_stages_history_long_sizing= 0;
- param.m_statement_class_sizing= 0;
+ /* Thread statements history sizing. */
+ memset(&param, 0, sizeof(param));
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);
- rc= init_instruments(& param);
- ok(rc == 1, "oom (thread statements history sizing)");
-
+ psi= initialize_performance_schema_helper(&param);
+ stub_alloc_fails_after_count= 3;
+ thread= psi->new_thread(thread_key_1, NULL, 0);
+ ok(thread == NULL, "oom (thread statements history sizing)");
+
cleanup_thread_class();
cleanup_instruments();
- param.m_enabled= true;
- param.m_mutex_class_sizing= 0;
- param.m_rwlock_class_sizing= 0;
- param.m_cond_class_sizing= 0;
- param.m_thread_class_sizing= 10;
- param.m_table_share_sizing= 0;
- param.m_file_class_sizing= 0;
- param.m_mutex_sizing= 0;
- param.m_rwlock_sizing= 0;
- param.m_cond_sizing= 0;
- param.m_thread_sizing= 1000;
- param.m_table_sizing= 0;
- param.m_file_sizing= 0;
- param.m_file_handle_sizing= 0;
- param.m_events_waits_history_sizing= 0;
- param.m_events_waits_history_long_sizing= 0;
- param.m_setup_actor_sizing= 0;
- param.m_setup_object_sizing= 0;
- param.m_host_sizing= 0;
- param.m_user_sizing= 0;
- param.m_account_sizing= 0;
- param.m_stage_class_sizing= 0;
- param.m_events_stages_history_sizing= 0;
- param.m_events_stages_history_long_sizing= 0;
- 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);
- rc= init_instruments(& param);
- ok(rc == 1, "oom (per thread statements)");
+ /* Per thread transactions. */
+ memset(&param, 0, sizeof(param));
+ psi= initialize_performance_schema_helper(&param);
+ transaction_class_max= 1; // set by register_global_classes();
+ stub_alloc_fails_after_count= 3;
+ thread= psi->new_thread(thread_key_1, NULL, 0);
+ ok(thread == NULL, "oom (per thread transactions)");
+ transaction_class_max= 0;
- cleanup_statement_class();
cleanup_thread_class();
cleanup_instruments();
- param.m_enabled= true;
- param.m_mutex_class_sizing= 10;
- param.m_rwlock_class_sizing= 0;
- param.m_cond_class_sizing= 0;
- param.m_thread_class_sizing= 0;
- param.m_table_share_sizing= 0;
- param.m_file_class_sizing= 0;
- param.m_mutex_sizing= 0;
- param.m_rwlock_sizing= 0;
- param.m_cond_sizing= 0;
- param.m_thread_sizing= 0;
- param.m_table_sizing= 0;
- param.m_file_sizing= 0;
- param.m_file_handle_sizing= 0;
- param.m_events_waits_history_sizing= 0;
- param.m_events_waits_history_long_sizing= 0;
- param.m_setup_actor_sizing= 0;
- param.m_setup_object_sizing= 0;
- param.m_host_sizing= 0;
- param.m_user_sizing= 0;
- param.m_account_sizing= 0;
- param.m_stage_class_sizing= 0;
- param.m_events_stages_history_sizing= 0;
- param.m_events_stages_history_long_sizing= 0;
- 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);
- rc= init_instruments(& param);
- ok(rc == 1, "oom (global waits)");
+ /* Thread transactions history sizing. */
+ memset(&param, 0, sizeof(param));
+ param.m_events_transactions_history_sizing= 10;
+ psi= initialize_performance_schema_helper(&param);
+ stub_alloc_fails_after_count= 3;
+ thread= psi->new_thread(thread_key_1, NULL, 0);
+ ok(thread == NULL, "oom (thread transactions history sizing)");
- cleanup_sync_class();
+ cleanup_thread_class();
cleanup_instruments();
+ /* Global stages. */
+ memset(&param, 0, sizeof(param));
param.m_enabled= true;
param.m_mutex_class_sizing= 10;
- param.m_rwlock_class_sizing= 0;
- param.m_cond_class_sizing= 0;
- param.m_thread_class_sizing= 0;
- param.m_table_share_sizing= 0;
- param.m_file_class_sizing= 0;
- param.m_mutex_sizing= 0;
- param.m_rwlock_sizing= 0;
- param.m_cond_sizing= 0;
- param.m_thread_sizing= 0;
- param.m_table_sizing= 0;
- param.m_file_sizing= 0;
- param.m_file_handle_sizing= 0;
- param.m_events_waits_history_sizing= 0;
- param.m_events_waits_history_long_sizing= 0;
- param.m_setup_actor_sizing= 0;
- param.m_setup_object_sizing= 0;
- param.m_host_sizing= 0;
- param.m_user_sizing= 0;
- param.m_account_sizing= 0;
param.m_stage_class_sizing= 20;
- param.m_events_stages_history_sizing= 0;
- param.m_events_stages_history_long_sizing= 0;
- 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);
+ stub_alloc_fails_after_count= 2;
+ init_event_name_sizing(&param);
rc= init_stage_class(param.m_stage_class_sizing);
ok(rc == 0, "init stage class");
rc= init_instruments(& param);
ok(rc == 1, "oom (global stages)");
- cleanup_sync_class();
cleanup_stage_class();
cleanup_instruments();
+ /* Global statements. */
+ memset(&param, 0, sizeof(param));
param.m_enabled= true;
param.m_mutex_class_sizing= 10;
- param.m_rwlock_class_sizing= 0;
- param.m_cond_class_sizing= 0;
- param.m_thread_class_sizing= 0;
- param.m_table_share_sizing= 0;
- param.m_file_class_sizing= 0;
- param.m_mutex_sizing= 0;
- param.m_rwlock_sizing= 0;
- param.m_cond_sizing= 0;
- param.m_thread_sizing= 0;
- param.m_table_sizing= 0;
- param.m_file_sizing= 0;
- param.m_file_handle_sizing= 0;
- param.m_events_waits_history_sizing= 0;
- param.m_events_waits_history_long_sizing= 0;
- param.m_setup_actor_sizing= 0;
- param.m_setup_object_sizing= 0;
- param.m_host_sizing= 0;
- param.m_user_sizing= 0;
- param.m_account_sizing= 0;
- param.m_stage_class_sizing= 0;
- param.m_events_stages_history_sizing= 0;
- param.m_events_stages_history_long_sizing= 0;
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);
+ stub_alloc_fails_after_count= 2;
+ init_event_name_sizing(&param);
rc= init_statement_class(param.m_statement_class_sizing);
ok(rc == 0, "init statement class");
- rc= init_instruments(& param);
+ rc= init_instruments(&param);
ok(rc == 1, "oom (global statements)");
- cleanup_sync_class();
cleanup_statement_class();
cleanup_instruments();
+
+ /* Global memory. */
+ memset(&param, 0, sizeof(param));
+ param.m_enabled= true;
+ param.m_mutex_class_sizing= 10;
+ param.m_memory_class_sizing= 20;
+
+ stub_alloc_fails_after_count= 2;
+ init_event_name_sizing(&param);
+ rc= init_memory_class(param.m_memory_class_sizing);
+ ok(rc == 0, "init memory class");
+ rc= init_instruments(& param);
+ ok(rc == 1, "oom (global memory)");
+
+ cleanup_memory_class();
+ cleanup_instruments();
}
void do_all_tests()
@@ -686,10 +450,10 @@ void do_all_tests()
int main(int argc, char **argv)
{
- plan(20);
+ plan(32);
MY_INIT(argv[0]);
do_all_tests();
my_end(0);
- return (exit_status());
+ return exit_status();
}
diff --git a/storage/perfschema/unittest/pfs_instr-t.cc b/storage/perfschema/unittest/pfs_instr-t.cc
index c9f4bac1171..d4401ab7ea2 100644
--- a/storage/perfschema/unittest/pfs_instr-t.cc
+++ b/storage/perfschema/unittest/pfs_instr-t.cc
@@ -21,13 +21,16 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
#include <my_global.h>
-#include <my_pthread.h>
+#include <my_thread.h>
#include <pfs_instr.h>
#include <pfs_stat.h>
#include <pfs_global.h>
#include <pfs_instr_class.h>
+#include <pfs_buffer_container.h>
#include <tap.h>
+#include "stub_global_status_var.h"
+
#include <memory.h>
PFS_global_param param;
@@ -66,9 +69,15 @@ 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_events_transactions_history_sizing= 0;
+ param.m_events_transactions_history_long_sizing= 0;
param.m_digest_sizing= 0;
param.m_session_connect_attrs_sizing= 0;
- param.m_max_digest_length= 0;
+ param.m_program_sizing= 0;
+ param.m_prepared_stmt_sizing= 0;
+ param.m_statement_stack_sizing= 0;
+ param.m_memory_class_sizing= 0;
+ param.m_metadata_lock_sizing= 0;
init_event_name_sizing(& param);
rc= init_instruments(& param);
@@ -95,6 +104,27 @@ void test_no_instances()
PFS_socket *socket;
PFS_table *table;
+ dummy_mutex_class.m_event_name_index = 0;
+ dummy_mutex_class.m_flags = 0;
+ dummy_mutex_class.m_enabled = true;
+ dummy_mutex_class.m_volatility = PSI_VOLATILITY_UNKNOWN;
+ dummy_rwlock_class.m_event_name_index = 1;
+ dummy_rwlock_class.m_flags = 0;
+ dummy_rwlock_class.m_enabled = true;
+ dummy_rwlock_class.m_volatility = PSI_VOLATILITY_UNKNOWN;
+ dummy_cond_class.m_event_name_index = 2;
+ dummy_cond_class.m_flags = 0;
+ dummy_cond_class.m_enabled = true;
+ dummy_cond_class.m_volatility = PSI_VOLATILITY_UNKNOWN;
+ dummy_file_class.m_event_name_index = 3;
+ dummy_file_class.m_flags = 0;
+ dummy_file_class.m_enabled = true;
+ dummy_file_class.m_volatility = PSI_VOLATILITY_UNKNOWN;
+ dummy_socket_class.m_event_name_index = 4;
+ dummy_socket_class.m_flags = 0;
+ dummy_socket_class.m_enabled = true;
+ dummy_socket_class.m_volatility = PSI_VOLATILITY_UNKNOWN;
+
memset(& param, 0xFF, sizeof(param));
param.m_enabled= true;
param.m_mutex_class_sizing= 1;
@@ -125,9 +155,15 @@ 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_events_transactions_history_sizing= 0;
+ param.m_events_transactions_history_long_sizing= 0;
param.m_digest_sizing= 0;
param.m_session_connect_attrs_sizing= 0;
- param.m_max_digest_length= 0;
+ param.m_program_sizing= 0;
+ param.m_prepared_stmt_sizing= 0;
+ param.m_statement_stack_sizing= 0;
+ param.m_memory_class_sizing= 1;
+ param.m_metadata_lock_sizing= 0;
init_event_name_sizing(& param);
rc= init_instruments(& param);
@@ -135,50 +171,50 @@ void test_no_instances()
mutex= create_mutex(& dummy_mutex_class, NULL);
ok(mutex == NULL, "no mutex");
- ok(mutex_lost == 1, "lost 1");
+ ok(global_mutex_container.get_lost_counter() == 1, "lost 1");
mutex= create_mutex(& dummy_mutex_class, NULL);
ok(mutex == NULL, "no mutex");
- ok(mutex_lost == 2, "lost 2");
+ ok(global_mutex_container.get_lost_counter() == 2, "lost 2");
rwlock= create_rwlock(& dummy_rwlock_class, NULL);
ok(rwlock == NULL, "no rwlock");
- ok(rwlock_lost == 1, "lost 1");
+ ok(global_rwlock_container.m_lost == 1, "lost 1");
rwlock= create_rwlock(& dummy_rwlock_class, NULL);
ok(rwlock == NULL, "no rwlock");
- ok(rwlock_lost == 2, "lost 2");
+ ok(global_rwlock_container.m_lost == 2, "lost 2");
cond= create_cond(& dummy_cond_class, NULL);
ok(cond == NULL, "no cond");
- ok(cond_lost == 1, "lost 1");
+ ok(global_cond_container.m_lost == 1, "lost 1");
cond= create_cond(& dummy_cond_class, NULL);
ok(cond == NULL, "no cond");
- ok(cond_lost == 2, "lost 2");
+ ok(global_cond_container.m_lost == 2, "lost 2");
thread= create_thread(& dummy_thread_class, NULL, 0);
ok(thread == NULL, "no thread");
- ok(thread_lost == 1, "lost 1");
+ ok(global_thread_container.m_lost == 1, "lost 1");
thread= create_thread(& dummy_thread_class, NULL, 0);
ok(thread == NULL, "no thread");
- ok(thread_lost == 2, "lost 2");
+ ok(global_thread_container.m_lost == 2, "lost 2");
PFS_thread fake_thread;
fake_thread.m_filename_hash_pins= NULL;
file= find_or_create_file(& fake_thread, & dummy_file_class, "dummy", 5, true);
ok(file == NULL, "no file");
- ok(file_lost == 1, "lost 1");
+ ok(global_file_container.m_lost == 1, "lost 1");
file= find_or_create_file(& fake_thread, & dummy_file_class, "dummy", 5, true);
ok(file == NULL, "no file");
- ok(file_lost == 2, "lost 2");
+ ok(global_file_container.m_lost == 2, "lost 2");
- init_file_hash();
+ init_file_hash(& param);
file= find_or_create_file(& fake_thread, & dummy_file_class, "dummy", 5, true);
ok(file == NULL, "no file");
- ok(file_lost == 3, "lost 3");
+ ok(global_file_container.m_lost == 3, "lost 3");
file= find_or_create_file(& fake_thread, & dummy_file_class, "dummy", 5, true);
ok(file == NULL, "no file");
- ok(file_lost == 4, "lost 4");
+ ok(global_file_container.m_lost == 4, "lost 4");
char long_file_name[10000];
int size= sizeof(long_file_name);
@@ -186,21 +222,21 @@ void test_no_instances()
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");
+ ok(global_file_container.m_lost == 5, "lost 5");
table= create_table(& dummy_table_share, & fake_thread, NULL);
ok(table == NULL, "no table");
- ok(table_lost == 1, "lost 1");
+ ok(global_table_container.m_lost == 1, "lost 1");
table= create_table(& dummy_table_share, & fake_thread, NULL);
ok(table == NULL, "no table");
- ok(table_lost == 2, "lost 2");
+ ok(global_table_container.m_lost == 2, "lost 2");
socket= create_socket(& dummy_socket_class, NULL, NULL, 0);
ok(socket == NULL, "no socket");
- ok(socket_lost == 1, "lost 1");
+ ok(global_socket_container.m_lost == 1, "lost 1");
socket= create_socket(& dummy_socket_class, NULL, NULL, 0);
ok(socket == NULL, "no socket");
- ok(socket_lost == 2, "lost 2");
+ ok(global_socket_container.m_lost == 2, "lost 2");
/* No result to test, just make sure it does not crash */
reset_events_waits_by_instance();
@@ -265,139 +301,163 @@ 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_events_transactions_history_sizing= 0;
+ param.m_events_transactions_history_long_sizing= 0;
param.m_digest_sizing= 0;
param.m_session_connect_attrs_sizing= 0;
- param.m_max_digest_length= 0;
+ param.m_program_sizing= 0;
+ param.m_prepared_stmt_sizing= 0;
+ param.m_statement_stack_sizing= 0;
+ param.m_memory_class_sizing= 1;
+ param.m_metadata_lock_sizing= 0;
init_event_name_sizing(& param);
rc= init_instruments(& param);
ok(rc == 0, "instances init");
dummy_mutex_class.m_event_name_index= 0;
+ dummy_mutex_class.m_flags= 0;
+ dummy_mutex_class.m_enabled= true;
+ dummy_mutex_class.m_volatility = PSI_VOLATILITY_UNKNOWN;
dummy_rwlock_class.m_event_name_index= 1;
+ dummy_rwlock_class.m_flags= 0;
+ dummy_rwlock_class.m_enabled= true;
+ dummy_rwlock_class.m_volatility = PSI_VOLATILITY_UNKNOWN;
dummy_cond_class.m_event_name_index= 2;
+ dummy_cond_class.m_flags= 0;
+ dummy_cond_class.m_enabled= true;
+ dummy_cond_class.m_volatility = PSI_VOLATILITY_UNKNOWN;
dummy_file_class.m_event_name_index= 3;
+ dummy_file_class.m_flags= 0;
+ dummy_file_class.m_enabled= true;
+ dummy_file_class.m_volatility = PSI_VOLATILITY_UNKNOWN;
dummy_socket_class.m_event_name_index= 4;
+ dummy_socket_class.m_flags= 0;
+ dummy_socket_class.m_enabled= true;
+ dummy_socket_class.m_volatility = PSI_VOLATILITY_UNKNOWN;
+
+ dummy_table_share.m_enabled= true;
+ dummy_table_share.m_timed= true;
mutex_1= create_mutex(& dummy_mutex_class, NULL);
ok(mutex_1 != NULL, "mutex");
- ok(mutex_lost == 0, "not lost");
+ ok(global_mutex_container.get_lost_counter() == 0, "not lost");
mutex_2= create_mutex(& dummy_mutex_class, NULL);
ok(mutex_2 != NULL, "mutex");
- ok(mutex_lost == 0, "not lost");
+ ok(global_mutex_container.get_lost_counter() == 0, "not lost");
mutex_2= create_mutex(& dummy_mutex_class, NULL);
ok(mutex_2 == NULL, "no mutex");
- ok(mutex_lost == 1, "lost 1");
+ ok(global_mutex_container.get_lost_counter() == 1, "lost 1");
destroy_mutex(mutex_1);
mutex_2= create_mutex(& dummy_mutex_class, NULL);
ok(mutex_2 != NULL, "mutex");
- ok(mutex_lost == 1, "no new loss");
+ ok(global_mutex_container.get_lost_counter() == 1, "no new loss");
rwlock_1= create_rwlock(& dummy_rwlock_class, NULL);
ok(rwlock_1 != NULL, "rwlock");
- ok(rwlock_lost == 0, "not lost");
+ ok(global_rwlock_container.m_lost == 0, "not lost");
rwlock_2= create_rwlock(& dummy_rwlock_class, NULL);
ok(rwlock_2 != NULL, "rwlock");
- ok(rwlock_lost == 0, "not lost");
+ ok(global_rwlock_container.m_lost == 0, "not lost");
rwlock_2= create_rwlock(& dummy_rwlock_class, NULL);
ok(rwlock_2 == NULL, "no rwlock");
- ok(rwlock_lost == 1, "lost 1");
+ ok(global_rwlock_container.m_lost == 1, "lost 1");
destroy_rwlock(rwlock_1);
rwlock_2= create_rwlock(& dummy_rwlock_class, NULL);
ok(rwlock_2 != NULL, "rwlock");
- ok(rwlock_lost == 1, "no new loss");
+ ok(global_rwlock_container.m_lost == 1, "no new loss");
cond_1= create_cond(& dummy_cond_class, NULL);
ok(cond_1 != NULL, "cond");
- ok(cond_lost == 0, "not lost");
+ ok(global_cond_container.m_lost == 0, "not lost");
cond_2= create_cond(& dummy_cond_class, NULL);
ok(cond_2 != NULL, "cond");
- ok(cond_lost == 0, "not lost");
+ ok(global_cond_container.m_lost == 0, "not lost");
cond_2= create_cond(& dummy_cond_class, NULL);
ok(cond_2 == NULL, "no cond");
- ok(cond_lost == 1, "lost 1");
+ ok(global_cond_container.m_lost == 1, "lost 1");
destroy_cond(cond_1);
cond_2= create_cond(& dummy_cond_class, NULL);
ok(cond_2 != NULL, "cond");
- ok(cond_lost == 1, "no new loss");
+ ok(global_cond_container.m_lost == 1, "no new loss");
thread_1= create_thread(& dummy_thread_class, NULL, 0);
ok(thread_1 != NULL, "thread");
- ok(thread_lost == 0, "not lost");
+ ok(global_thread_container.m_lost == 0, "not lost");
thread_2= create_thread(& dummy_thread_class, NULL, 0);
ok(thread_2 != NULL, "thread");
- ok(thread_lost == 0, "not lost");
+ ok(global_thread_container.m_lost == 0, "not lost");
thread_2= create_thread(& dummy_thread_class, NULL, 0);
ok(thread_2 == NULL, "no thread");
- ok(thread_lost == 1, "lost 1");
+ ok(global_thread_container.m_lost == 1, "lost 1");
destroy_thread(thread_1);
thread_2= create_thread(& dummy_thread_class, NULL, 0);
ok(thread_2 != NULL, "thread");
- ok(thread_lost == 1, "no new loss");
+ ok(global_thread_container.m_lost == 1, "no new loss");
PFS_thread fake_thread;
fake_thread.m_filename_hash_pins= NULL;
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");
+ ok(global_file_container.m_lost == 1, "lost 1");
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");
+ ok(global_file_container.m_lost == 2, "lost 2");
- init_file_hash();
- file_lost= 0;
+ init_file_hash(& param);
+ global_file_container.m_lost= 0;
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");
+ ok(global_file_container.m_lost == 0, "not lost");
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");
+ ok(global_file_container.m_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, true);
ok(file_2 != NULL, "file");
- ok(file_lost == 0, "not lost");
+ ok(global_file_container.m_lost == 0, "not lost");
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");
+ ok(global_file_container.m_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, true);
ok(file_2 == NULL, "no file");
- ok(file_lost == 2, "lost");
+ ok(global_file_container.m_lost == 2, "lost");
socket_1= create_socket(& dummy_socket_class, NULL, NULL, 0);
ok(socket_1 != NULL, "socket");
- ok(socket_lost == 0, "not lost");
+ ok(global_socket_container.m_lost == 0, "not lost");
socket_2= create_socket(& dummy_socket_class, NULL, NULL, 0);
ok(socket_2 != NULL, "socket");
- ok(socket_lost == 0, "not lost");
+ ok(global_socket_container.m_lost == 0, "not lost");
socket_2= create_socket(& dummy_socket_class, NULL, NULL, 0);
ok(socket_2 == NULL, "no socket");
- ok(socket_lost == 1, "lost 1");
+ ok(global_socket_container.m_lost == 1, "lost 1");
destroy_socket(socket_1);
socket_2= create_socket(& dummy_socket_class, NULL, NULL, 0);
ok(socket_2 != NULL, "socket");
- ok(socket_lost == 1, "no new loss");
+ ok(global_socket_container.m_lost == 1, "no new loss");
table_1= create_table(& dummy_table_share, & fake_thread, NULL);
ok(table_1 != NULL, "table");
- ok(table_lost == 0, "not lost");
+ ok(global_table_container.m_lost == 0, "not lost");
table_2= create_table(& dummy_table_share, & fake_thread, NULL);
ok(table_2 != NULL, "table");
- ok(table_lost == 0, "not lost");
+ ok(global_table_container.m_lost == 0, "not lost");
table_2= create_table(& dummy_table_share, & fake_thread, NULL);
ok(table_2 == NULL, "no table");
- ok(table_lost == 1, "lost 1");
+ ok(global_table_container.m_lost == 1, "lost 1");
destroy_table(table_1);
table_2= create_table(& dummy_table_share, & fake_thread, NULL);
ok(table_2 != NULL, "table");
- ok(table_lost == 1, "no new loss");
+ ok(global_table_container.m_lost == 1, "no new loss");
//TODO: test that cleanup works
reset_events_waits_by_instance();
@@ -409,6 +469,9 @@ void test_with_instances()
void do_all_tests()
{
+ flag_global_instrumentation= true;
+ flag_thread_instrumentation= true;
+
test_no_instruments();
test_no_instances();
test_with_instances();
diff --git a/storage/perfschema/unittest/pfs_instr_class-oom-t.cc b/storage/perfschema/unittest/pfs_instr_class-oom-t.cc
index 7eb21a33bd7..0f9d6ef07d5 100644
--- a/storage/perfschema/unittest/pfs_instr_class-oom-t.cc
+++ b/storage/perfschema/unittest/pfs_instr_class-oom-t.cc
@@ -21,16 +21,24 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
#include <my_global.h>
-#include <my_pthread.h>
+#include <my_thread.h>
#include <pfs_instr_class.h>
+#include <pfs_instr.h>
#include <pfs_global.h>
#include <tap.h>
+#include <sql_class.h>
+#include <pfs_buffer_container.h>
#include "stub_pfs_global.h"
+#include "stub_global_status_var.h"
void test_oom()
{
int rc;
+ PFS_global_param param;
+ TABLE_SHARE table_share;
+ PFS_thread pfs_thread;
+ PFS_table_share *pfs_table_share;
rc= init_sync_class(1000, 0, 0);
ok(rc == 1, "oom (mutex)");
@@ -42,14 +50,14 @@ void test_oom()
ok(rc == 1, "oom (thread)");
rc= init_file_class(1000);
ok(rc == 1, "oom (file)");
- rc= init_table_share(1000);
- ok(rc == 1, "oom (cond)");
rc= init_socket_class(1000);
ok(rc == 1, "oom (socket)");
rc= init_stage_class(1000);
ok(rc == 1, "oom (stage)");
rc= init_statement_class(1000);
ok(rc == 1, "oom (statement)");
+ rc= init_memory_class(1000);
+ ok(rc == 1, "oom (memory)");
cleanup_sync_class();
cleanup_thread_class();
@@ -58,6 +66,36 @@ void test_oom()
cleanup_socket_class();
cleanup_stage_class();
cleanup_statement_class();
+ cleanup_memory_class();
+
+ /* Table share classes. */
+ memset(&param, 0, sizeof(param));
+ param.m_enabled= true;
+ param.m_table_share_sizing= 100;
+ param.m_setup_object_sizing= 100;
+
+ pfs_thread.m_table_share_hash_pins= NULL;
+ pfs_thread.m_setup_object_hash_pins= NULL;
+
+ char db_name[]= "schema 1";
+ char table_name[]= "table 1";
+ table_share.db.str= db_name;
+ table_share.db.length= strlen(db_name);
+ table_share.table_name.str= table_name;
+ table_share.table_name.length= strlen(table_name);
+
+ init_table_share(param.m_table_share_sizing);
+ init_table_share_hash(&param);
+ init_setup_object_hash(&param);
+
+ stub_alloc_always_fails= false;
+ pfs_table_share= find_or_create_table_share(&pfs_thread, false, &table_share);
+ ok(pfs_table_share == NULL, "oom (pfs table share)");
+ ok(global_table_share_container.m_lost == 1, "oom (table share)");
+
+ cleanup_table_share();
+ cleanup_table_share_hash();
+ cleanup_setup_object_hash();
}
void do_all_tests()
@@ -67,7 +105,7 @@ void do_all_tests()
int main(int argc, char **argv)
{
- plan(9);
+ plan(11);
MY_INIT(argv[0]);
do_all_tests();
my_end(0);
diff --git a/storage/perfschema/unittest/pfs_instr_class-t.cc b/storage/perfschema/unittest/pfs_instr_class-t.cc
index f1e246dc387..3dfd725cb91 100644
--- a/storage/perfschema/unittest/pfs_instr_class-t.cc
+++ b/storage/perfschema/unittest/pfs_instr_class-t.cc
@@ -21,13 +21,15 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
#include <my_global.h>
-#include <my_pthread.h>
+#include <my_thread.h>
#include <string.h> // strncpy
#include <pfs_instr_class.h>
#include <pfs_instr.h>
#include <pfs_global.h>
#include <tap.h>
+#include "stub_global_status_var.h"
+
void test_no_registration()
{
int rc;
@@ -35,12 +37,14 @@ void test_no_registration()
PFS_thread_key thread_key;
PFS_file_key file_key;
PFS_socket_key socket_key;
+ PFS_memory_key memory_key;
PFS_mutex_class *mutex;
PFS_rwlock_class *rwlock;
PFS_cond_class *cond;
PFS_thread_class *thread;
PFS_file_class *file;
PFS_socket_class *socket;
+ PFS_memory_class *memory;
/* PFS_table_share *table; */
rc= init_sync_class(0, 0, 0);
@@ -53,6 +57,8 @@ void test_no_registration()
ok(rc == 0, "zero init (socket)");
rc= init_table_share(0);
ok(rc == 0, "zero init (table)");
+ rc= init_memory_class(0);
+ ok(rc == 0, "zero init (memory)");
key= register_mutex_class("FOO", 3, 0);
ok(key == 0, "no mutex registered");
@@ -96,6 +102,13 @@ void test_no_registration()
socket_key= register_socket_class("FOO", 3, 0);
ok(socket_key == 0, "no socket registered");
+ memory_key= register_memory_class("FOO", 3, 0);
+ ok(memory_key == 0, "no memory registered");
+ memory_key= register_memory_class("BAR", 3, 0);
+ ok(memory_key == 0, "no memory registered");
+ memory_key= register_memory_class("FOO", 3, 0);
+ ok(memory_key == 0, "no memory registered");
+
#ifdef LATER
PFS_thread fake_thread;
fake_thread.m_table_share_hash_pins= NULL;
@@ -150,11 +163,19 @@ void test_no_registration()
socket= find_socket_class(9999);
ok(socket == NULL, "no socket key 9999");
+ memory= find_memory_class(0);
+ ok(memory == NULL, "no memory key 0");
+ memory= find_memory_class(1);
+ ok(memory == NULL, "no memory key 1");
+ memory= find_memory_class(9999);
+ ok(memory == NULL, "no memory key 9999");
+
cleanup_sync_class();
cleanup_thread_class();
cleanup_file_class();
cleanup_socket_class();
cleanup_table_share();
+ cleanup_memory_class();
}
void test_mutex_registration()
@@ -480,6 +501,53 @@ void test_table_registration()
#endif
}
+void test_memory_registration()
+{
+ int rc;
+ PFS_memory_key key;
+ PFS_memory_class *memory;
+
+ rc= init_memory_class(5);
+ ok(rc == 0, "room for 5 memory");
+
+ key= register_memory_class("FOO", 3, 0);
+ ok(key == 1, "foo registered");
+ key= register_memory_class("BAR", 3, 0);
+ ok(key == 2, "bar registered");
+ key= register_memory_class("FOO", 3, 0);
+ ok(key == 1, "foo re registered");
+ key= register_memory_class("Memory-3", 8, 0);
+ ok(key == 3, "Memory-3 registered");
+ key= register_memory_class("Memory-4", 8, 0);
+ ok(key == 4, "Memory-4 registered");
+ key= register_memory_class("Memory-5", 8, 0);
+ ok(key == 5, "Memory-5 registered");
+ ok(memory_class_lost == 0, "lost nothing");
+ key= register_memory_class("Memory-6", 8, 0);
+ ok(key == 0, "Memory-6 not registered");
+ ok(memory_class_lost == 1, "lost 1 memory");
+ key= register_memory_class("Memory-7", 8, 0);
+ ok(key == 0, "Memory-7 not registered");
+ ok(memory_class_lost == 2, "lost 2 memory");
+ key= register_memory_class("Memory-3", 8, 0);
+ ok(key == 3, "Memory-3 re registered");
+ ok(memory_class_lost == 2, "lost 2 memory");
+ key= register_memory_class("Memory-5", 8, 0);
+ ok(key == 5, "Memory-5 re registered");
+ ok(memory_class_lost == 2, "lost 2 memory");
+
+ memory= find_memory_class(0);
+ ok(memory == NULL, "no key 0");
+ memory= find_memory_class(3);
+ ok(memory != NULL, "found key 3");
+ ok(strncmp(memory->m_name, "Memory-3", 8) == 0, "key 3 is Memory-3");
+ ok(memory->m_name_length == 8, "name length 3");
+ memory= find_memory_class(9999);
+ ok(memory == NULL, "no key 9999");
+
+ cleanup_memory_class();
+}
+
#ifdef LATER
void set_wait_stat(PFS_instr_class *klass)
{
@@ -668,12 +736,13 @@ void do_all_tests()
test_file_registration();
test_socket_registration();
test_table_registration();
+ test_memory_registration();
test_instruments_reset();
}
int main(int argc, char **argv)
{
- plan(181);
+ plan(209);
MY_INIT(argv[0]);
do_all_tests();
my_end(0);
diff --git a/storage/perfschema/unittest/pfs_misc-t.cc b/storage/perfschema/unittest/pfs_misc-t.cc
index 7d274c0820d..d82178000c2 100644
--- a/storage/perfschema/unittest/pfs_misc-t.cc
+++ b/storage/perfschema/unittest/pfs_misc-t.cc
@@ -21,22 +21,26 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
#include <my_global.h>
+#include <my_thread.h>
#include <pfs_instr.h>
#include <pfs_stat.h>
#include <pfs_global.h>
#include <pfs_instr_class.h>
+#include <pfs_buffer_container.h>
#include <tap.h>
+#include "stub_global_status_var.h"
+
#include <memory.h>
void test_digest_length_overflow()
{
if (sizeof(size_t) != 4)
{
- skip(2, "digest length overflow requires a 32-bit environment");
+ skip(3, "digest length overflow requires a 32-bit environment");
return;
}
-
+
PFS_global_param param;
memset(&param, 0, sizeof(param));
param.m_enabled= true;
@@ -45,19 +49,32 @@ void test_digest_length_overflow()
parameters. The Performance Schema should detect the overflow, free
allocated memory and abort initialization with a warning.
*/
-
+
/* Max digest length, events_statements_history_long. */
param.m_events_statements_history_long_sizing= 10000;
param.m_digest_sizing= 1000;
param.m_max_digest_length= (1024 * 1024);
+ param.m_max_sql_text_length= 0;
pfs_max_digest_length= param.m_max_digest_length;
+ pfs_max_sqltext= param.m_max_sql_text_length;
int rc = init_events_statements_history_long(param.m_events_statements_history_long_sizing);
ok(rc == 1, "digest length overflow (init_events_statements_history_long");
+ /* Max sql text length, events_statements_history_long. */
+ param.m_max_sql_text_length= (1024 * 1024);
+ param.m_max_digest_length= 0;
+ pfs_max_digest_length= param.m_max_digest_length;
+ pfs_max_sqltext= param.m_max_sql_text_length;
+
+ rc = init_events_statements_history_long(param.m_events_statements_history_long_sizing);
+ ok(rc == 1, "sql text length overflow (init_events_statements_history_long");
+
/* Max digest length, events_statements_summary_by_digest. */
param.m_max_digest_length= (1024 * 1024);
param.m_digest_sizing= 10000;
+ pfs_max_digest_length= param.m_max_digest_length;
+ pfs_max_sqltext= param.m_max_sql_text_length;
rc = init_digest(&param);
ok(rc == 1, "digest length overflow (init_digest)");
@@ -70,10 +87,9 @@ void do_all_tests()
int main(int, char **)
{
- plan(2);
+ plan(3);
MY_INIT("pfs_misc-t");
do_all_tests();
my_end(0);
return (exit_status());
}
-
diff --git a/storage/perfschema/unittest/pfs_noop-t.cc b/storage/perfschema/unittest/pfs_noop-t.cc
new file mode 100644
index 00000000000..8ef11371519
--- /dev/null
+++ b/storage/perfschema/unittest/pfs_noop-t.cc
@@ -0,0 +1,242 @@
+/* Copyright (c) 2013, 2017, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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_thread.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>
+
+#include "stub_print_error.h"
+#include "stub_pfs_defaults.h"
+
+void test_noop()
+{
+ PSI_mutex *mutex;
+ PSI_rwlock *rwlock;
+ PSI_cond *cond;
+ PSI_socket *socket;
+ PSI_table_share *table_share;
+ PSI_table *table;
+ PSI_file *file;
+ PSI_thread *thread;
+ PSI_file_locker *file_locker;
+ PSI_idle_locker *idle_locker;
+ PSI_mutex_locker *mutex_locker;
+ PSI_rwlock_locker *rwlock_locker;
+ PSI_cond_locker *cond_locker;
+ PSI_table_locker *table_locker;
+ PSI_statement_locker *statement_locker;
+ PSI_transaction_locker *transaction_locker;
+ PSI_socket_locker *socket_locker;
+ PSI_digest_locker *digest_locker;
+ PSI_sp_locker *sp_locker;
+ PSI_sp_share *sp_share;
+ PSI_memory_key memory_key;
+ PSI_metadata_lock *metadata_lock;
+ PSI_metadata_locker *metadata_locker;
+ PSI_thread *owner;
+
+ diag("test_noop");
+
+ PSI_server->register_mutex(NULL, NULL, 0);
+ PSI_server->register_rwlock(NULL, NULL, 0);
+ PSI_server->register_cond(NULL, NULL, 0);
+ PSI_server->register_thread(NULL, NULL, 0);
+ PSI_server->register_file(NULL, NULL, 0);
+ PSI_server->register_stage(NULL, NULL, 0);
+ PSI_server->register_statement(NULL, NULL, 0);
+ PSI_server->register_socket(NULL, NULL, 0);
+
+ ok(true, "register");
+ mutex= PSI_server->init_mutex(1, NULL);
+ ok(mutex == NULL, "no mutex");
+ PSI_server->destroy_mutex(NULL);
+ rwlock= PSI_server->init_rwlock(1, NULL);
+ ok(rwlock == NULL, "no rwlock");
+ PSI_server->destroy_rwlock(NULL);
+ cond= PSI_server->init_cond(1, NULL);
+ ok(cond == NULL, "no cond");
+ PSI_server->destroy_cond(NULL);
+ socket= PSI_server->init_socket(1, NULL, NULL, 0);
+ ok(socket == NULL, "no socket");
+ PSI_server->destroy_socket(NULL);
+ table_share= PSI_server->get_table_share(false, NULL);
+ ok(table_share == NULL, "no table_share");
+ PSI_server->release_table_share(NULL);
+ PSI_server->drop_table_share(false, NULL, 0, NULL, 0);
+ table= PSI_server->open_table(NULL, NULL);
+ ok(table == NULL, "no table");
+ PSI_server->unbind_table(NULL);
+ table= PSI_server->rebind_table(NULL, NULL, NULL);
+ ok(table == NULL, "no table");
+ PSI_server->close_table(NULL, NULL);
+ PSI_server->create_file(1, NULL, 2);
+ /* TODO: spawn thread */
+ thread= PSI_server->new_thread(1, NULL, 2);
+ ok(thread == NULL, "no thread");
+ PSI_server->set_thread_id(NULL, 1);
+ thread= PSI_server->get_thread();
+ ok(thread == NULL, "no thread");
+ PSI_server->set_thread_user(NULL, 0);
+ PSI_server->set_thread_account(NULL, 0, NULL, 0);
+ PSI_server->set_thread_db(NULL, 0);
+ PSI_server->set_thread_command(1);
+ PSI_server->set_thread_start_time(1);
+ PSI_server->set_thread_state(NULL);
+ PSI_server->set_thread_info(NULL, 0);
+ PSI_server->set_thread(NULL);
+ PSI_server->delete_current_thread();
+ PSI_server->delete_thread(NULL);
+ file_locker= PSI_server->get_thread_file_name_locker(NULL, 1, PSI_FILE_OPEN, NULL, NULL);
+ ok(file_locker == NULL, "no file_locker");
+ file_locker= PSI_server->get_thread_file_stream_locker(NULL, NULL, PSI_FILE_OPEN);
+ ok(file_locker == NULL, "no file_locker");
+ file_locker= PSI_server->get_thread_file_descriptor_locker(NULL, 0, PSI_FILE_OPEN);
+ ok(file_locker == NULL, "no file_locker");
+ PSI_server->unlock_mutex(NULL);
+ PSI_server->unlock_rwlock(NULL);
+ PSI_server->signal_cond(NULL);
+ PSI_server->broadcast_cond(NULL);
+ idle_locker= PSI_server->start_idle_wait(NULL, NULL, 0);
+ ok(idle_locker == NULL, "no idle_locker");
+ PSI_server->end_idle_wait(NULL);
+ mutex_locker= PSI_server->start_mutex_wait(NULL, NULL, PSI_MUTEX_LOCK, NULL, 0);
+ ok(mutex_locker == NULL, "no mutex_locker");
+ PSI_server->end_mutex_wait(NULL, 0);
+ rwlock_locker= PSI_server->start_rwlock_rdwait(NULL, NULL, PSI_RWLOCK_READLOCK, NULL, 0);
+ ok(rwlock_locker == NULL, "no rwlock_locker");
+ PSI_server->end_rwlock_rdwait(NULL, 0);
+ rwlock_locker= PSI_server->start_rwlock_wrwait(NULL, NULL, PSI_RWLOCK_WRITELOCK, NULL, 0);
+ ok(rwlock_locker == NULL, "no rwlock_locker");
+ PSI_server->end_rwlock_wrwait(NULL, 0);
+ cond_locker= PSI_server->start_cond_wait(NULL, NULL, NULL, PSI_COND_WAIT, NULL, 0);
+ ok(cond_locker == NULL, "no cond_locker");
+ PSI_server->end_cond_wait(NULL, 0);
+ table_locker= PSI_server->start_table_io_wait(NULL, NULL, PSI_TABLE_FETCH_ROW, 0, NULL, 0);
+ ok(table_locker == NULL, "no table_locker");
+ PSI_server->end_table_io_wait(NULL, 0);
+ table_locker= PSI_server->start_table_lock_wait(NULL, NULL, PSI_TABLE_LOCK, 0, NULL, 0);
+ ok(table_locker == NULL, "no table_locker");
+ PSI_server->end_table_lock_wait(NULL);
+ PSI_server->start_file_open_wait(NULL, NULL, 0);
+ file= PSI_server->end_file_open_wait(NULL, NULL);
+ ok(file == NULL, "no file");
+ PSI_server->end_file_open_wait_and_bind_to_descriptor(NULL, 0);
+ PSI_server->start_file_wait(NULL, 0, NULL, 0);
+ PSI_server->end_file_wait(NULL, 0);
+ PSI_server->start_file_close_wait(NULL, NULL, 0);
+ PSI_server->end_file_close_wait(NULL, 0);
+ PSI_server->end_file_rename_wait(NULL, NULL, NULL, 0);
+ PSI_server->start_stage(1, NULL, 0);
+
+ PSI_stage_progress *progress;
+ progress= PSI_server->get_current_stage_progress();
+ ok(progress == NULL, "no progress");
+
+ PSI_server->end_stage();
+ statement_locker= PSI_server->get_thread_statement_locker(NULL, 1, NULL, NULL);
+ ok(statement_locker == NULL, "no statement_locker");
+ statement_locker= PSI_server->refine_statement(NULL, 1);
+ ok(statement_locker == NULL, "no statement_locker");
+ PSI_server->start_statement(NULL, NULL, 0, NULL, 0);
+ PSI_server->set_statement_text(NULL, NULL, 0);
+ PSI_server->set_statement_lock_time(NULL, 0);
+ PSI_server->set_statement_rows_sent(NULL, 0);
+ PSI_server->set_statement_rows_examined(NULL, 0);
+ PSI_server->inc_statement_created_tmp_disk_tables(NULL, 0);
+ PSI_server->inc_statement_created_tmp_tables(NULL, 0);
+ PSI_server->inc_statement_select_full_join(NULL, 0);
+ PSI_server->inc_statement_select_full_range_join(NULL, 0);
+ PSI_server->inc_statement_select_range(NULL, 0);
+ PSI_server->inc_statement_select_range_check(NULL, 0);
+ PSI_server->inc_statement_select_scan(NULL, 0);
+ PSI_server->inc_statement_sort_merge_passes(NULL, 0);
+ PSI_server->inc_statement_sort_range(NULL, 0);
+ PSI_server->inc_statement_sort_rows(NULL, 0);
+ PSI_server->inc_statement_sort_scan(NULL, 0);
+ PSI_server->set_statement_no_index_used(NULL);
+ PSI_server->set_statement_no_good_index_used(NULL);
+ PSI_server->end_statement(NULL, NULL);
+ socket_locker= PSI_server->start_socket_wait(NULL, NULL, PSI_SOCKET_SEND, 1, NULL, 0);
+ ok(socket_locker == NULL, "no socket_locker");
+ PSI_server->end_socket_wait(NULL, 0);
+ PSI_server->set_socket_state(NULL, PSI_SOCKET_STATE_IDLE);
+ PSI_server->set_socket_info(NULL, NULL, NULL, 0);
+ PSI_server->set_socket_thread_owner(NULL);
+ digest_locker= PSI_server->digest_start(NULL);
+ ok(digest_locker == NULL, "no digest_locker");
+ PSI_server->digest_end(NULL, NULL);
+ sp_locker= PSI_server->start_sp(NULL, NULL);
+ ok(sp_locker == NULL, "no sp_locker");
+ PSI_server->end_sp(NULL);
+ PSI_server->drop_sp(0, NULL, 0, NULL, 0);
+ sp_share= PSI_server->get_sp_share(0, NULL, 0, NULL, 0);
+ ok(sp_share == NULL, "no sp_share");
+ PSI_server->release_sp_share(NULL);
+ PSI_server->register_memory(NULL, NULL, 0);
+ memory_key= PSI_server->memory_alloc(0, 0, & owner);
+ ok(memory_key == PSI_NOT_INSTRUMENTED, "no memory_key");
+ memory_key= PSI_server->memory_realloc(0, 0, 0, & owner);
+ ok(memory_key == PSI_NOT_INSTRUMENTED, "no memory_key");
+ PSI_server->memory_free(0, 0, NULL);
+ PSI_server->unlock_table(NULL);
+ metadata_lock= PSI_server->create_metadata_lock(NULL, NULL, 1, 2, 3, NULL, 0);
+ ok(metadata_lock == NULL, "no metadata_lock");
+ PSI_server->set_metadata_lock_status(NULL, 0);
+ PSI_server->destroy_metadata_lock(NULL);
+ metadata_locker= PSI_server->start_metadata_wait(NULL, NULL, NULL, 0);
+ ok(metadata_locker == NULL, "no metadata_locker");
+ PSI_server->end_metadata_wait(NULL, 0);
+
+ transaction_locker= PSI_server->get_thread_transaction_locker(NULL, NULL, NULL, 1, false, 1);
+ ok(transaction_locker == NULL, "no transaction_locker");
+ PSI_server->start_transaction(NULL, NULL, 0);
+ PSI_server->end_transaction(NULL, true);
+
+ PSI_server->set_transaction_gtid(NULL, NULL, NULL);
+ PSI_server->set_transaction_trxid(NULL, NULL);
+ PSI_server->set_transaction_xa_state(NULL, 1);
+ PSI_server->set_transaction_xid(NULL, NULL, 1);
+ PSI_server->inc_transaction_release_savepoint(NULL, 1);
+ PSI_server->inc_transaction_rollback_to_savepoint(NULL, 1);
+ PSI_server->inc_transaction_savepoints(NULL, 1);
+
+ PSI_server->set_thread_THD(NULL, NULL);
+
+ ok(true, "all noop api called");
+}
+
+int main(int, char **)
+{
+ plan(34);
+
+ MY_INIT("pfs_noop-t");
+ test_noop();
+ return (exit_status());
+}
+
diff --git a/storage/perfschema/unittest/pfs_server_stubs.cc b/storage/perfschema/unittest/pfs_server_stubs.cc
index 0cabce37e51..31894223e89 100644
--- a/storage/perfschema/unittest/pfs_server_stubs.cc
+++ b/storage/perfschema/unittest/pfs_server_stubs.cc
@@ -1,4 +1,5 @@
-/* Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2017, 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, version 2.0,
@@ -29,6 +30,8 @@
#include "sql_class.h"
#include "sql_show.h"
+my_bool show_compatibility_56= FALSE;
+struct system_status_var global_status_var;
struct sql_digest_storage;
uint lower_case_table_names= 0;
@@ -39,6 +42,15 @@ void compute_digest_md5(const sql_digest_storage *, unsigned char *)
{
}
+void reset_status_vars()
+{
+}
+
+void sql_print_warning(const char *format, ...)
+{
+ /* Do not pollute the unit test output with annoying messages. */
+}
+
class sys_var { public: enum where { AUTO }; };
void set_sys_var_value_origin(void *ptr, enum sys_var::where here)
{
diff --git a/storage/perfschema/unittest/pfs_timer-t.cc b/storage/perfschema/unittest/pfs_timer-t.cc
index 139454b8649..6c852242537 100644
--- a/storage/perfschema/unittest/pfs_timer-t.cc
+++ b/storage/perfschema/unittest/pfs_timer-t.cc
@@ -22,7 +22,6 @@
#include <my_global.h>
#include <my_pthread.h>
-#include <pfs_atomic.h>
#include <pfs_timer.h>
#include "my_sys.h"
#include <tap.h>
diff --git a/storage/perfschema/unittest/pfs_user-oom-t.cc b/storage/perfschema/unittest/pfs_user-oom-t.cc
index ca451f3e457..864275b765e 100644
--- a/storage/perfschema/unittest/pfs_user-oom-t.cc
+++ b/storage/perfschema/unittest/pfs_user-oom-t.cc
@@ -21,21 +21,24 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
#include <my_global.h>
-#include <my_pthread.h>
+#include <my_thread.h>
#include <pfs_instr.h>
#include <pfs_stat.h>
#include <pfs_global.h>
#include <pfs_user.h>
+#include <pfs_buffer_container.h>
#include <tap.h>
#include "stub_pfs_global.h"
+#include "stub_global_status_var.h"
#include <string.h> /* memset */
void test_oom()
{
- int rc;
+ PSI *psi;
PFS_global_param param;
+ PSI_bootstrap *boot;
memset(& param, 0xFF, sizeof(param));
param.m_enabled= true;
@@ -45,6 +48,7 @@ void test_oom()
param.m_thread_class_sizing= 10;
param.m_table_share_sizing= 0;
param.m_file_class_sizing= 0;
+ param.m_socket_class_sizing= 0;
param.m_mutex_sizing= 0;
param.m_rwlock_sizing= 0;
param.m_cond_sizing= 0;
@@ -52,6 +56,7 @@ void test_oom()
param.m_table_sizing= 0;
param.m_file_sizing= 0;
param.m_file_handle_sizing= 0;
+ param.m_socket_sizing= 0;
param.m_events_waits_history_sizing= 10;
param.m_events_waits_history_long_sizing= 0;
param.m_setup_actor_sizing= 0;
@@ -65,42 +70,64 @@ 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_events_transactions_history_sizing= 0;
+ param.m_events_transactions_history_long_sizing= 0;
+ param.m_digest_sizing= 0;
+ param.m_session_connect_attrs_sizing= 0;
+ param.m_program_sizing= 0;
+ param.m_statement_stack_sizing= 0;
+ param.m_memory_class_sizing= 10;
+ param.m_metadata_lock_sizing= 0;
+ param.m_max_digest_length= 0;
+ param.m_max_sql_text_length= 0;
/* Setup */
stub_alloc_always_fails= false;
stub_alloc_fails_after_count= 1000;
- init_event_name_sizing(& param);
- rc= init_stage_class(param.m_stage_class_sizing);
- ok(rc == 0, "init stage class");
- rc= init_statement_class(param.m_statement_class_sizing);
- ok(rc == 0, "init statement class");
+ pre_initialize_performance_schema();
+ boot= initialize_performance_schema(&param);
+ psi= (PSI *)boot->get_interface(PSI_VERSION_1);
+
+ PSI_thread_key thread_key_1;
+ PSI_thread_info all_thread[]=
+ {
+ {&thread_key_1, "T-1", 0}
+ };
+ psi->register_thread("test", all_thread, 1);
+
+ PSI_thread *thread_1= psi->new_thread(thread_key_1, NULL, 0);
+ psi->set_thread(thread_1);
/* Tests */
- stub_alloc_fails_after_count= 1;
- rc= init_user(& param);
- ok(rc == 1, "oom (user)");
- cleanup_user();
+ int first_fail= 1;
+ stub_alloc_fails_after_count= first_fail;
+ psi->set_thread_account("user1", 5, "", 0);
+ ok(global_user_container.m_lost == 1, "oom (user)");
+
+ stub_alloc_fails_after_count= first_fail + 1;
+ psi->set_thread_account("user2", 5, "", 0);
+ ok(global_user_container.m_lost == 2, "oom (user waits)");
+
+ stub_alloc_fails_after_count= first_fail + 2;
+ psi->set_thread_account("user3", 5, "", 0);
+ ok(global_user_container.m_lost == 3, "oom (user stages)");
- stub_alloc_fails_after_count= 2;
- rc= init_user(& param);
- ok(rc == 1, "oom (user waits)");
- cleanup_user();
+ stub_alloc_fails_after_count= first_fail + 3;
+ psi->set_thread_account("user4", 5, "", 0);
+ ok(global_user_container.m_lost == 4, "oom (user statements)");
- stub_alloc_fails_after_count= 3;
- rc= init_user(& param);
- ok(rc == 1, "oom (user stages)");
- cleanup_user();
+ stub_alloc_fails_after_count= first_fail + 4;
+ psi->set_thread_account("user5", 5, "", 0);
+ ok(global_user_container.m_lost == 5, "oom (user transactions)");
- stub_alloc_fails_after_count= 4;
- rc= init_user(& param);
- ok(rc == 1, "oom (user statements)");
- cleanup_user();
+ stub_alloc_fails_after_count= first_fail + 5;
+ psi->set_thread_account("user6", 5, "", 0);
+ ok(global_user_container.m_lost == 6, "oom (user memory)");
- cleanup_statement_class();
- cleanup_stage_class();
+ shutdown_performance_schema();
}
void do_all_tests()
diff --git a/storage/perfschema/unittest/stub_global_status_var.h b/storage/perfschema/unittest/stub_global_status_var.h
new file mode 100644
index 00000000000..bfb06b4e0d5
--- /dev/null
+++ b/storage/perfschema/unittest/stub_global_status_var.h
@@ -0,0 +1,31 @@
+/* Copyright (c) 2015, 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, version 2.0,
+ as published by the Free Software Foundation.
+
+ This program is also distributed with certain software (including
+ but not limited to OpenSSL) that is licensed under separate terms,
+ as designated in a particular file or component or in included license
+ documentation. The authors of MySQL hereby grant you an additional
+ permission to link the program and your derivative works with the
+ separately licensed software that they have included with MySQL.
+
+ 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, version 2.0, 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_sys.h>
+#include <pfs_global.h>
+#include <string.h>
+
+
+void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var, bool reset_from_var)
+{
+}
diff --git a/storage/perfschema/unittest/stub_pfs_global.h b/storage/perfschema/unittest/stub_pfs_global.h
index 8a1f9216ba2..23b731cb8b2 100644
--- a/storage/perfschema/unittest/stub_pfs_global.h
+++ b/storage/perfschema/unittest/stub_pfs_global.h
@@ -26,11 +26,13 @@
#include <string.h>
bool pfs_initialized= false;
+size_t pfs_allocated_memory_size= 0;
+size_t pfs_allocated_memory_count= 0;
bool stub_alloc_always_fails= true;
int stub_alloc_fails_after_count= 0;
-void *pfs_malloc(size_t size, myf)
+void *pfs_malloc(PFS_builtin_memory_class *klass, size_t size, myf)
{
/*
Catch non initialized sizing parameter in the unit tests.
@@ -49,19 +51,27 @@ void *pfs_malloc(size_t size, myf)
return ptr;
}
-void pfs_free(void *ptr)
+void pfs_free(PFS_builtin_memory_class *, size_t, void *ptr)
{
if (ptr != NULL)
free(ptr);
}
-void *pfs_malloc_array(size_t n, size_t size, myf flags)
+void *pfs_malloc_array(PFS_builtin_memory_class *klass, size_t n, size_t size, myf flags)
{
size_t array_size= n * size;
/* Check for overflow before allocating. */
if (is_overflow(array_size, n, size))
return NULL;
- return pfs_malloc(array_size, flags);
+ return pfs_malloc(klass, array_size, flags);
+}
+
+void pfs_free_array(PFS_builtin_memory_class *klass, size_t n, size_t size, void *ptr)
+{
+ if (ptr == NULL)
+ return;
+ size_t array_size= n * size;
+ return pfs_free(klass, array_size, ptr);
}
bool is_overflow(size_t product, size_t n1, size_t n2)
@@ -76,3 +86,4 @@ void pfs_print_error(const char *format, ...)
{
}
+
diff --git a/storage/perfschema/unittest/stub_print_error.h b/storage/perfschema/unittest/stub_print_error.h
index 2cd2ad5b03c..8d87fbe5923 100644
--- a/storage/perfschema/unittest/stub_print_error.h
+++ b/storage/perfschema/unittest/stub_print_error.h
@@ -26,7 +26,7 @@
bool pfs_initialized= false;
-void *pfs_malloc(size_t size, myf flags)
+void *pfs_malloc(PFS_builtin_memory_class *klass, size_t size, myf flags)
{
void *ptr= malloc(size);
if (ptr && (flags & MY_ZEROFILL))
@@ -34,19 +34,27 @@ void *pfs_malloc(size_t size, myf flags)
return ptr;
}
-void pfs_free(void *ptr)
+void pfs_free(PFS_builtin_memory_class *, size_t, void *ptr)
{
if (ptr != NULL)
free(ptr);
}
-void *pfs_malloc_array(size_t n, size_t size, myf flags)
+void *pfs_malloc_array(PFS_builtin_memory_class *klass, size_t n, size_t size, myf flags)
{
size_t array_size= n * size;
/* Check for overflow before allocating. */
if (is_overflow(array_size, n, size))
return NULL;
- return pfs_malloc(array_size, flags);
+ return pfs_malloc(klass, array_size, flags);
+}
+
+void pfs_free_array(PFS_builtin_memory_class *klass, size_t n, size_t size, void *ptr)
+{
+ if (ptr == NULL)
+ return;
+ size_t array_size= n * size;
+ return pfs_free(klass, array_size, ptr);
}
bool is_overflow(size_t product, size_t n1, size_t n2)