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