List:Commits« Previous MessageNext Message »
From:Marc Alff Date:September 23 2010 4:09pm
Subject:bzr push into mysql-next-mr-wl4816 branch (marc.alff:3193 to 3194) WL#4816
View as plain text  
 3194 Marc Alff	2010-09-23
      WL#4816 PERFORMANCE SCHEMA SUMMARIES

    added:
      storage/perfschema/pfs_setup_object.cc
      storage/perfschema/pfs_setup_object.h
      storage/perfschema/table_ews_by_thread_by_event_name.cc
      storage/perfschema/table_ews_by_thread_by_event_name.h
      storage/perfschema/table_os_global_by_type.cc
      storage/perfschema/table_os_global_by_type.h
      storage/perfschema/table_setup_objects.cc
      storage/perfschema/table_setup_objects.h
      storage/perfschema/unittest/stub_pfs_defaults.h
      storage/perfschema/unittest/stub_server_misc.h
    modified:
      .bzr-mysql/default.conf
      mysql-test/suite/perfschema/include/schema.inc
      mysql-test/suite/perfschema/r/dml_setup_consumers.result
      mysql-test/suite/perfschema/r/information_schema.result
      mysql-test/suite/perfschema/r/innodb_table_io.result
      mysql-test/suite/perfschema/r/pfs_upgrade_lc0.result
      mysql-test/suite/perfschema/r/schema_lc0.result
      mysql-test/suite/perfschema/r/start_server_no_cond_class.result
      mysql-test/suite/perfschema/r/start_server_no_cond_inst.result
      mysql-test/suite/perfschema/r/start_server_no_file_class.result
      mysql-test/suite/perfschema/r/start_server_no_file_inst.result
      mysql-test/suite/perfschema/r/start_server_no_mutex_class.result
      mysql-test/suite/perfschema/r/start_server_no_mutex_inst.result
      mysql-test/suite/perfschema/r/start_server_no_rwlock_class.result
      mysql-test/suite/perfschema/r/start_server_no_rwlock_inst.result
      mysql-test/suite/perfschema/r/start_server_no_setup_actors.result
      mysql-test/suite/perfschema/r/start_server_no_table_hdl.result
      mysql-test/suite/perfschema/r/start_server_no_table_inst.result
      mysql-test/suite/perfschema/r/start_server_no_thread_class.result
      mysql-test/suite/perfschema/r/start_server_no_thread_inst.result
      mysql-test/suite/perfschema/r/start_server_nothing.result
      mysql-test/suite/perfschema/r/start_server_off.result
      mysql-test/suite/perfschema/r/start_server_on.result
      mysql-test/suite/perfschema/r/temp_table_io.result
      scripts/mysql_system_tables.sql
      sql/sql_lex.h
      sql/sys_vars.cc
      storage/perfschema/CMakeLists.txt
      storage/perfschema/Makefile.am
      storage/perfschema/pfs.cc
      storage/perfschema/pfs_defaults.cc
      storage/perfschema/pfs_engine_table.cc
      storage/perfschema/pfs_events_waits.cc
      storage/perfschema/pfs_events_waits.h
      storage/perfschema/pfs_instr.cc
      storage/perfschema/pfs_instr.h
      storage/perfschema/pfs_instr_class.cc
      storage/perfschema/pfs_instr_class.h
      storage/perfschema/pfs_server.cc
      storage/perfschema/pfs_server.h
      storage/perfschema/pfs_stat.h
      storage/perfschema/pfs_timer.cc
      storage/perfschema/pfs_timer.h
      storage/perfschema/table_all_instr.cc
      storage/perfschema/table_all_instr.h
      storage/perfschema/table_events_waits.cc
      storage/perfschema/table_events_waits.h
      storage/perfschema/table_events_waits_summary.cc
      storage/perfschema/table_events_waits_summary.h
      storage/perfschema/table_ews_global_by_event_name.cc
      storage/perfschema/table_ews_global_by_event_name.h
      storage/perfschema/table_file_summary.cc
      storage/perfschema/table_file_summary.h
      storage/perfschema/table_helper.h
      storage/perfschema/table_setup_consumers.cc
      storage/perfschema/table_setup_instruments.cc
      storage/perfschema/unittest/pfs-t.cc
      storage/perfschema/unittest/pfs_instr-oom-t.cc
      storage/perfschema/unittest/pfs_instr-t.cc
      storage/perfschema/unittest/pfs_instr_class-oom-t.cc
      storage/perfschema/unittest/pfs_instr_class-t.cc
 3193 Marc Alff	2010-09-20 [merge]
      Merge mysql-next-mr --> mysql-next-mr-wl4816

    removed:
      mysql-test/suite/perfschema/r/ddl_threads.result
      mysql-test/suite/perfschema/r/dml_threads.result
      mysql-test/suite/perfschema/t/ddl_threads.test
      mysql-test/suite/perfschema/t/dml_threads.test
      mysql-test/suite/perfschema/t/schema.test
      storage/perfschema/table_threads.cc
      storage/perfschema/table_threads.h
    added:
      mysql-test/suite/perfschema/include/schema.inc
      mysql-test/suite/perfschema/r/ddl_setup_actors.result
      mysql-test/suite/perfschema/r/ddl_threads.result
      mysql-test/suite/perfschema/r/dml_setup_actors.result
      mysql-test/suite/perfschema/r/dml_threads.result
      mysql-test/suite/perfschema/r/schema_lc0.result
      mysql-test/suite/perfschema/r/schema_lc1.result
      mysql-test/suite/perfschema/r/schema_lc2.result
      mysql-test/suite/perfschema/r/setup_actors.result
      mysql-test/suite/perfschema/r/start_server_no_setup_actors.result
      mysql-test/suite/perfschema/r/threads_events.result
      mysql-test/suite/perfschema/r/threads_innodb.result
      mysql-test/suite/perfschema/r/threads_insert_delayed.result
      mysql-test/suite/perfschema/r/threads_mysql.result
      mysql-test/suite/perfschema/t/ddl_setup_actors.test
      mysql-test/suite/perfschema/t/ddl_threads.test
      mysql-test/suite/perfschema/t/dml_setup_actors.test
      mysql-test/suite/perfschema/t/dml_threads.test
      mysql-test/suite/perfschema/t/schema_lc0.test
      mysql-test/suite/perfschema/t/schema_lc1.test
      mysql-test/suite/perfschema/t/schema_lc2.test
      mysql-test/suite/perfschema/t/setup_actors.test
      mysql-test/suite/perfschema/t/start_server_no_setup_actors-master.opt
      mysql-test/suite/perfschema/t/start_server_no_setup_actors.test
      mysql-test/suite/perfschema/t/threads_innodb.test
      mysql-test/suite/perfschema/t/threads_insert_delayed.test
      mysql-test/suite/perfschema/t/threads_mysql-master.opt
      mysql-test/suite/perfschema/t/threads_mysql.test
      mysql-test/suite/sys_vars/r/pfs_setup_actors_size_basic.result
      mysql-test/suite/sys_vars/t/pfs_setup_actors_size_basic-master.opt
      mysql-test/suite/sys_vars/t/pfs_setup_actors_size_basic.test
      storage/perfschema/pfs_defaults.cc
      storage/perfschema/pfs_defaults.h
      storage/perfschema/pfs_setup_actor.cc
      storage/perfschema/pfs_setup_actor.h
      storage/perfschema/table_setup_actors.cc
      storage/perfschema/table_setup_actors.h
      storage/perfschema/table_threads.cc
      storage/perfschema/table_threads.h
    modified:
      client/CMakeLists.txt
      include/CMakeLists.txt
      include/Makefile.am
      include/mysql/psi/psi.h
      include/mysql/psi/psi_abi_v1.h.pp
      libmysqld/lib_sql.cc
      mysql-test/r/information_schema.result
      mysql-test/r/mysqld--help-notwin.result
      mysql-test/r/mysqld--help-win.result
      mysql-test/r/sp-destruct.result
      mysql-test/suite/perfschema/include/setup_helper.inc
      mysql-test/suite/perfschema/include/start_server_common.inc
      mysql-test/suite/perfschema/r/func_file_io.result
      mysql-test/suite/perfschema/r/information_schema.result
      mysql-test/suite/perfschema/r/pfs_upgrade_lc0.result
      mysql-test/suite/perfschema/r/pfs_upgrade_lc1.result
      mysql-test/suite/perfschema/r/pfs_upgrade_lc2.result
      mysql-test/suite/perfschema/r/selects.result
      mysql-test/suite/perfschema/r/start_server_no_cond_class.result
      mysql-test/suite/perfschema/r/start_server_no_cond_inst.result
      mysql-test/suite/perfschema/r/start_server_no_file_class.result
      mysql-test/suite/perfschema/r/start_server_no_file_inst.result
      mysql-test/suite/perfschema/r/start_server_no_mutex_class.result
      mysql-test/suite/perfschema/r/start_server_no_mutex_inst.result
      mysql-test/suite/perfschema/r/start_server_no_rwlock_class.result
      mysql-test/suite/perfschema/r/start_server_no_rwlock_inst.result
      mysql-test/suite/perfschema/r/start_server_no_table_hdl.result
      mysql-test/suite/perfschema/r/start_server_no_table_inst.result
      mysql-test/suite/perfschema/r/start_server_no_thread_class.result
      mysql-test/suite/perfschema/r/start_server_no_thread_inst.result
      mysql-test/suite/perfschema/r/start_server_nothing.result
      mysql-test/suite/perfschema/r/start_server_off.result
      mysql-test/suite/perfschema/r/start_server_on.result
      mysql-test/suite/perfschema/t/disabled.def
      mysql-test/suite/perfschema/t/func_file_io.test
      mysql-test/suite/perfschema/t/selects.test
      mysql-test/suite/perfschema/t/start_server_nothing.test
      mysql-test/suite/perfschema/t/thread_cache.test
      mysql-test/t/information_schema.test
      mysql-test/t/sp-destruct.test
      scripts/CMakeLists.txt
      scripts/make_win_bin_dist
      scripts/mysql_system_tables.sql
      sql/CMakeLists.txt
      sql/event_scheduler.cc
      sql/ha_ndbcluster_binlog.cc
      sql/log.cc
      sql/mdl.cc
      sql/mdl.h
      sql/rpl_master.cc
      sql/sp.cc
      sql/sql_base.cc
      sql/sql_base.h
      sql/sql_class.cc
      sql/sql_class.h
      sql/sql_connect.cc
      sql/sql_insert.cc
      sql/sql_parse.cc
      sql/sql_prepare.cc
      sql/sql_show.cc
      sql/sql_table.cc
      sql/sys_vars.cc
      sql/table.cc
      storage/perfschema/CMakeLists.txt
      storage/perfschema/Makefile.am
      storage/perfschema/ha_perfschema.cc
      storage/perfschema/ha_perfschema.h
      storage/perfschema/pfs.cc
      storage/perfschema/pfs_engine_table.cc
      storage/perfschema/pfs_engine_table.h
      storage/perfschema/pfs_instr.cc
      storage/perfschema/pfs_instr.h
      storage/perfschema/pfs_lock.h
      storage/perfschema/pfs_server.cc
      storage/perfschema/pfs_server.h
      storage/perfschema/table_events_waits.cc
      storage/perfschema/table_events_waits.h
      storage/perfschema/table_events_waits_summary.cc
      storage/perfschema/table_events_waits_summary.h
      storage/perfschema/table_ews_global_by_event_name.cc
      storage/perfschema/table_file_instances.cc
      storage/perfschema/table_file_instances.h
      storage/perfschema/table_file_summary.cc
      storage/perfschema/table_file_summary.h
      storage/perfschema/table_performance_timers.cc
      storage/perfschema/table_setup_consumers.cc
      storage/perfschema/table_setup_instruments.cc
      storage/perfschema/table_setup_timers.cc
      storage/perfschema/table_sync_instances.cc
      storage/perfschema/table_sync_instances.h
      storage/perfschema/unittest/pfs-t.cc
      storage/perfschema/unittest/pfs_instr-oom-t.cc
      storage/perfschema/unittest/pfs_instr-t.cc
      storage/perfschema/unittest/stub_pfs_global.h
=== modified file '.bzr-mysql/default.conf'
--- a/.bzr-mysql/default.conf	2010-09-01 13:06:14 +0000
+++ b/.bzr-mysql/default.conf	2010-09-23 16:08:54 +0000
@@ -1,4 +1,4 @@
 [MYSQL]
 post_commit_to = "commits@stripped"
 post_push_to = "commits@stripped"
-tree_name = "mysql-next-mr"
+tree_name = "mysql-next-mr-wl4816"

=== modified file 'mysql-test/suite/perfschema/include/schema.inc'
--- a/mysql-test/suite/perfschema/include/schema.inc	2010-09-01 22:59:33 +0000
+++ b/mysql-test/suite/perfschema/include/schema.inc	2010-09-23 16:08:54 +0000
@@ -34,11 +34,13 @@ show create table FILE_INSTANCES;
 show create table FILE_SUMMARY_BY_EVENT_NAME;
 show create table FILE_SUMMARY_BY_INSTANCE;
 show create table MUTEX_INSTANCES;
+show create table OBJECTS_SUMMARY_GLOBAL_BY_TYPE;
 show create table PERFORMANCE_TIMERS;
 show create table RWLOCK_INSTANCES;
 show create table SETUP_ACTORS;
 show create table SETUP_CONSUMERS;
 show create table SETUP_INSTRUMENTS;
+show create table SETUP_OBJECTS;
 show create table SETUP_TIMERS;
 show create table THREADS;
 

=== modified file 'mysql-test/suite/perfschema/r/dml_setup_consumers.result'
--- a/mysql-test/suite/perfschema/r/dml_setup_consumers.result	2010-01-12 01:47:27 +0000
+++ b/mysql-test/suite/perfschema/r/dml_setup_consumers.result	2010-09-23 16:08:54 +0000
@@ -3,11 +3,8 @@ NAME	ENABLED
 events_waits_current	YES
 events_waits_history	YES
 events_waits_history_long	YES
-events_waits_summary_by_thread_by_event_name	YES
-events_waits_summary_by_event_name	YES
-events_waits_summary_by_instance	YES
-file_summary_by_event_name	YES
-file_summary_by_instance	YES
+global_instrumentation	YES
+thread_instrumentation	YES
 select * from performance_schema.SETUP_CONSUMERS
 where name='events_waits_current';
 NAME	ENABLED
@@ -18,11 +15,8 @@ NAME	ENABLED
 events_waits_current	YES
 events_waits_history	YES
 events_waits_history_long	YES
-events_waits_summary_by_thread_by_event_name	YES
-events_waits_summary_by_event_name	YES
-events_waits_summary_by_instance	YES
-file_summary_by_event_name	YES
-file_summary_by_instance	YES
+global_instrumentation	YES
+thread_instrumentation	YES
 select * from performance_schema.SETUP_CONSUMERS
 where enabled='NO';
 NAME	ENABLED

=== modified file 'mysql-test/suite/perfschema/r/information_schema.result'
--- a/mysql-test/suite/perfschema/r/information_schema.result	2010-09-01 22:59:33 +0000
+++ b/mysql-test/suite/perfschema/r/information_schema.result	2010-09-23 16:08:54 +0000
@@ -13,11 +13,13 @@ performance_schema	FILE_INSTANCES	def
 performance_schema	FILE_SUMMARY_BY_EVENT_NAME	def
 performance_schema	FILE_SUMMARY_BY_INSTANCE	def
 performance_schema	MUTEX_INSTANCES	def
+performance_schema	OBJECTS_SUMMARY_GLOBAL_BY_TYPE	def
 performance_schema	PERFORMANCE_TIMERS	def
 performance_schema	RWLOCK_INSTANCES	def
 performance_schema	SETUP_ACTORS	def
 performance_schema	SETUP_CONSUMERS	def
 performance_schema	SETUP_INSTRUMENTS	def
+performance_schema	SETUP_OBJECTS	def
 performance_schema	SETUP_TIMERS	def
 performance_schema	THREADS	def
 select upper(TABLE_NAME), TABLE_TYPE, ENGINE
@@ -35,11 +37,13 @@ FILE_INSTANCES	BASE TABLE	PERFORMANCE_SC
 FILE_SUMMARY_BY_EVENT_NAME	BASE TABLE	PERFORMANCE_SCHEMA
 FILE_SUMMARY_BY_INSTANCE	BASE TABLE	PERFORMANCE_SCHEMA
 MUTEX_INSTANCES	BASE TABLE	PERFORMANCE_SCHEMA
+OBJECTS_SUMMARY_GLOBAL_BY_TYPE	BASE TABLE	PERFORMANCE_SCHEMA
 PERFORMANCE_TIMERS	BASE TABLE	PERFORMANCE_SCHEMA
 RWLOCK_INSTANCES	BASE TABLE	PERFORMANCE_SCHEMA
 SETUP_ACTORS	BASE TABLE	PERFORMANCE_SCHEMA
 SETUP_CONSUMERS	BASE TABLE	PERFORMANCE_SCHEMA
 SETUP_INSTRUMENTS	BASE TABLE	PERFORMANCE_SCHEMA
+SETUP_OBJECTS	BASE TABLE	PERFORMANCE_SCHEMA
 SETUP_TIMERS	BASE TABLE	PERFORMANCE_SCHEMA
 THREADS	BASE TABLE	PERFORMANCE_SCHEMA
 select upper(TABLE_NAME), VERSION, ROW_FORMAT
@@ -57,11 +61,13 @@ FILE_INSTANCES	10	Dynamic
 FILE_SUMMARY_BY_EVENT_NAME	10	Dynamic
 FILE_SUMMARY_BY_INSTANCE	10	Dynamic
 MUTEX_INSTANCES	10	Dynamic
+OBJECTS_SUMMARY_GLOBAL_BY_TYPE	10	Dynamic
 PERFORMANCE_TIMERS	10	Fixed
 RWLOCK_INSTANCES	10	Dynamic
 SETUP_ACTORS	10	Fixed
 SETUP_CONSUMERS	10	Dynamic
 SETUP_INSTRUMENTS	10	Dynamic
+SETUP_OBJECTS	10	Dynamic
 SETUP_TIMERS	10	Dynamic
 THREADS	10	Dynamic
 select upper(TABLE_NAME), TABLE_ROWS, AVG_ROW_LENGTH
@@ -79,11 +85,13 @@ FILE_INSTANCES	1000	0
 FILE_SUMMARY_BY_EVENT_NAME	1000	0
 FILE_SUMMARY_BY_INSTANCE	1000	0
 MUTEX_INSTANCES	1000	0
+OBJECTS_SUMMARY_GLOBAL_BY_TYPE	1000	0
 PERFORMANCE_TIMERS	5	0
 RWLOCK_INSTANCES	1000	0
 SETUP_ACTORS	1	0
-SETUP_CONSUMERS	8	0
+SETUP_CONSUMERS	5	0
 SETUP_INSTRUMENTS	1000	0
+SETUP_OBJECTS	3	0
 SETUP_TIMERS	1	0
 THREADS	1000	0
 select upper(TABLE_NAME), DATA_LENGTH, MAX_DATA_LENGTH
@@ -101,11 +109,13 @@ FILE_INSTANCES	0	0
 FILE_SUMMARY_BY_EVENT_NAME	0	0
 FILE_SUMMARY_BY_INSTANCE	0	0
 MUTEX_INSTANCES	0	0
+OBJECTS_SUMMARY_GLOBAL_BY_TYPE	0	0
 PERFORMANCE_TIMERS	0	0
 RWLOCK_INSTANCES	0	0
 SETUP_ACTORS	0	0
 SETUP_CONSUMERS	0	0
 SETUP_INSTRUMENTS	0	0
+SETUP_OBJECTS	0	0
 SETUP_TIMERS	0	0
 THREADS	0	0
 select upper(TABLE_NAME), INDEX_LENGTH, DATA_FREE, AUTO_INCREMENT
@@ -123,11 +133,13 @@ FILE_INSTANCES	0	0	NULL
 FILE_SUMMARY_BY_EVENT_NAME	0	0	NULL
 FILE_SUMMARY_BY_INSTANCE	0	0	NULL
 MUTEX_INSTANCES	0	0	NULL
+OBJECTS_SUMMARY_GLOBAL_BY_TYPE	0	0	NULL
 PERFORMANCE_TIMERS	0	0	NULL
 RWLOCK_INSTANCES	0	0	NULL
 SETUP_ACTORS	0	0	NULL
 SETUP_CONSUMERS	0	0	NULL
 SETUP_INSTRUMENTS	0	0	NULL
+SETUP_OBJECTS	0	0	NULL
 SETUP_TIMERS	0	0	NULL
 THREADS	0	0	NULL
 select upper(TABLE_NAME), CREATE_TIME, UPDATE_TIME, CHECK_TIME
@@ -145,11 +157,13 @@ FILE_INSTANCES	NULL	NULL	NULL
 FILE_SUMMARY_BY_EVENT_NAME	NULL	NULL	NULL
 FILE_SUMMARY_BY_INSTANCE	NULL	NULL	NULL
 MUTEX_INSTANCES	NULL	NULL	NULL
+OBJECTS_SUMMARY_GLOBAL_BY_TYPE	NULL	NULL	NULL
 PERFORMANCE_TIMERS	NULL	NULL	NULL
 RWLOCK_INSTANCES	NULL	NULL	NULL
 SETUP_ACTORS	NULL	NULL	NULL
 SETUP_CONSUMERS	NULL	NULL	NULL
 SETUP_INSTRUMENTS	NULL	NULL	NULL
+SETUP_OBJECTS	NULL	NULL	NULL
 SETUP_TIMERS	NULL	NULL	NULL
 THREADS	NULL	NULL	NULL
 select upper(TABLE_NAME), TABLE_COLLATION, CHECKSUM
@@ -167,11 +181,13 @@ FILE_INSTANCES	utf8_general_ci	NULL
 FILE_SUMMARY_BY_EVENT_NAME	utf8_general_ci	NULL
 FILE_SUMMARY_BY_INSTANCE	utf8_general_ci	NULL
 MUTEX_INSTANCES	utf8_general_ci	NULL
+OBJECTS_SUMMARY_GLOBAL_BY_TYPE	utf8_general_ci	NULL
 PERFORMANCE_TIMERS	utf8_general_ci	NULL
 RWLOCK_INSTANCES	utf8_general_ci	NULL
 SETUP_ACTORS	utf8_general_ci	NULL
 SETUP_CONSUMERS	utf8_general_ci	NULL
 SETUP_INSTRUMENTS	utf8_general_ci	NULL
+SETUP_OBJECTS	utf8_general_ci	NULL
 SETUP_TIMERS	utf8_general_ci	NULL
 THREADS	utf8_general_ci	NULL
 select upper(TABLE_NAME), TABLE_COMMENT
@@ -189,10 +205,12 @@ FILE_INSTANCES
 FILE_SUMMARY_BY_EVENT_NAME	
 FILE_SUMMARY_BY_INSTANCE	
 MUTEX_INSTANCES	
+OBJECTS_SUMMARY_GLOBAL_BY_TYPE	
 PERFORMANCE_TIMERS	
 RWLOCK_INSTANCES	
 SETUP_ACTORS	
 SETUP_CONSUMERS	
 SETUP_INSTRUMENTS	
+SETUP_OBJECTS	
 SETUP_TIMERS	
 THREADS	

=== modified file 'mysql-test/suite/perfschema/r/innodb_table_io.result'
--- a/mysql-test/suite/perfschema/r/innodb_table_io.result	2010-07-13 14:17:39 +0000
+++ b/mysql-test/suite/perfschema/r/innodb_table_io.result	2010-09-23 16:08:54 +0000
@@ -106,9 +106,7 @@ wait/io/table/sql/handler	handler.cc:	TA
 wait/io/table/sql/handler	handler.cc:	TABLE	test	no_index_tab	fetch	NULL
 wait/io/table/sql/handler	handler.cc:	TABLE	test	marker	insert	NULL
 wait/io/table/sql/handler	handler.cc:	TABLE	test	no_index_tab	fetch	NULL
-wait/io/table/sql/handler	handler.cc:	TEMPORARY TABLE	test	#sql-XXXX	insert	NULL
 wait/io/table/sql/handler	handler.cc:	TABLE	test	no_index_tab	fetch	NULL
-wait/io/table/sql/handler	handler.cc:	TEMPORARY TABLE	test	#sql-XXXX	insert	NULL
 wait/io/table/sql/handler	handler.cc:	TABLE	test	no_index_tab	fetch	NULL
 wait/io/table/sql/handler	handler.cc:	TABLE	test	marker	insert	NULL
 wait/io/table/sql/handler	handler.cc:	TABLE	test	no_index_tab	fetch	NULL

=== modified file 'mysql-test/suite/perfschema/r/pfs_upgrade_lc0.result'
--- a/mysql-test/suite/perfschema/r/pfs_upgrade_lc0.result	2010-09-01 22:59:33 +0000
+++ b/mysql-test/suite/perfschema/r/pfs_upgrade_lc0.result	2010-09-23 16:08:54 +0000
@@ -19,14 +19,16 @@ ERROR 1050 (42S01) at line 180: Table 'F
 ERROR 1050 (42S01) at line 191: Table 'FILE_SUMMARY_BY_EVENT_NAME' already exists
 ERROR 1050 (42S01) at line 203: Table 'FILE_SUMMARY_BY_INSTANCE' already exists
 ERROR 1050 (42S01) at line 212: Table 'MUTEX_INSTANCES' already exists
-ERROR 1050 (42S01) at line 222: Table 'PERFORMANCE_TIMERS' already exists
-ERROR 1050 (42S01) at line 232: Table 'RWLOCK_INSTANCES' already exists
-ERROR 1050 (42S01) at line 242: Table 'SETUP_ACTORS' already exists
-ERROR 1050 (42S01) at line 250: Table 'SETUP_CONSUMERS' already exists
-ERROR 1050 (42S01) at line 259: Table 'SETUP_INSTRUMENTS' already exists
-ERROR 1050 (42S01) at line 267: Table 'SETUP_TIMERS' already exists
-ERROR 1050 (42S01) at line 287: Table 'THREADS' already exists
-ERROR 1644 (HY000) at line 703: Unexpected content found in the performance_schema database.
+ERROR 1050 (42S01) at line 226: Table 'OBJECTS_SUMMARY_GLOBAL_BY_TYPE' already exists
+ERROR 1050 (42S01) at line 236: Table 'PERFORMANCE_TIMERS' already exists
+ERROR 1050 (42S01) at line 246: Table 'RWLOCK_INSTANCES' already exists
+ERROR 1050 (42S01) at line 256: Table 'SETUP_ACTORS' already exists
+ERROR 1050 (42S01) at line 264: Table 'SETUP_CONSUMERS' already exists
+ERROR 1050 (42S01) at line 273: Table 'SETUP_INSTRUMENTS' already exists
+ERROR 1050 (42S01) at line 283: Table 'SETUP_OBJECTS' already exists
+ERROR 1050 (42S01) at line 291: Table 'SETUP_TIMERS' already exists
+ERROR 1050 (42S01) at line 311: Table 'THREADS' already exists
+ERROR 1644 (HY000) at line 727: Unexpected content found in the performance_schema database.
 FATAL ERROR: Upgrade failed
 show tables like "user_table";
 Tables_in_performance_schema (user_table)
@@ -50,14 +52,16 @@ ERROR 1050 (42S01) at line 180: Table 'F
 ERROR 1050 (42S01) at line 191: Table 'FILE_SUMMARY_BY_EVENT_NAME' already exists
 ERROR 1050 (42S01) at line 203: Table 'FILE_SUMMARY_BY_INSTANCE' already exists
 ERROR 1050 (42S01) at line 212: Table 'MUTEX_INSTANCES' already exists
-ERROR 1050 (42S01) at line 222: Table 'PERFORMANCE_TIMERS' already exists
-ERROR 1050 (42S01) at line 232: Table 'RWLOCK_INSTANCES' already exists
-ERROR 1050 (42S01) at line 242: Table 'SETUP_ACTORS' already exists
-ERROR 1050 (42S01) at line 250: Table 'SETUP_CONSUMERS' already exists
-ERROR 1050 (42S01) at line 259: Table 'SETUP_INSTRUMENTS' already exists
-ERROR 1050 (42S01) at line 267: Table 'SETUP_TIMERS' already exists
-ERROR 1050 (42S01) at line 287: Table 'THREADS' already exists
-ERROR 1644 (HY000) at line 703: Unexpected content found in the performance_schema database.
+ERROR 1050 (42S01) at line 226: Table 'OBJECTS_SUMMARY_GLOBAL_BY_TYPE' already exists
+ERROR 1050 (42S01) at line 236: Table 'PERFORMANCE_TIMERS' already exists
+ERROR 1050 (42S01) at line 246: Table 'RWLOCK_INSTANCES' already exists
+ERROR 1050 (42S01) at line 256: Table 'SETUP_ACTORS' already exists
+ERROR 1050 (42S01) at line 264: Table 'SETUP_CONSUMERS' already exists
+ERROR 1050 (42S01) at line 273: Table 'SETUP_INSTRUMENTS' already exists
+ERROR 1050 (42S01) at line 283: Table 'SETUP_OBJECTS' already exists
+ERROR 1050 (42S01) at line 291: Table 'SETUP_TIMERS' already exists
+ERROR 1050 (42S01) at line 311: Table 'THREADS' already exists
+ERROR 1644 (HY000) at line 727: Unexpected content found in the performance_schema database.
 FATAL ERROR: Upgrade failed
 show tables like "user_view";
 Tables_in_performance_schema (user_view)
@@ -79,14 +83,16 @@ ERROR 1050 (42S01) at line 180: Table 'F
 ERROR 1050 (42S01) at line 191: Table 'FILE_SUMMARY_BY_EVENT_NAME' already exists
 ERROR 1050 (42S01) at line 203: Table 'FILE_SUMMARY_BY_INSTANCE' already exists
 ERROR 1050 (42S01) at line 212: Table 'MUTEX_INSTANCES' already exists
-ERROR 1050 (42S01) at line 222: Table 'PERFORMANCE_TIMERS' already exists
-ERROR 1050 (42S01) at line 232: Table 'RWLOCK_INSTANCES' already exists
-ERROR 1050 (42S01) at line 242: Table 'SETUP_ACTORS' already exists
-ERROR 1050 (42S01) at line 250: Table 'SETUP_CONSUMERS' already exists
-ERROR 1050 (42S01) at line 259: Table 'SETUP_INSTRUMENTS' already exists
-ERROR 1050 (42S01) at line 267: Table 'SETUP_TIMERS' already exists
-ERROR 1050 (42S01) at line 287: Table 'THREADS' already exists
-ERROR 1644 (HY000) at line 703: Unexpected content found in the performance_schema database.
+ERROR 1050 (42S01) at line 226: Table 'OBJECTS_SUMMARY_GLOBAL_BY_TYPE' already exists
+ERROR 1050 (42S01) at line 236: Table 'PERFORMANCE_TIMERS' already exists
+ERROR 1050 (42S01) at line 246: Table 'RWLOCK_INSTANCES' already exists
+ERROR 1050 (42S01) at line 256: Table 'SETUP_ACTORS' already exists
+ERROR 1050 (42S01) at line 264: Table 'SETUP_CONSUMERS' already exists
+ERROR 1050 (42S01) at line 273: Table 'SETUP_INSTRUMENTS' already exists
+ERROR 1050 (42S01) at line 283: Table 'SETUP_OBJECTS' already exists
+ERROR 1050 (42S01) at line 291: Table 'SETUP_TIMERS' already exists
+ERROR 1050 (42S01) at line 311: Table 'THREADS' already exists
+ERROR 1644 (HY000) at line 727: Unexpected content found in the performance_schema database.
 FATAL ERROR: Upgrade failed
 select name from mysql.proc where db='performance_schema';
 name
@@ -108,14 +114,16 @@ ERROR 1050 (42S01) at line 180: Table 'F
 ERROR 1050 (42S01) at line 191: Table 'FILE_SUMMARY_BY_EVENT_NAME' already exists
 ERROR 1050 (42S01) at line 203: Table 'FILE_SUMMARY_BY_INSTANCE' already exists
 ERROR 1050 (42S01) at line 212: Table 'MUTEX_INSTANCES' already exists
-ERROR 1050 (42S01) at line 222: Table 'PERFORMANCE_TIMERS' already exists
-ERROR 1050 (42S01) at line 232: Table 'RWLOCK_INSTANCES' already exists
-ERROR 1050 (42S01) at line 242: Table 'SETUP_ACTORS' already exists
-ERROR 1050 (42S01) at line 250: Table 'SETUP_CONSUMERS' already exists
-ERROR 1050 (42S01) at line 259: Table 'SETUP_INSTRUMENTS' already exists
-ERROR 1050 (42S01) at line 267: Table 'SETUP_TIMERS' already exists
-ERROR 1050 (42S01) at line 287: Table 'THREADS' already exists
-ERROR 1644 (HY000) at line 703: Unexpected content found in the performance_schema database.
+ERROR 1050 (42S01) at line 226: Table 'OBJECTS_SUMMARY_GLOBAL_BY_TYPE' already exists
+ERROR 1050 (42S01) at line 236: Table 'PERFORMANCE_TIMERS' already exists
+ERROR 1050 (42S01) at line 246: Table 'RWLOCK_INSTANCES' already exists
+ERROR 1050 (42S01) at line 256: Table 'SETUP_ACTORS' already exists
+ERROR 1050 (42S01) at line 264: Table 'SETUP_CONSUMERS' already exists
+ERROR 1050 (42S01) at line 273: Table 'SETUP_INSTRUMENTS' already exists
+ERROR 1050 (42S01) at line 283: Table 'SETUP_OBJECTS' already exists
+ERROR 1050 (42S01) at line 291: Table 'SETUP_TIMERS' already exists
+ERROR 1050 (42S01) at line 311: Table 'THREADS' already exists
+ERROR 1644 (HY000) at line 727: Unexpected content found in the performance_schema database.
 FATAL ERROR: Upgrade failed
 select name from mysql.proc where db='performance_schema';
 name
@@ -137,14 +145,16 @@ ERROR 1050 (42S01) at line 180: Table 'F
 ERROR 1050 (42S01) at line 191: Table 'FILE_SUMMARY_BY_EVENT_NAME' already exists
 ERROR 1050 (42S01) at line 203: Table 'FILE_SUMMARY_BY_INSTANCE' already exists
 ERROR 1050 (42S01) at line 212: Table 'MUTEX_INSTANCES' already exists
-ERROR 1050 (42S01) at line 222: Table 'PERFORMANCE_TIMERS' already exists
-ERROR 1050 (42S01) at line 232: Table 'RWLOCK_INSTANCES' already exists
-ERROR 1050 (42S01) at line 242: Table 'SETUP_ACTORS' already exists
-ERROR 1050 (42S01) at line 250: Table 'SETUP_CONSUMERS' already exists
-ERROR 1050 (42S01) at line 259: Table 'SETUP_INSTRUMENTS' already exists
-ERROR 1050 (42S01) at line 267: Table 'SETUP_TIMERS' already exists
-ERROR 1050 (42S01) at line 287: Table 'THREADS' already exists
-ERROR 1644 (HY000) at line 703: Unexpected content found in the performance_schema database.
+ERROR 1050 (42S01) at line 226: Table 'OBJECTS_SUMMARY_GLOBAL_BY_TYPE' already exists
+ERROR 1050 (42S01) at line 236: Table 'PERFORMANCE_TIMERS' already exists
+ERROR 1050 (42S01) at line 246: Table 'RWLOCK_INSTANCES' already exists
+ERROR 1050 (42S01) at line 256: Table 'SETUP_ACTORS' already exists
+ERROR 1050 (42S01) at line 264: Table 'SETUP_CONSUMERS' already exists
+ERROR 1050 (42S01) at line 273: Table 'SETUP_INSTRUMENTS' already exists
+ERROR 1050 (42S01) at line 283: Table 'SETUP_OBJECTS' already exists
+ERROR 1050 (42S01) at line 291: Table 'SETUP_TIMERS' already exists
+ERROR 1050 (42S01) at line 311: Table 'THREADS' already exists
+ERROR 1644 (HY000) at line 727: Unexpected content found in the performance_schema database.
 FATAL ERROR: Upgrade failed
 select name from mysql.event where db='performance_schema';
 name

=== modified file 'mysql-test/suite/perfschema/r/schema_lc0.result'
--- a/mysql-test/suite/perfschema/r/schema_lc0.result	2010-09-01 22:59:33 +0000
+++ b/mysql-test/suite/perfschema/r/schema_lc0.result	2010-09-23 16:08:54 +0000
@@ -18,11 +18,13 @@ FILE_INSTANCES
 FILE_SUMMARY_BY_EVENT_NAME
 FILE_SUMMARY_BY_INSTANCE
 MUTEX_INSTANCES
+OBJECTS_SUMMARY_GLOBAL_BY_TYPE
 PERFORMANCE_TIMERS
 RWLOCK_INSTANCES
 SETUP_ACTORS
 SETUP_CONSUMERS
 SETUP_INSTRUMENTS
+SETUP_OBJECTS
 SETUP_TIMERS
 THREADS
 show create table COND_INSTANCES;
@@ -156,6 +158,18 @@ MUTEX_INSTANCES	CREATE TABLE `MUTEX_INST
   `OBJECT_INSTANCE_BEGIN` bigint(20) NOT NULL,
   `LOCKED_BY_THREAD_ID` int(11) DEFAULT NULL
 ) ENGINE=PERFORMANCE_SCHEMA DEFAULT CHARSET=utf8
+show create table OBJECTS_SUMMARY_GLOBAL_BY_TYPE;
+Table	Create Table
+OBJECTS_SUMMARY_GLOBAL_BY_TYPE	CREATE TABLE `OBJECTS_SUMMARY_GLOBAL_BY_TYPE` (
+  `OBJECT_TYPE` varchar(64) DEFAULT NULL,
+  `OBJECT_SCHEMA` varchar(64) DEFAULT NULL,
+  `OBJECT_NAME` varchar(64) DEFAULT NULL,
+  `COUNT_STAR` bigint(20) unsigned NOT NULL,
+  `SUM_TIMER_WAIT` bigint(20) unsigned NOT NULL,
+  `MIN_TIMER_WAIT` bigint(20) unsigned NOT NULL,
+  `AVG_TIMER_WAIT` bigint(20) unsigned NOT NULL,
+  `MAX_TIMER_WAIT` bigint(20) unsigned NOT NULL
+) ENGINE=PERFORMANCE_SCHEMA DEFAULT CHARSET=utf8
 show create table PERFORMANCE_TIMERS;
 Table	Create Table
 PERFORMANCE_TIMERS	CREATE TABLE `PERFORMANCE_TIMERS` (
@@ -192,6 +206,14 @@ SETUP_INSTRUMENTS	CREATE TABLE `SETUP_IN
   `ENABLED` enum('YES','NO') NOT NULL,
   `TIMED` enum('YES','NO') NOT NULL
 ) ENGINE=PERFORMANCE_SCHEMA DEFAULT CHARSET=utf8
+show create table SETUP_OBJECTS;
+Table	Create Table
+SETUP_OBJECTS	CREATE TABLE `SETUP_OBJECTS` (
+  `OBJECT_TYPE` enum('TABLE') NOT NULL DEFAULT 'TABLE',
+  `OBJECT_SCHEMA` varchar(64) DEFAULT '%',
+  `OBJECT_NAME` varchar(64) NOT NULL DEFAULT '%',
+  `TIMED` enum('YES','NO') NOT NULL DEFAULT 'YES'
+) ENGINE=PERFORMANCE_SCHEMA DEFAULT CHARSET=utf8
 show create table SETUP_TIMERS;
 Table	Create Table
 SETUP_TIMERS	CREATE TABLE `SETUP_TIMERS` (

=== modified file 'mysql-test/suite/perfschema/r/start_server_no_cond_class.result'
--- a/mysql-test/suite/perfschema/r/start_server_no_cond_class.result	2010-09-01 22:59:33 +0000
+++ b/mysql-test/suite/perfschema/r/start_server_no_cond_class.result	2010-09-23 16:08:54 +0000
@@ -10,7 +10,7 @@ count(*)
 5
 select count(*) from performance_schema.SETUP_CONSUMERS;
 count(*)
-8
+5
 select count(*) > 1 from performance_schema.SETUP_INSTRUMENTS;
 count(*) > 1
 1
@@ -54,6 +54,7 @@ performance_schema_max_table_instances	1
 performance_schema_max_thread_classes	50
 performance_schema_max_thread_instances	1000
 performance_schema_setup_actors_size	100
+performance_schema_setup_objects_size	100
 show engine PERFORMANCE_SCHEMA status;
 show status like "performance_schema%";
 show variables like "performance_schema_max_cond_classes";

=== modified file 'mysql-test/suite/perfschema/r/start_server_no_cond_inst.result'
--- a/mysql-test/suite/perfschema/r/start_server_no_cond_inst.result	2010-09-01 22:59:33 +0000
+++ b/mysql-test/suite/perfschema/r/start_server_no_cond_inst.result	2010-09-23 16:08:54 +0000
@@ -10,7 +10,7 @@ count(*)
 5
 select count(*) from performance_schema.SETUP_CONSUMERS;
 count(*)
-8
+5
 select count(*) > 1 from performance_schema.SETUP_INSTRUMENTS;
 count(*) > 1
 1
@@ -54,6 +54,7 @@ performance_schema_max_table_instances	1
 performance_schema_max_thread_classes	50
 performance_schema_max_thread_instances	1000
 performance_schema_setup_actors_size	100
+performance_schema_setup_objects_size	100
 show engine PERFORMANCE_SCHEMA status;
 show status like "performance_schema%";
 show variables like "performance_schema_max_cond_classes";

=== modified file 'mysql-test/suite/perfschema/r/start_server_no_file_class.result'
--- a/mysql-test/suite/perfschema/r/start_server_no_file_class.result	2010-09-01 22:59:33 +0000
+++ b/mysql-test/suite/perfschema/r/start_server_no_file_class.result	2010-09-23 16:08:54 +0000
@@ -10,7 +10,7 @@ count(*)
 5
 select count(*) from performance_schema.SETUP_CONSUMERS;
 count(*)
-8
+5
 select count(*) > 1 from performance_schema.SETUP_INSTRUMENTS;
 count(*) > 1
 1
@@ -54,6 +54,7 @@ performance_schema_max_table_instances	1
 performance_schema_max_thread_classes	50
 performance_schema_max_thread_instances	1000
 performance_schema_setup_actors_size	100
+performance_schema_setup_objects_size	100
 show engine PERFORMANCE_SCHEMA status;
 show status like "performance_schema%";
 show variables like "performance_schema_max_file_classes";

=== modified file 'mysql-test/suite/perfschema/r/start_server_no_file_inst.result'
--- a/mysql-test/suite/perfschema/r/start_server_no_file_inst.result	2010-09-01 22:59:33 +0000
+++ b/mysql-test/suite/perfschema/r/start_server_no_file_inst.result	2010-09-23 16:08:54 +0000
@@ -10,7 +10,7 @@ count(*)
 5
 select count(*) from performance_schema.SETUP_CONSUMERS;
 count(*)
-8
+5
 select count(*) > 1 from performance_schema.SETUP_INSTRUMENTS;
 count(*) > 1
 1
@@ -54,6 +54,7 @@ performance_schema_max_table_instances	1
 performance_schema_max_thread_classes	50
 performance_schema_max_thread_instances	1000
 performance_schema_setup_actors_size	100
+performance_schema_setup_objects_size	100
 show engine PERFORMANCE_SCHEMA status;
 show status like "performance_schema%";
 show variables like "performance_schema_max_file_classes";

=== modified file 'mysql-test/suite/perfschema/r/start_server_no_mutex_class.result'
--- a/mysql-test/suite/perfschema/r/start_server_no_mutex_class.result	2010-09-01 22:59:33 +0000
+++ b/mysql-test/suite/perfschema/r/start_server_no_mutex_class.result	2010-09-23 16:08:54 +0000
@@ -10,7 +10,7 @@ count(*)
 5
 select count(*) from performance_schema.SETUP_CONSUMERS;
 count(*)
-8
+5
 select count(*) > 1 from performance_schema.SETUP_INSTRUMENTS;
 count(*) > 1
 1
@@ -54,6 +54,7 @@ performance_schema_max_table_instances	1
 performance_schema_max_thread_classes	50
 performance_schema_max_thread_instances	1000
 performance_schema_setup_actors_size	100
+performance_schema_setup_objects_size	100
 show engine PERFORMANCE_SCHEMA status;
 show status like "performance_schema%";
 show variables like "performance_schema_max_mutex_classes";

=== modified file 'mysql-test/suite/perfschema/r/start_server_no_mutex_inst.result'
--- a/mysql-test/suite/perfschema/r/start_server_no_mutex_inst.result	2010-09-01 22:59:33 +0000
+++ b/mysql-test/suite/perfschema/r/start_server_no_mutex_inst.result	2010-09-23 16:08:54 +0000
@@ -10,7 +10,7 @@ count(*)
 5
 select count(*) from performance_schema.SETUP_CONSUMERS;
 count(*)
-8
+5
 select count(*) > 1 from performance_schema.SETUP_INSTRUMENTS;
 count(*) > 1
 1
@@ -54,6 +54,7 @@ performance_schema_max_table_instances	1
 performance_schema_max_thread_classes	50
 performance_schema_max_thread_instances	1000
 performance_schema_setup_actors_size	100
+performance_schema_setup_objects_size	100
 show engine PERFORMANCE_SCHEMA status;
 show status like "performance_schema%";
 show variables like "performance_schema_max_mutex_classes";

=== modified file 'mysql-test/suite/perfschema/r/start_server_no_rwlock_class.result'
--- a/mysql-test/suite/perfschema/r/start_server_no_rwlock_class.result	2010-09-01 22:59:33 +0000
+++ b/mysql-test/suite/perfschema/r/start_server_no_rwlock_class.result	2010-09-23 16:08:54 +0000
@@ -10,7 +10,7 @@ count(*)
 5
 select count(*) from performance_schema.SETUP_CONSUMERS;
 count(*)
-8
+5
 select count(*) > 1 from performance_schema.SETUP_INSTRUMENTS;
 count(*) > 1
 1
@@ -54,6 +54,7 @@ performance_schema_max_table_instances	1
 performance_schema_max_thread_classes	50
 performance_schema_max_thread_instances	1000
 performance_schema_setup_actors_size	100
+performance_schema_setup_objects_size	100
 show engine PERFORMANCE_SCHEMA status;
 show status like "performance_schema%";
 show variables like "performance_schema_max_rwlock_classes";

=== modified file 'mysql-test/suite/perfschema/r/start_server_no_rwlock_inst.result'
--- a/mysql-test/suite/perfschema/r/start_server_no_rwlock_inst.result	2010-09-01 22:59:33 +0000
+++ b/mysql-test/suite/perfschema/r/start_server_no_rwlock_inst.result	2010-09-23 16:08:54 +0000
@@ -10,7 +10,7 @@ count(*)
 5
 select count(*) from performance_schema.SETUP_CONSUMERS;
 count(*)
-8
+5
 select count(*) > 1 from performance_schema.SETUP_INSTRUMENTS;
 count(*) > 1
 1
@@ -54,6 +54,7 @@ performance_schema_max_table_instances	1
 performance_schema_max_thread_classes	50
 performance_schema_max_thread_instances	1000
 performance_schema_setup_actors_size	100
+performance_schema_setup_objects_size	100
 show engine PERFORMANCE_SCHEMA status;
 show status like "performance_schema%";
 show variables like "performance_schema_max_rwlock_classes";

=== modified file 'mysql-test/suite/perfschema/r/start_server_no_setup_actors.result'
--- a/mysql-test/suite/perfschema/r/start_server_no_setup_actors.result	2010-09-01 22:59:33 +0000
+++ b/mysql-test/suite/perfschema/r/start_server_no_setup_actors.result	2010-09-23 16:08:54 +0000
@@ -10,7 +10,7 @@ count(*)
 5
 select count(*) from performance_schema.SETUP_CONSUMERS;
 count(*)
-8
+5
 select count(*) > 1 from performance_schema.SETUP_INSTRUMENTS;
 count(*) > 1
 1
@@ -54,6 +54,7 @@ performance_schema_max_table_instances	1
 performance_schema_max_thread_classes	50
 performance_schema_max_thread_instances	1000
 performance_schema_setup_actors_size	0
+performance_schema_setup_objects_size	100
 show engine PERFORMANCE_SCHEMA status;
 show status like "performance_schema%";
 show variables like "performance_schema_setup_actors_size";

=== modified file 'mysql-test/suite/perfschema/r/start_server_no_table_hdl.result'
--- a/mysql-test/suite/perfschema/r/start_server_no_table_hdl.result	2010-09-01 22:59:33 +0000
+++ b/mysql-test/suite/perfschema/r/start_server_no_table_hdl.result	2010-09-23 16:08:54 +0000
@@ -10,7 +10,7 @@ count(*)
 5
 select count(*) from performance_schema.SETUP_CONSUMERS;
 count(*)
-8
+5
 select count(*) > 1 from performance_schema.SETUP_INSTRUMENTS;
 count(*) > 1
 1
@@ -54,6 +54,7 @@ performance_schema_max_table_instances	1
 performance_schema_max_thread_classes	50
 performance_schema_max_thread_instances	1000
 performance_schema_setup_actors_size	100
+performance_schema_setup_objects_size	100
 show engine PERFORMANCE_SCHEMA status;
 show status like "performance_schema%";
 show variables like "performance_schema_max_table_instances";

=== modified file 'mysql-test/suite/perfschema/r/start_server_no_table_inst.result'
--- a/mysql-test/suite/perfschema/r/start_server_no_table_inst.result	2010-09-01 22:59:33 +0000
+++ b/mysql-test/suite/perfschema/r/start_server_no_table_inst.result	2010-09-23 16:08:54 +0000
@@ -10,7 +10,7 @@ count(*)
 5
 select count(*) from performance_schema.SETUP_CONSUMERS;
 count(*)
-8
+5
 select count(*) > 1 from performance_schema.SETUP_INSTRUMENTS;
 count(*) > 1
 1
@@ -54,6 +54,7 @@ performance_schema_max_table_instances	0
 performance_schema_max_thread_classes	50
 performance_schema_max_thread_instances	1000
 performance_schema_setup_actors_size	100
+performance_schema_setup_objects_size	100
 show engine PERFORMANCE_SCHEMA status;
 show status like "performance_schema%";
 show variables like "performance_schema_max_table_instances";

=== modified file 'mysql-test/suite/perfschema/r/start_server_no_thread_class.result'
--- a/mysql-test/suite/perfschema/r/start_server_no_thread_class.result	2010-09-01 22:59:33 +0000
+++ b/mysql-test/suite/perfschema/r/start_server_no_thread_class.result	2010-09-23 16:08:54 +0000
@@ -10,7 +10,7 @@ count(*)
 5
 select count(*) from performance_schema.SETUP_CONSUMERS;
 count(*)
-8
+5
 select count(*) > 1 from performance_schema.SETUP_INSTRUMENTS;
 count(*) > 1
 1
@@ -54,6 +54,7 @@ performance_schema_max_table_instances	1
 performance_schema_max_thread_classes	0
 performance_schema_max_thread_instances	1000
 performance_schema_setup_actors_size	100
+performance_schema_setup_objects_size	100
 show engine PERFORMANCE_SCHEMA status;
 show status like "performance_schema%";
 show variables like "performance_schema_max_thread_classes";

=== modified file 'mysql-test/suite/perfschema/r/start_server_no_thread_inst.result'
--- a/mysql-test/suite/perfschema/r/start_server_no_thread_inst.result	2010-09-01 22:59:33 +0000
+++ b/mysql-test/suite/perfschema/r/start_server_no_thread_inst.result	2010-09-23 16:08:54 +0000
@@ -10,7 +10,7 @@ count(*)
 5
 select count(*) from performance_schema.SETUP_CONSUMERS;
 count(*)
-8
+5
 select count(*) > 1 from performance_schema.SETUP_INSTRUMENTS;
 count(*) > 1
 1
@@ -54,6 +54,7 @@ performance_schema_max_table_instances	1
 performance_schema_max_thread_classes	50
 performance_schema_max_thread_instances	0
 performance_schema_setup_actors_size	100
+performance_schema_setup_objects_size	100
 show engine PERFORMANCE_SCHEMA status;
 show status like "performance_schema%";
 show variables like "performance_schema_max_thread_classes";

=== modified file 'mysql-test/suite/perfschema/r/start_server_nothing.result'
--- a/mysql-test/suite/perfschema/r/start_server_nothing.result	2010-09-01 22:59:33 +0000
+++ b/mysql-test/suite/perfschema/r/start_server_nothing.result	2010-09-23 16:08:54 +0000
@@ -10,7 +10,7 @@ count(*)
 5
 select count(*) from performance_schema.SETUP_CONSUMERS;
 count(*)
-8
+5
 select count(*) > 1 from performance_schema.SETUP_INSTRUMENTS;
 count(*) > 1
 0
@@ -54,6 +54,7 @@ performance_schema_max_table_instances	0
 performance_schema_max_thread_classes	0
 performance_schema_max_thread_instances	0
 performance_schema_setup_actors_size	0
+performance_schema_setup_objects_size	0
 show engine PERFORMANCE_SCHEMA status;
 show status like "performance_schema%";
 show variables like "performance_schema%";
@@ -75,6 +76,7 @@ performance_schema_max_table_instances	0
 performance_schema_max_thread_classes	0
 performance_schema_max_thread_instances	0
 performance_schema_setup_actors_size	0
+performance_schema_setup_objects_size	0
 select * from performance_schema.SETUP_INSTRUMENTS;
 NAME	ENABLED	TIMED
 wait/io/table/sql/handler	YES	YES
@@ -90,11 +92,8 @@ NAME	ENABLED
 events_waits_current	YES
 events_waits_history	YES
 events_waits_history_long	YES
-events_waits_summary_by_thread_by_event_name	YES
-events_waits_summary_by_event_name	YES
-events_waits_summary_by_instance	YES
-file_summary_by_event_name	YES
-file_summary_by_instance	YES
+global_instrumentation	YES
+thread_instrumentation	YES
 select * from performance_schema.SETUP_TIMERS;
 NAME	TIMER_NAME
 wait	CYCLE
@@ -112,6 +111,7 @@ select * from performance_schema.EVENTS_
 THREAD_ID	EVENT_NAME	COUNT_STAR	SUM_TIMER_WAIT	MIN_TIMER_WAIT	AVG_TIMER_WAIT	MAX_TIMER_WAIT
 select * from performance_schema.EVENTS_WAITS_SUMMARY_GLOBAL_BY_EVENT_NAME;
 EVENT_NAME	COUNT_STAR	SUM_TIMER_WAIT	MIN_TIMER_WAIT	AVG_TIMER_WAIT	MAX_TIMER_WAIT
+wait/io/table/sql/handler	0	0	0	0	0
 select * from performance_schema.FILE_INSTANCES;
 FILE_NAME	EVENT_NAME	OPEN_COUNT
 select * from performance_schema.FILE_SUMMARY_BY_EVENT_NAME;

=== modified file 'mysql-test/suite/perfschema/r/start_server_off.result'
--- a/mysql-test/suite/perfschema/r/start_server_off.result	2010-09-01 22:59:33 +0000
+++ b/mysql-test/suite/perfschema/r/start_server_off.result	2010-09-23 16:08:54 +0000
@@ -10,7 +10,7 @@ count(*)
 5
 select count(*) from performance_schema.SETUP_CONSUMERS;
 count(*)
-8
+5
 select count(*) > 1 from performance_schema.SETUP_INSTRUMENTS;
 count(*) > 1
 0
@@ -54,6 +54,7 @@ performance_schema_max_table_instances	1
 performance_schema_max_thread_classes	50
 performance_schema_max_thread_instances	1000
 performance_schema_setup_actors_size	100
+performance_schema_setup_objects_size	100
 show engine PERFORMANCE_SCHEMA status;
 show status like "performance_schema%";
 show status like "performance_schema%";

=== modified file 'mysql-test/suite/perfschema/r/start_server_on.result'
--- a/mysql-test/suite/perfschema/r/start_server_on.result	2010-09-01 22:59:33 +0000
+++ b/mysql-test/suite/perfschema/r/start_server_on.result	2010-09-23 16:08:54 +0000
@@ -10,7 +10,7 @@ count(*)
 5
 select count(*) from performance_schema.SETUP_CONSUMERS;
 count(*)
-8
+5
 select count(*) > 1 from performance_schema.SETUP_INSTRUMENTS;
 count(*) > 1
 1
@@ -54,6 +54,7 @@ performance_schema_max_table_instances	1
 performance_schema_max_thread_classes	50
 performance_schema_max_thread_instances	1000
 performance_schema_setup_actors_size	100
+performance_schema_setup_objects_size	100
 show engine PERFORMANCE_SCHEMA status;
 show status like "performance_schema%";
 show status like "performance_schema%";

=== modified file 'mysql-test/suite/perfschema/r/temp_table_io.result'
--- a/mysql-test/suite/perfschema/r/temp_table_io.result	2010-07-13 14:17:39 +0000
+++ b/mysql-test/suite/perfschema/r/temp_table_io.result	2010-09-23 16:08:54 +0000
@@ -72,42 +72,15 @@ event_name	short_source	object_type	obje
 wait/io/table/sql/handler	handler.cc:	TABLE	test	marker	insert	NULL
 wait/io/table/sql/handler	handler.cc:	TABLE	test	marker	insert	NULL
 wait/io/table/sql/handler	handler.cc:	TABLE	test	marker	insert	NULL
-wait/io/table/sql/handler	handler.cc:	TEMPORARY TABLE	test	no_index_tab	insert	NULL
 wait/io/table/sql/handler	handler.cc:	TABLE	test	marker	insert	NULL
-wait/io/table/sql/handler	handler.cc:	TEMPORARY TABLE	test	no_index_tab	insert	NULL
 wait/io/table/sql/handler	handler.cc:	TABLE	test	marker	insert	NULL
-wait/io/table/sql/handler	handler.cc:	TEMPORARY TABLE	test	no_index_tab	insert	NULL
 wait/io/table/sql/handler	handler.cc:	TABLE	test	marker	insert	NULL
-wait/io/table/sql/handler	handler.cc:	TEMPORARY TABLE	test	no_index_tab	fetch	NULL
-wait/io/table/sql/handler	handler.cc:	TEMPORARY TABLE	test	no_index_tab	fetch	NULL
-wait/io/table/sql/handler	handler.cc:	TEMPORARY TABLE	test	no_index_tab	fetch	NULL
-wait/io/table/sql/handler	handler.cc:	TEMPORARY TABLE	test	no_index_tab	fetch	NULL
-wait/io/table/sql/handler	handler.cc:	TABLE	test	marker	insert	NULL
-wait/io/table/sql/handler	handler.cc:	TEMPORARY TABLE	test	no_index_tab	fetch	NULL
-wait/io/table/sql/handler	handler.cc:	TEMPORARY TABLE	test	no_index_tab	update	NULL
-wait/io/table/sql/handler	handler.cc:	TEMPORARY TABLE	test	no_index_tab	fetch	NULL
-wait/io/table/sql/handler	handler.cc:	TEMPORARY TABLE	test	no_index_tab	update	NULL
-wait/io/table/sql/handler	handler.cc:	TEMPORARY TABLE	test	no_index_tab	fetch	NULL
-wait/io/table/sql/handler	handler.cc:	TEMPORARY TABLE	test	no_index_tab	update	NULL
-wait/io/table/sql/handler	handler.cc:	TEMPORARY TABLE	test	no_index_tab	fetch	NULL
-wait/io/table/sql/handler	handler.cc:	TABLE	test	marker	insert	NULL
-wait/io/table/sql/handler	handler.cc:	TEMPORARY TABLE	test	no_index_tab	fetch	NULL
-wait/io/table/sql/handler	handler.cc:	TEMPORARY TABLE	test	no_index_tab	fetch	NULL
-wait/io/table/sql/handler	handler.cc:	TABLE	test	marker	insert	NULL
-wait/io/table/sql/handler	handler.cc:	TEMPORARY TABLE	test	no_index_tab	fetch	NULL
-wait/io/table/sql/handler	handler.cc:	TEMPORARY TABLE	test	no_index_tab	fetch	NULL
-wait/io/table/sql/handler	handler.cc:	TEMPORARY TABLE	test	no_index_tab	fetch	NULL
-wait/io/table/sql/handler	handler.cc:	TEMPORARY TABLE	test	no_index_tab	delete	NULL
-wait/io/table/sql/handler	handler.cc:	TEMPORARY TABLE	test	no_index_tab	fetch	NULL
-wait/io/table/sql/handler	handler.cc:	TABLE	test	marker	insert	NULL
-wait/io/table/sql/handler	handler.cc:	TEMPORARY TABLE	test	no_index_tab	fetch	NULL
-wait/io/table/sql/handler	handler.cc:	TEMPORARY TABLE	test	no_index_tab	fetch	NULL
-wait/io/table/sql/handler	handler.cc:	TEMPORARY TABLE	test	no_index_tab	fetch	NULL
-wait/io/table/sql/handler	handler.cc:	TABLE	test	marker	insert	NULL
-wait/io/table/sql/handler	handler.cc:	TABLE	test	marker	insert	NULL
-wait/io/table/sql/handler	handler.cc:	TEMPORARY TABLE	test	no_index_tab	fetch	NULL
-wait/io/table/sql/handler	handler.cc:	TEMPORARY TABLE	test	no_index_tab	fetch	NULL
-wait/io/table/sql/handler	handler.cc:	TEMPORARY TABLE	test	no_index_tab	fetch	NULL
+wait/io/table/sql/handler	handler.cc:	TABLE	test	marker	insert	NULL
+wait/io/table/sql/handler	handler.cc:	TABLE	test	marker	insert	NULL
+wait/io/table/sql/handler	handler.cc:	TABLE	test	marker	insert	NULL
+wait/io/table/sql/handler	handler.cc:	TABLE	test	marker	insert	NULL
+wait/io/table/sql/handler	handler.cc:	TABLE	test	marker	insert	NULL
+wait/io/table/sql/handler	handler.cc:	TABLE	test	marker	insert	NULL
 wait/io/table/sql/handler	handler.cc:	TABLE	test	marker	insert	NULL
 wait/io/table/sql/handler	handler.cc:	TABLE	test	marker	insert	NULL
 show status like 'performance_schema_%';

=== modified file 'scripts/mysql_system_tables.sql'
--- a/scripts/mysql_system_tables.sql	2010-09-01 22:59:33 +0000
+++ b/scripts/mysql_system_tables.sql	2010-09-23 16:08:54 +0000
@@ -385,6 +385,26 @@ EXECUTE stmt;
 DROP PREPARE stmt;
 
 --
+-- TABLE OBJECTS_SUMMARY_GLOBAL_BY_TYPE
+--
+
+SET @cmd="CREATE TABLE performance_schema.OBJECTS_SUMMARY_GLOBAL_BY_TYPE("
+  "OBJECT_TYPE VARCHAR(64),"
+  "OBJECT_SCHEMA VARCHAR(64),"
+  "OBJECT_NAME VARCHAR(64),"
+  "COUNT_STAR BIGINT unsigned not null,"
+  "SUM_TIMER_WAIT BIGINT unsigned not null,"
+  "MIN_TIMER_WAIT BIGINT unsigned not null,"
+  "AVG_TIMER_WAIT BIGINT unsigned not null,"
+  "MAX_TIMER_WAIT BIGINT unsigned not null"
+  ")ENGINE=PERFORMANCE_SCHEMA;";
+
+SET @str = IF(@have_pfs = 1, @cmd, 'SET @dummy = 0');
+PREPARE stmt FROM @str;
+EXECUTE stmt;
+DROP PREPARE stmt;
+
+--
 -- TABLE PERFORMANCE_TIMERS
 --
 
@@ -458,6 +478,22 @@ SET @cmd="CREATE TABLE performance_schem
   ")ENGINE=PERFORMANCE_SCHEMA;";
 
 SET @str = IF(@have_pfs = 1, @cmd, 'SET @dummy = 0');
+PREPARE stmt FROM @str;
+EXECUTE stmt;
+DROP PREPARE stmt;
+
+--
+-- TABLE SETUP_OBJECTS
+--
+
+SET @cmd="CREATE TABLE performance_schema.SETUP_OBJECTS("
+  "OBJECT_TYPE ENUM ('TABLE') not null default 'TABLE',"
+  "OBJECT_SCHEMA VARCHAR(64) default '%',"
+  "OBJECT_NAME VARCHAR(64) not null default '%',"
+  "TIMED ENUM ('YES', 'NO') not null default 'YES'"
+  ")ENGINE=PERFORMANCE_SCHEMA;";
+
+SET @str = IF(@have_pfs = 1, @cmd, 'SET @dummy = 0');
 PREPARE stmt FROM @str;
 EXECUTE stmt;
 DROP PREPARE stmt;

=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h	2010-08-30 08:40:42 +0000
+++ b/sql/sql_lex.h	2010-09-23 16:08:54 +0000
@@ -763,7 +763,8 @@ public:
   inline st_select_lex* last_select() 
   { 
     st_select_lex* mylast= this;
-    for (; mylast->next_select(); mylast= mylast->next_select());
+    for (; mylast->next_select(); mylast= mylast->next_select())
+    {}
     return mylast; 
   }
 

=== modified file 'sql/sys_vars.cc'
--- a/sql/sys_vars.cc	2010-09-01 22:59:33 +0000
+++ b/sql/sys_vars.cc	2010-09-23 16:08:54 +0000
@@ -205,6 +205,14 @@ static Sys_var_ulong Sys_pfs_setup_actor
        DEFAULT(PFS_MAX_SETUP_ACTOR),
        BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);
 
+static Sys_var_ulong Sys_pfs_setup_objects_size(
+       "performance_schema_setup_objects_size",
+       "Maximum number of rows in SETUP_OBJECTS.",
+       READ_ONLY GLOBAL_VAR(pfs_param.m_setup_object_sizing),
+       CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 1024*1024),
+       DEFAULT(PFS_MAX_SETUP_OBJECT),
+       BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);
+
 #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
 
 static Sys_var_ulong Sys_auto_increment_increment(

=== modified file 'storage/perfschema/CMakeLists.txt'
--- a/storage/perfschema/CMakeLists.txt	2010-09-01 22:59:33 +0000
+++ b/storage/perfschema/CMakeLists.txt	2010-09-23 16:08:54 +0000
@@ -34,20 +34,24 @@ SET(PERFSCHEMA_SOURCES ha_perfschema.h
   pfs_atomic.h
   pfs_server.h
   pfs_setup_actor.h
+  pfs_setup_object.h
   pfs_stat.h
   pfs_engine_table.h
   pfs_timer.h
   table_all_instr.h
   table_events_waits.h
   table_events_waits_summary.h
+  table_ews_by_thread_by_event_name.h
   table_ews_global_by_event_name.h
   table_file_instances.h
   table_file_summary.h
   table_helper.h
+  table_os_global_by_type.h
   table_performance_timers.h
   table_setup_actors.h
   table_setup_consumers.h
   table_setup_instruments.h
+  table_setup_objects.h
   table_setup_timers.h
   table_sync_instances.h
   table_threads.h
@@ -61,18 +65,23 @@ SET(PERFSCHEMA_SOURCES ha_perfschema.h
   pfs_instr_class.cc
   pfs_server.cc
   pfs_setup_actor.cc
+  pfs_setup_object.cc
   pfs_engine_table.cc
   pfs_timer.cc
   table_all_instr.cc
   table_events_waits.cc
   table_events_waits_summary.cc
+  table_ews_by_thread_by_event_name.cc
   table_ews_global_by_event_name.cc
   table_file_instances.cc
   table_file_summary.cc
+  table_helper.cc
+  table_os_global_by_type.cc
   table_performance_timers.cc
   table_setup_actors.cc
   table_setup_consumers.cc
   table_setup_instruments.cc
+  table_setup_objects.cc
   table_setup_timers.cc
   table_sync_instances.cc
   table_threads.cc

=== modified file 'storage/perfschema/Makefile.am'
--- a/storage/perfschema/Makefile.am	2010-09-01 22:59:33 +0000
+++ b/storage/perfschema/Makefile.am	2010-09-23 16:08:54 +0000
@@ -45,7 +45,9 @@ noinst_HEADERS = ha_perfschema.h pfs_eng
 		table_ews_global_by_event_name.h table_all_instr.h \
 		table_file_instances.h table_file_summary.h \
 		pfs_lock.h pfs_atomic.h \
-		pfs_setup_actor.h pfs_defaults.h
+		pfs_setup_actor.h pfs_defaults.h \
+		pfs_setup_objects.h table_setup_objects.h table_helper.cc \
+		table_ews_by_thread_by_event_name.h table_os_global_by_type.h
 
 PSE_SOURCES = ha_perfschema.cc pfs_engine_table.cc pfs.cc pfs_server.cc \
 		pfs_global.cc pfs_instr_class.cc pfs_instr.cc \
@@ -59,7 +61,9 @@ PSE_SOURCES = ha_perfschema.cc pfs_engin
 		table_ews_global_by_event_name.cc table_all_instr.cc \
 		table_file_instances.cc table_file_summary.cc \
 		pfs_atomic.cc pfs_check.cc \
-		pfs_setup_actor.cc pfs_defaults.cc
+		pfs_setup_actor.cc pfs_defaults.cc \
+		pfs_setup_object.cc table_setup_objects.cc \
+		table_ews_by_thread_by_event_name.cc table_os_global_by_type.cc
 
 EXTRA_LIBRARIES = libperfschema.a
 noinst_LIBRARIES = @plugin_perfschema_static_target@

=== modified file 'storage/perfschema/pfs.cc'
--- a/storage/perfschema/pfs.cc	2010-09-01 22:59:33 +0000
+++ b/storage/perfschema/pfs.cc	2010-09-23 16:08:54 +0000
@@ -29,6 +29,7 @@
 #include "pfs_timer.h"
 #include "pfs_events_waits.h"
 #include "pfs_setup_actor.h"
+#include "pfs_setup_object.h"
 
 /**
   @page PAGE_PERFORMANCE_SCHEMA The Performance Schema main page
@@ -654,10 +655,35 @@ static inline int mysql_mutex_lock(...)
   This is necessary because the data the aggregate is based on is volatile,
   and can not be kept indefinitely.
 
+  With on the fly aggregates:
+  - the writer thread does all the computation
+  - the reader thread accesses the result directly
+
+  This model is to be avoided if possible, due to the overhead
+  caused when instrumenting code.
+
   @section HIGHER_LEVEL Higher level aggregates
 
-  Note: no higher level aggregate is implemented yet,
-  this section is a place holder.
+  'Higher level' aggregates are implemented on demand only.
+  The code executing a SELECT from the aggregate table is
+  collecting data from multiple internal buffers to produce the result.
+
+  With higher level aggregates:
+  - the reader thread does all the computation
+  - the writer thread has no overhead.
+
+  @section MIXED Mixed level aggregates
+
+  The 'Mixed' model is a compromise between 'On the fly' and 'Higher level'
+  aggregates, for internal buffers that are not permanent.
+
+  While an object is present in a buffer, the higher level model is used.
+  When an object is about to be destroyed, statistics are saved into
+  a 'parent' buffer with a longer life cycle, to follow the on the fly model.
+
+  With mixed aggregates:
+  - the reader thread does a lot of complex computation,
+  - the writer thread has minimal overhead, on destroy events.
 */
 
 /**
@@ -673,6 +699,10 @@ static inline int mysql_mutex_lock(...)
   @ingroup Performance_schema_implementation
 */
 
+#define STATE_FLAG_TIMED (1<<0)
+#define STATE_FLAG_THREAD (1<<1)
+#define STATE_FLAG_WAIT (1<<2)
+
 pthread_key(PFS_thread*, THR_PFS);
 bool THR_PFS_initialized= false;
 
@@ -735,6 +765,27 @@ static enum_operation_type table_operati
   OPERATION_TYPE_TABLE_DELETE_ROW
 };
 
+static void aggregate_table(PFS_table *pfs)
+{
+  DBUG_ASSERT(pfs);
+  PFS_table_share *table_share= pfs->m_share;
+  DBUG_ASSERT(table_share);
+
+  /* Aggregate to EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME */
+  PFS_thread *thread= pfs->m_opening_thread;
+  DBUG_ASSERT(thread != NULL);
+  PFS_single_stat *event_name_array;
+  uint index;
+  event_name_array= thread->m_instr_class_wait_stats;
+
+  index= global_table_io_class.m_event_name_index;
+  pfs->m_table_stat.sum_io(& event_name_array[index]);
+
+  /* Aggregate to TABLE_IO_SUMMARY, TABLE_LOCK_SUMMARY */
+  table_share->m_table_stat.aggregate(&pfs->m_table_stat);
+  pfs->m_table_stat.reset();
+}
+
 /**
   Build the prefix name of a class of instruments in a category.
   For example, this function builds the string 'wait/sync/mutex/sql/' from
@@ -872,11 +923,6 @@ static void register_file_v1(const char
 #define INIT_BODY_V1(T, KEY, ID)                                            \
   PFS_##T##_class *klass;                                                   \
   PFS_##T *pfs;                                                             \
-  PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS); \
-  if (unlikely(pfs_thread == NULL))                                         \
-    return NULL;                                                            \
-  if (! pfs_thread->m_enabled)                                              \
-    return NULL;                                                            \
   klass= find_##T##_class(KEY);                                             \
   if (unlikely(klass == NULL))                                              \
     return NULL;                                                            \
@@ -928,11 +974,16 @@ static void destroy_cond_v1(PSI_cond* co
 static PSI_table_share*
 get_table_share_v1(my_bool temporary, TABLE_SHARE *share)
 {
+  /* SETUP_OBJECTS does not allow to enable temporary tables. */
+  if (temporary)
+    return NULL;
+  /* Do not instrument this table is all table instruments are disabled. */
+  if (! global_table_io_class.m_enabled)
+    return NULL;
+  /* An instrumented thread is required, for LF_PINS. */
   PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
   if (unlikely(pfs_thread == NULL))
     return NULL;
-  if (! global_table_class.m_enabled)
-    return NULL;
   PFS_table_share* pfs_share;
   pfs_share= find_or_create_table_share(pfs_thread, temporary, share);
   return reinterpret_cast<PSI_table_share*> (pfs_share);
@@ -945,12 +996,9 @@ get_table_share_v1(my_bool temporary, TA
 static void release_table_share_v1(PSI_table_share* share)
 {
   DBUG_ASSERT(share != NULL);
-  PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
-  if (unlikely(pfs_thread == NULL))
-    return;
   PFS_table_share* pfs;
   pfs= reinterpret_cast<PFS_table_share*> (share);
-  purge_table_share(pfs_thread, pfs);
+  release_table_share(pfs);
 }
 
 /**
@@ -976,14 +1024,12 @@ drop_table_share_v1(const char *schema_n
 static PSI_table*
 open_table_v1(PSI_table_share *share, const void *identity)
 {
+  PFS_table_share *pfs_table_share= reinterpret_cast<PFS_table_share*> (share);
+  DBUG_ASSERT(pfs_table_share);
   PFS_thread *thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
   if (unlikely(thread == NULL))
     return NULL;
-  PFS_table_share *pfs_table_share=
-    reinterpret_cast<PFS_table_share*> (share);
-  PFS_table *pfs_table;
-  DBUG_ASSERT(pfs_table_share);
-  pfs_table= create_table(pfs_table_share, thread, identity);
+  PFS_table *pfs_table= create_table(pfs_table_share, thread, identity);
   return reinterpret_cast<PSI_table *> (pfs_table);
 }
 
@@ -995,32 +1041,45 @@ static void close_table_v1(PSI_table *ta
 {
   PFS_table *pfs= reinterpret_cast<PFS_table*> (table);
   DBUG_ASSERT(pfs);
+  aggregate_table(pfs);
   destroy_table(pfs);
 }
 
 static void create_file_v1(PSI_file_key key, const char *name, File file)
 {
+  if (! flag_global_instrumentation)
+    return;
   int index= (int) file;
   if (unlikely(index < 0))
     return;
-  PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
-  if (unlikely(pfs_thread == NULL))
-    return;
-  if (! pfs_thread->m_enabled)
-    return;
   PFS_file_class *klass= find_file_class(key);
   if (unlikely(klass == NULL))
     return;
   if (! klass->m_enabled)
     return;
-  if (likely(index < file_handle_max))
+
+  /* A thread is needed for LF_PINS */
+  PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+  if (unlikely(pfs_thread == NULL))
+    return;
+
+  if (flag_thread_instrumentation && ! pfs_thread->m_enabled)
+    return;
+
+  /*
+    We want this check after pfs_thread->m_enabled,
+    to avoid reporting false loss.
+  */
+  if (unlikely(index >= file_handle_max))
   {
-    uint len= strlen(name);
-    PFS_file *pfs= find_or_create_file(pfs_thread, klass, name, len);
-    file_handle_array[index]= pfs;
-  }
-  else
     file_handle_lost++;
+    return;
+  }
+
+  uint len= strlen(name);
+  PFS_file *pfs_file= find_or_create_file(pfs_thread, klass, name, len);
+
+  file_handle_array[index]= pfs_file;
 }
 
 struct PFS_spawn_thread_arg
@@ -1147,25 +1206,30 @@ static void set_thread_user_v1(const cha
   if (unlikely(pfs == NULL))
     return;
 
+  aggregate_thread(pfs);
+
   pfs->m_lock.allocated_to_dirty();
+
   if (user_len > 0)
     memcpy(pfs->m_username, user, user_len);
   pfs->m_username_length= user_len;
 
-  bool enabled= false;
-
-  if ((pfs->m_username_length > 0) && (pfs->m_hostname_length > 0))
+  bool enabled= true;
+  if (flag_thread_instrumentation)
   {
-    /*
-      TODO: performance improvement.
-      Once performance_schema.USERS is exposed,
-      we can use PFS_user::m_enabled instead of looking up
-      SETUP_ACTORS every time.
-    */
-    lookup_setup_actor(pfs,
-                       pfs->m_username, pfs->m_username_length,
-                       pfs->m_hostname, pfs->m_hostname_length,
-                       &enabled);
+    if ((pfs->m_username_length > 0) && (pfs->m_hostname_length > 0))
+    {
+      /*
+        TODO: performance improvement.
+        Once performance_schema.USERS is exposed,
+        we can use PFS_user::m_enabled instead of looking up
+        SETUP_ACTORS every time.
+      */
+      lookup_setup_actor(pfs,
+                         pfs->m_username, pfs->m_username_length,
+                         pfs->m_hostname, pfs->m_hostname_length,
+                         &enabled);
+    }
   }
 
   pfs->m_enabled= enabled;
@@ -1202,19 +1266,22 @@ static void set_thread_user_host_v1(cons
     memcpy(pfs->m_username, user, user_len);
   pfs->m_username_length= user_len;
 
-  bool enabled= false;
-  if ((pfs->m_username_length > 0) && (pfs->m_hostname_length > 0))
+  bool enabled= true;
+  if (flag_thread_instrumentation)
   {
-    /*
-      TODO: performance improvement.
-      Once performance_schema.USERS is exposed,
-      we can use PFS_user::m_enabled instead of looking up
-      SETUP_ACTORS every time.
-    */
-    lookup_setup_actor(pfs,
-                       pfs->m_username, pfs->m_username_length,
-                       pfs->m_hostname, pfs->m_hostname_length,
-                       &enabled);
+    if ((pfs->m_username_length > 0) && (pfs->m_hostname_length > 0))
+    {
+      /*
+        TODO: performance improvement.
+        Once performance_schema.USERS is exposed,
+        we can use PFS_user::m_enabled instead of looking up
+        SETUP_ACTORS every time.
+      */
+      lookup_setup_actor(pfs,
+                         pfs->m_username, pfs->m_username_length,
+                         pfs->m_hostname, pfs->m_hostname_length,
+                         &enabled);
+    }
   }
   pfs->m_enabled= enabled;
 
@@ -1325,6 +1392,7 @@ static void delete_current_thread_v1(voi
   PFS_thread *thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
   if (thread != NULL)
   {
+    aggregate_thread(thread);
     my_pthread_setspecific_ptr(THR_PFS, NULL);
     destroy_thread(thread);
   }
@@ -1333,8 +1401,12 @@ static void delete_current_thread_v1(voi
 static void delete_thread_v1(PSI_thread *thread)
 {
   PFS_thread *pfs= reinterpret_cast<PFS_thread*> (thread);
+
   if (pfs != NULL)
+  {
+    aggregate_thread(pfs);
     destroy_thread(pfs);
+  }
 }
 
 static PSI_mutex_locker*
@@ -1344,50 +1416,80 @@ get_thread_mutex_locker_v1(PSI_mutex_loc
   PFS_mutex *pfs_mutex= reinterpret_cast<PFS_mutex*> (mutex);
   DBUG_ASSERT((int) op >= 0);
   DBUG_ASSERT((uint) op < array_elements(mutex_operation_map));
+  DBUG_ASSERT(state != NULL);
   DBUG_ASSERT(pfs_mutex != NULL);
   DBUG_ASSERT(pfs_mutex->m_class != NULL);
-  if (! flag_events_waits_current)
-    return NULL;
-  if (! pfs_mutex->m_class->m_enabled)
-    return NULL;
-  PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
-  if (unlikely(pfs_thread == NULL))
+
+  if (! flag_global_instrumentation)
     return NULL;
-  if (! pfs_thread->m_enabled)
+  PFS_mutex_class *klass= pfs_mutex->m_class;
+  if (! klass->m_enabled)
     return NULL;
-  if (unlikely(pfs_thread->m_wait_locker_count >= LOCKER_STACK_SIZE))
+
+  register uint flags;
+
+  if (flag_thread_instrumentation)
   {
-    locker_lost++;
-    return NULL;
+    PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+    if (unlikely(pfs_thread == NULL))
+      return NULL;
+    if (! pfs_thread->m_enabled)
+      return NULL;
+    state->m_thread= reinterpret_cast<PSI_thread *> (pfs_thread);
+    flags= STATE_FLAG_THREAD;
+
+    if (klass->m_timed)
+      flags|= STATE_FLAG_TIMED;
+
+    if (flag_events_waits_current)
+    {
+      if (unlikely(pfs_thread->m_events_waits_count >= WAIT_STACK_SIZE))
+      {
+        locker_lost++;
+        return NULL;
+      }
+      PFS_events_waits *wait= &pfs_thread->m_events_waits_stack[pfs_thread->m_events_waits_count];
+      state->m_wait= wait;
+      flags|= STATE_FLAG_WAIT;
+
+#ifdef HAVE_NESTED_EVENTS
+      wait->m_nesting_event_id= (wait - 1)->m_event_id;
+#endif
+
+      wait->m_thread= pfs_thread;
+      wait->m_class= klass;
+      wait->m_timer_start= 0;
+      wait->m_timer_end= 0;
+      wait->m_object_instance_addr= pfs_mutex->m_identity;
+      wait->m_event_id= pfs_thread->m_event_id++;
+      wait->m_operation= mutex_operation_map[(int) op];
+      wait->m_wait_class= WAIT_CLASS_MUTEX;
+
+      pfs_thread->m_events_waits_count++;
+    }
   }
-  PFS_wait_locker *pfs_locker= &pfs_thread->m_wait_locker_stack
-    [pfs_thread->m_wait_locker_count];
-  if (likely(pfs_thread->m_wait_locker_count == 0))
-    pfs_locker->m_waits_current.m_nesting_event_id= 0;
   else
   {
-    PFS_wait_locker *parent_locker= pfs_locker-1;
-    pfs_locker->m_waits_current.m_nesting_event_id=
-      parent_locker->m_waits_current.m_event_id;
-  }
-
-  pfs_locker->m_target.m_mutex= pfs_mutex;
-  pfs_locker->m_waits_current.m_thread= pfs_thread;
-  pfs_locker->m_waits_current.m_class= pfs_mutex->m_class;
-  if (pfs_mutex->m_class->m_timed)
-  {
-    pfs_locker->m_timer_name= wait_timer;
-    pfs_locker->m_waits_current.m_timer_state= TIMER_STATE_STARTING;
+    if (klass->m_timed)
+    {
+      flags= STATE_FLAG_TIMED;
+      state->m_thread= NULL;
+    }
+    else
+    {
+      /*
+        Complete shortcut.
+      */
+      PFS_mutex *pfs_mutex= reinterpret_cast<PFS_mutex *> (mutex);
+      /* Aggregate to EVENTS_WAITS_SUMMARY_BY_INSTANCE (counted) */
+      pfs_mutex->m_wait_stat.aggregate_counted();
+      return NULL;
+    }
   }
-  else
-    pfs_locker->m_waits_current.m_timer_state= TIMER_STATE_UNTIMED;
-  pfs_locker->m_waits_current.m_object_instance_addr= pfs_mutex->m_identity;
-  pfs_locker->m_waits_current.m_event_id= pfs_thread->m_event_id++;
-  pfs_locker->m_waits_current.m_operation= mutex_operation_map[(int) op];
-  pfs_locker->m_waits_current.m_wait_class= WAIT_CLASS_MUTEX;
 
-  pfs_thread->m_wait_locker_count++;
-  return reinterpret_cast<PSI_mutex_locker*> (pfs_locker);
+  state->m_flags= flags;
+  state->m_mutex= mutex;
+  return reinterpret_cast<PSI_mutex_locker*> (state);
 }
 
 static PSI_rwlock_locker*
@@ -1397,56 +1499,85 @@ get_thread_rwlock_locker_v1(PSI_rwlock_l
   PFS_rwlock *pfs_rwlock= reinterpret_cast<PFS_rwlock*> (rwlock);
   DBUG_ASSERT(static_cast<int> (op) >= 0);
   DBUG_ASSERT(static_cast<uint> (op) < array_elements(rwlock_operation_map));
+  DBUG_ASSERT(state != NULL);
   DBUG_ASSERT(pfs_rwlock != NULL);
   DBUG_ASSERT(pfs_rwlock->m_class != NULL);
-  if (! flag_events_waits_current)
-    return NULL;
-  if (! pfs_rwlock->m_class->m_enabled)
-    return NULL;
-  PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
-  if (unlikely(pfs_thread == NULL))
+
+  if (! flag_global_instrumentation)
     return NULL;
-  if (! pfs_thread->m_enabled)
+  PFS_rwlock_class *klass= pfs_rwlock->m_class;
+  if (! klass->m_enabled)
     return NULL;
-  if (unlikely(pfs_thread->m_wait_locker_count >= LOCKER_STACK_SIZE))
+
+  register uint flags;
+
+  if (flag_thread_instrumentation)
   {
-    locker_lost++;
-    return NULL;
+    PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+    if (unlikely(pfs_thread == NULL))
+      return NULL;
+    if (! pfs_thread->m_enabled)
+      return NULL;
+    state->m_thread= reinterpret_cast<PSI_thread *> (pfs_thread);
+    flags= STATE_FLAG_THREAD;
+
+    if (klass->m_timed)
+      flags|= STATE_FLAG_TIMED;
+
+    if (flag_events_waits_current)
+    {
+      if (unlikely(pfs_thread->m_events_waits_count >= WAIT_STACK_SIZE))
+      {
+        locker_lost++;
+        return NULL;
+      }
+      PFS_events_waits *wait= &pfs_thread->m_events_waits_stack[pfs_thread->m_events_waits_count];
+      state->m_wait= wait;
+      flags|= STATE_FLAG_WAIT;
+
+#ifdef HAVE_NESTED_EVENTS
+      wait->m_nesting_event_id= (wait - 1)->m_event_id;
+#endif
+
+      wait->m_thread= pfs_thread;
+      wait->m_class= klass;
+      wait->m_timer_start= 0;
+      wait->m_timer_end= 0;
+      wait->m_object_instance_addr= pfs_rwlock->m_identity;
+      wait->m_event_id= pfs_thread->m_event_id++;
+      wait->m_operation= rwlock_operation_map[static_cast<int> (op)];
+      wait->m_wait_class= WAIT_CLASS_RWLOCK;
+
+      pfs_thread->m_events_waits_count++;
+    }
   }
-  PFS_wait_locker *pfs_locker= &pfs_thread->m_wait_locker_stack
-    [pfs_thread->m_wait_locker_count];
-  if (likely(pfs_thread->m_wait_locker_count == 0))
-    pfs_locker->m_waits_current.m_nesting_event_id= 0;
   else
   {
-    PFS_wait_locker *parent_locker= pfs_locker-1;
-    pfs_locker->m_waits_current.m_nesting_event_id=
-      parent_locker->m_waits_current.m_event_id;
-  }
-
-  pfs_locker->m_target.m_rwlock= pfs_rwlock;
-  pfs_locker->m_waits_current.m_thread= pfs_thread;
-  pfs_locker->m_waits_current.m_class= pfs_rwlock->m_class;
-  if (pfs_rwlock->m_class->m_timed)
-  {
-    pfs_locker->m_timer_name= wait_timer;
-    pfs_locker->m_waits_current.m_timer_state= TIMER_STATE_STARTING;
+    if (klass->m_timed)
+    {
+      flags= STATE_FLAG_TIMED;
+      state->m_thread= NULL;
+    }
+    else
+    {
+      /*
+        Complete shortcut.
+      */
+      PFS_rwlock *pfs_rwlock= reinterpret_cast<PFS_rwlock *> (rwlock);
+      /* Aggregate to EVENTS_WAITS_SUMMARY_BY_INSTANCE (counted) */
+      pfs_rwlock->m_wait_stat.aggregate_counted();
+      return NULL;
+    }
   }
-  else
-    pfs_locker->m_waits_current.m_timer_state= TIMER_STATE_UNTIMED;
-  pfs_locker->m_waits_current.m_object_instance_addr= pfs_rwlock->m_identity;
-  pfs_locker->m_waits_current.m_event_id= pfs_thread->m_event_id++;
-  pfs_locker->m_waits_current.m_operation=
-    rwlock_operation_map[static_cast<int> (op)];
-  pfs_locker->m_waits_current.m_wait_class= WAIT_CLASS_RWLOCK;
 
-  pfs_thread->m_wait_locker_count++;
-  return reinterpret_cast<PSI_rwlock_locker*> (pfs_locker);
+  state->m_flags= flags;
+  state->m_rwlock= rwlock;
+  return reinterpret_cast<PSI_rwlock_locker*> (state);
 }
 
 static PSI_cond_locker*
 get_thread_cond_locker_v1(PSI_cond_locker_state *state,
-                          PSI_cond *cond, PSI_mutex * /* unused: mutex */,
+                          PSI_cond *cond, PSI_mutex *mutex,
                           PSI_cond_operation op)
 {
   /*
@@ -1463,51 +1594,83 @@ get_thread_cond_locker_v1(PSI_cond_locke
   PFS_cond *pfs_cond= reinterpret_cast<PFS_cond*> (cond);
   DBUG_ASSERT(static_cast<int> (op) >= 0);
   DBUG_ASSERT(static_cast<uint> (op) < array_elements(cond_operation_map));
+  DBUG_ASSERT(state != NULL);
   DBUG_ASSERT(pfs_cond != NULL);
   DBUG_ASSERT(pfs_cond->m_class != NULL);
-  if (! flag_events_waits_current)
-    return NULL;
-  if (! pfs_cond->m_class->m_enabled)
-    return NULL;
-  PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
-  if (unlikely(pfs_thread == NULL))
-    return NULL;
-  if (! pfs_thread->m_enabled)
+
+  if (! flag_global_instrumentation)
     return NULL;
-  if (unlikely(pfs_thread->m_wait_locker_count >= LOCKER_STACK_SIZE))
-  {
-    locker_lost++;
+  PFS_cond_class *klass= pfs_cond->m_class;
+  if (! klass->m_enabled)
     return NULL;
-  }
-  PFS_wait_locker *pfs_locker= &pfs_thread->m_wait_locker_stack
-    [pfs_thread->m_wait_locker_count];
-  if (likely(pfs_thread->m_wait_locker_count == 0))
-    pfs_locker->m_waits_current.m_nesting_event_id= 0;
+
+  register uint flags;
+
+  if (klass->m_timed)
+    state->m_flags= STATE_FLAG_TIMED;
   else
-  {
-    PFS_wait_locker *parent_locker= pfs_locker-1;
-    pfs_locker->m_waits_current.m_nesting_event_id=
-      parent_locker->m_waits_current.m_event_id;
-  }
+    state->m_flags= 0;
 
-  pfs_locker->m_target.m_cond= pfs_cond;
-  pfs_locker->m_waits_current.m_thread= pfs_thread;
-  pfs_locker->m_waits_current.m_class= pfs_cond->m_class;
-  if (pfs_cond->m_class->m_timed)
+  if (flag_thread_instrumentation)
   {
-    pfs_locker->m_timer_name= wait_timer;
-    pfs_locker->m_waits_current.m_timer_state= TIMER_STATE_STARTING;
+    PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+    if (unlikely(pfs_thread == NULL))
+      return NULL;
+    if (! pfs_thread->m_enabled)
+      return NULL;
+    state->m_thread= reinterpret_cast<PSI_thread *> (pfs_thread);
+    flags= STATE_FLAG_THREAD;
+
+    if (klass->m_timed)
+      flags|= STATE_FLAG_TIMED;
+
+    if (flag_events_waits_current)
+    {
+      if (unlikely(pfs_thread->m_events_waits_count >= WAIT_STACK_SIZE))
+      {
+        locker_lost++;
+        return NULL;
+      }
+      PFS_events_waits *wait= &pfs_thread->m_events_waits_stack[pfs_thread->m_events_waits_count];
+      state->m_wait= wait;
+      flags|= STATE_FLAG_WAIT;
+
+#ifdef HAVE_NESTED_EVENTS
+      wait->m_nesting_event_id= (wait - 1)->m_event_id;
+#endif
+
+      wait->m_thread= pfs_thread;
+      wait->m_class= klass;
+      wait->m_timer_start= 0;
+      wait->m_timer_end= 0;
+      wait->m_object_instance_addr= pfs_cond->m_identity;
+      wait->m_event_id= pfs_thread->m_event_id++;
+      wait->m_operation= cond_operation_map[static_cast<int> (op)];
+      wait->m_wait_class= WAIT_CLASS_COND;
+
+      pfs_thread->m_events_waits_count++;
+    }
   }
   else
-    pfs_locker->m_waits_current.m_timer_state= TIMER_STATE_UNTIMED;
-  pfs_locker->m_waits_current.m_object_instance_addr= pfs_cond->m_identity;
-  pfs_locker->m_waits_current.m_event_id= pfs_thread->m_event_id++;
-  pfs_locker->m_waits_current.m_operation=
-    cond_operation_map[static_cast<int> (op)];
-  pfs_locker->m_waits_current.m_wait_class= WAIT_CLASS_COND;
+  {
+    if (klass->m_timed)
+      flags= STATE_FLAG_TIMED;
+    else
+    {
+      /*
+        Complete shortcut.
+      */
+      PFS_cond *pfs_cond= reinterpret_cast<PFS_cond *> (cond);
+      /* Aggregate to EVENTS_WAITS_SUMMARY_BY_INSTANCE (counted) */
+      pfs_cond->m_wait_stat.aggregate_counted();
+      return NULL;
+    }
+  }
 
-  pfs_thread->m_wait_locker_count++;
-  return reinterpret_cast<PSI_cond_locker*> (pfs_locker);
+  state->m_flags= flags;
+  state->m_cond= cond;
+  state->m_mutex= mutex;
+  return reinterpret_cast<PSI_cond_locker*> (state);
 }
 
 /**
@@ -1516,65 +1679,128 @@ get_thread_cond_locker_v1(PSI_cond_locke
 */
 static PSI_table_locker*
 get_thread_table_locker_v1(PSI_table_locker_state *state,
-                           PSI_table *table, PSI_table_operation op, ulong flags)
+                           PSI_table *table, PSI_table_operation op, ulong op_flags)
 {
   DBUG_ASSERT(static_cast<int> (op) >= 0);
   DBUG_ASSERT(static_cast<uint> (op) < array_elements(table_operation_map));
+  DBUG_ASSERT(state != NULL);
   PFS_table *pfs_table= reinterpret_cast<PFS_table*> (table);
   DBUG_ASSERT(pfs_table != NULL);
   DBUG_ASSERT(pfs_table->m_share != NULL);
 
-  if (! flag_events_waits_current)
-    return NULL;
-  if (! global_table_class.m_enabled)
+  if (! flag_global_instrumentation)
     return NULL;
-  /*
-    Table locks will be recorded with WL#5371.
-  */
-  if ((op == PSI_TABLE_EXTERNAL_LOCK) || (op == PSI_TABLE_LOCK))
-    return NULL;
-  if (! pfs_table->m_share->m_enabled)
-    return NULL;
-  PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
-  if (unlikely(pfs_thread == NULL))
-    return NULL;
-  if (! pfs_thread->m_enabled)
-    return NULL;
-  if (unlikely(pfs_thread->m_wait_locker_count >= LOCKER_STACK_SIZE))
+  PFS_table_share *share= pfs_table->m_share;
+  if (unlikely(setup_objects_version != share->m_setup_objects_version))
   {
-    locker_lost++;
-    return NULL;
-  }
-  PFS_wait_locker *pfs_locker= &pfs_thread->m_wait_locker_stack
-    [pfs_thread->m_wait_locker_count];
-  if (likely(pfs_thread->m_wait_locker_count == 0))
-    pfs_locker->m_waits_current.m_nesting_event_id= 0;
-  else
-  {
-    PFS_wait_locker *parent_locker= pfs_locker-1;
-    pfs_locker->m_waits_current.m_nesting_event_id=
-      parent_locker->m_waits_current.m_event_id;
+    PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+    if (unlikely(pfs_thread == NULL))
+      return NULL;
+    /* Refresh the enabled and timed flags from SETUP_OBJECTS */
+    share->m_setup_objects_version= setup_objects_version;
+    lookup_setup_object(pfs_thread,
+                        share->get_object_type(),
+                        share->m_schema_name,
+                        share->m_schema_name_length,
+                        share->m_table_name,
+                        share->m_table_name_length,
+                        & share->m_enabled,
+                        & share->m_timed);
+  }
+  if (! share->m_enabled)
+    return NULL;
+
+  PFS_instr_class *klass;
+
+  switch (op)
+  {
+    case PSI_TABLE_LOCK:
+    case PSI_TABLE_EXTERNAL_LOCK:
+      return NULL;
+    case PSI_TABLE_FETCH_ROW:
+    case PSI_TABLE_WRITE_ROW:
+    case PSI_TABLE_UPDATE_ROW:
+    case PSI_TABLE_DELETE_ROW:
+      if (! global_table_io_class.m_enabled)
+        return NULL;
+      klass= &global_table_io_class;
+      break;
+    default:
+      klass= NULL;
+      DBUG_ASSERT(false);
   }
 
-  pfs_locker->m_target.m_table= pfs_table;
-  pfs_locker->m_waits_current.m_thread= pfs_thread;
-  pfs_locker->m_waits_current.m_class= &global_table_class;
-  if (pfs_table->m_share->m_timed)
+
+  register uint flags;
+
+  if (flag_thread_instrumentation)
   {
-    pfs_locker->m_timer_name= wait_timer;
-    pfs_locker->m_waits_current.m_timer_state= TIMER_STATE_STARTING;
+    PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+    if (unlikely(pfs_thread == NULL))
+      return NULL;
+    if (! pfs_thread->m_enabled)
+      return NULL;
+    state->m_thread= reinterpret_cast<PSI_thread *> (pfs_thread);
+    flags= STATE_FLAG_THREAD;
+
+    if (share->m_timed)
+      flags|= STATE_FLAG_TIMED;
+
+    if (flag_events_waits_current)
+    {
+      if (unlikely(pfs_thread->m_events_waits_count >= WAIT_STACK_SIZE))
+      {
+        locker_lost++;
+        return NULL;
+      }
+      PFS_events_waits *wait= &pfs_thread->m_events_waits_stack[pfs_thread->m_events_waits_count];
+      state->m_wait= wait;
+      flags|= STATE_FLAG_WAIT;
+
+      wait->m_thread= pfs_thread;
+      wait->m_class= klass;
+      wait->m_timer_start= 0;
+      wait->m_timer_end= 0;
+      wait->m_object_instance_addr= pfs_table->m_identity;
+      wait->m_event_id= pfs_thread->m_event_id++;
+      wait->m_operation= table_operation_map[static_cast<int> (op)];
+      wait->m_flags= op_flags;
+      wait->m_object_type= share->get_object_type();
+      wait->m_schema_name= share->m_schema_name;
+      wait->m_schema_name_length= share->m_schema_name_length;
+      wait->m_object_name= share->m_table_name;
+      wait->m_object_name_length= share->m_table_name_length;
+      wait->m_wait_class= WAIT_CLASS_TABLE;
+
+      pfs_thread->m_events_waits_count++;
+    }
   }
   else
-    pfs_locker->m_waits_current.m_timer_state= TIMER_STATE_UNTIMED;
-  pfs_locker->m_waits_current.m_object_instance_addr= pfs_table->m_identity;
-  pfs_locker->m_waits_current.m_event_id= pfs_thread->m_event_id++;
-  pfs_locker->m_waits_current.m_operation=
-    table_operation_map[static_cast<int> (op)];
-  pfs_locker->m_waits_current.m_flags= flags;
-  pfs_locker->m_waits_current.m_wait_class= WAIT_CLASS_TABLE;
+  {
+    if (share->m_timed)
+    {
+      flags= STATE_FLAG_TIMED;
+    }
+    else
+    {
+#ifdef LATER
+      /*
+        Complete shortcut.
+      */
+      PFS_table *pfs_table= reinterpret_cast<PFS_table *> (table);
+      /* Aggregate to EVENTS_WAITS_SUMMARY_BY_INSTANCE (counted) */
+      pfs_table->m_wait_stat.aggregate_counted();
+      return NULL;
+#endif
+      flags= 0;
+    }
+  }
 
-  pfs_thread->m_wait_locker_count++;
-  return reinterpret_cast<PSI_table_locker*> (pfs_locker);
+  state->m_flags= flags;
+  state->m_table= table;
+  state->m_class= klass;
+  state->m_operation= op;
+  return reinterpret_cast<PSI_table_locker*> (state);
 }
 
 static PSI_file_locker*
@@ -1585,61 +1811,70 @@ get_thread_file_name_locker_v1(PSI_file_
 {
   DBUG_ASSERT(static_cast<int> (op) >= 0);
   DBUG_ASSERT(static_cast<uint> (op) < array_elements(file_operation_map));
+  DBUG_ASSERT(state != NULL);
 
-  if (! flag_events_waits_current)
+  if (! flag_global_instrumentation)
     return NULL;
   PFS_file_class *klass= find_file_class(key);
   if (unlikely(klass == NULL))
     return NULL;
   if (! klass->m_enabled)
     return NULL;
+
+  /* Needed for the LF_HASH */
   PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
   if (unlikely(pfs_thread == NULL))
     return NULL;
-  if (! pfs_thread->m_enabled)
-    return NULL;
-  if (unlikely(pfs_thread->m_wait_locker_count >= LOCKER_STACK_SIZE))
-  {
-    locker_lost++;
+
+  if (flag_thread_instrumentation && ! pfs_thread->m_enabled)
     return NULL;
-  }
+
+  register uint flags;
+
+  state->m_thread= reinterpret_cast<PSI_thread *> (pfs_thread);
+  flags= STATE_FLAG_THREAD;
+
+  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;
 
-  PFS_wait_locker *pfs_locker= &pfs_thread->m_wait_locker_stack
-    [pfs_thread->m_wait_locker_count];
-  if (likely(pfs_thread->m_wait_locker_count == 0))
-    pfs_locker->m_waits_current.m_nesting_event_id= 0;
-  else
+  if (flag_events_waits_current)
   {
-    PFS_wait_locker *parent_locker= pfs_locker-1;
-    pfs_locker->m_waits_current.m_nesting_event_id=
-      parent_locker->m_waits_current.m_event_id;
-  }
+    if (unlikely(pfs_thread->m_events_waits_count >= WAIT_STACK_SIZE))
+    {
+      locker_lost++;
+      return NULL;
+    }
+    PFS_events_waits *wait= &pfs_thread->m_events_waits_stack[pfs_thread->m_events_waits_count];
+    state->m_wait= wait;
+    flags|= STATE_FLAG_WAIT;
 
-  pfs_locker->m_target.m_file= pfs_file;
-  pfs_locker->m_waits_current.m_thread= pfs_thread;
-  pfs_locker->m_waits_current.m_class= pfs_file->m_class;
-  if (pfs_file->m_class->m_timed)
-  {
-    pfs_locker->m_timer_name= wait_timer;
-    pfs_locker->m_waits_current.m_timer_state= TIMER_STATE_STARTING;
-  }
-  else
-    pfs_locker->m_waits_current.m_timer_state= TIMER_STATE_UNTIMED;
-  pfs_locker->m_waits_current.m_object_instance_addr= pfs_file;
-  pfs_locker->m_waits_current.m_object_name= pfs_file->m_filename;
-  pfs_locker->m_waits_current.m_object_name_length=
-    pfs_file->m_filename_length;
-  pfs_locker->m_waits_current.m_event_id= pfs_thread->m_event_id++;
-  pfs_locker->m_waits_current.m_operation=
-    file_operation_map[static_cast<int> (op)];
-  pfs_locker->m_waits_current.m_wait_class= WAIT_CLASS_FILE;
+#ifdef HAVE_NESTED_EVENTS
+    wait->m_nesting_event_id= (wait - 1)->m_event_id;
+#endif
 
-  pfs_thread->m_wait_locker_count++;
-  return reinterpret_cast<PSI_file_locker*> (pfs_locker);
+    wait->m_thread= pfs_thread;
+    wait->m_class= klass;
+    wait->m_timer_start= 0;
+    wait->m_timer_end= 0;
+    wait->m_object_instance_addr= pfs_file;
+    wait->m_object_name= pfs_file->m_filename;
+    wait->m_object_name_length= pfs_file->m_filename_length;
+    wait->m_event_id= pfs_thread->m_event_id++;
+    wait->m_operation= file_operation_map[static_cast<int> (op)];
+    wait->m_wait_class= WAIT_CLASS_FILE;
+
+    pfs_thread->m_events_waits_count++;
+  }
+
+  state->m_flags= flags;
+  state->m_file= reinterpret_cast<PSI_file*> (pfs_file);
+  state->m_operation= op;
+  return reinterpret_cast<PSI_file_locker*> (state);
 }
 
 static PSI_file_locker*
@@ -1647,58 +1882,81 @@ get_thread_file_stream_locker_v1(PSI_fil
                                  PSI_file *file, PSI_file_operation op)
 {
   PFS_file *pfs_file= reinterpret_cast<PFS_file*> (file);
-
-  DBUG_ASSERT(static_cast<int> (op) >= 0);
-  DBUG_ASSERT(static_cast<uint> (op) < array_elements(file_operation_map));
   DBUG_ASSERT(pfs_file != NULL);
   DBUG_ASSERT(pfs_file->m_class != NULL);
+  DBUG_ASSERT(static_cast<int> (op) >= 0);
+  DBUG_ASSERT(static_cast<uint> (op) < array_elements(file_operation_map));
+  DBUG_ASSERT(state != NULL);
 
-  if (! flag_events_waits_current)
-    return NULL;
-  if (! pfs_file->m_class->m_enabled)
-    return NULL;
-  PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
-  if (unlikely(pfs_thread == NULL))
+  if (! flag_global_instrumentation)
     return NULL;
-  if (! pfs_thread->m_enabled)
+
+  PFS_file_class *klass= pfs_file->m_class;
+  if (! klass->m_enabled)
     return NULL;
-  if (unlikely(pfs_thread->m_wait_locker_count >= LOCKER_STACK_SIZE))
+
+  register uint flags;
+
+  if (flag_thread_instrumentation)
   {
-    locker_lost++;
-    return NULL;
+    PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+    if (unlikely(pfs_thread == NULL))
+      return NULL;
+    if (! pfs_thread->m_enabled)
+      return NULL;
+    state->m_thread= reinterpret_cast<PSI_thread *> (pfs_thread);
+    flags= STATE_FLAG_THREAD;
+
+    if (klass->m_timed)
+      flags|= STATE_FLAG_TIMED;
+
+    if (flag_events_waits_current)
+    {
+      if (unlikely(pfs_thread->m_events_waits_count >= WAIT_STACK_SIZE))
+      {
+        locker_lost++;
+        return NULL;
+      }
+      PFS_events_waits *wait= &pfs_thread->m_events_waits_stack[pfs_thread->m_events_waits_count];
+      state->m_wait= wait;
+      flags|= STATE_FLAG_WAIT;
+
+#ifdef HAVE_NESTED_EVENTS
+      wait->m_nesting_event_id= (wait - 1)->m_event_id;
+#endif
+
+      wait->m_thread= pfs_thread;
+      wait->m_class= klass;
+      wait->m_timer_start= 0;
+      wait->m_timer_end= 0;
+      wait->m_object_instance_addr= pfs_file;
+      wait->m_object_name= pfs_file->m_filename;
+      wait->m_object_name_length= pfs_file->m_filename_length;
+      wait->m_event_id= pfs_thread->m_event_id++;
+      wait->m_operation= file_operation_map[static_cast<int> (op)];
+      wait->m_wait_class= WAIT_CLASS_FILE;
+
+      pfs_thread->m_events_waits_count++;
+    }
   }
-  PFS_wait_locker *pfs_locker= &pfs_thread->m_wait_locker_stack
-    [pfs_thread->m_wait_locker_count];
-  if (likely(pfs_thread->m_wait_locker_count == 0))
-    pfs_locker->m_waits_current.m_nesting_event_id= 0;
   else
   {
-    PFS_wait_locker *parent_locker= pfs_locker-1;
-    pfs_locker->m_waits_current.m_nesting_event_id=
-      parent_locker->m_waits_current.m_event_id;
-  }
-
-  pfs_locker->m_target.m_file= pfs_file;
-  pfs_locker->m_waits_current.m_thread= pfs_thread;
-  pfs_locker->m_waits_current.m_class= pfs_file->m_class;
-  if (pfs_file->m_class->m_timed)
-  {
-    pfs_locker->m_timer_name= wait_timer;
-    pfs_locker->m_waits_current.m_timer_state= TIMER_STATE_STARTING;
+    state->m_thread= NULL;
+    if (klass->m_timed)
+    {
+      flags= STATE_FLAG_TIMED;
+    }
+    else
+    {
+      /* TODO: consider a shortcut. */
+      flags= 0;
+    }
   }
-  else
-    pfs_locker->m_waits_current.m_timer_state= TIMER_STATE_UNTIMED;
-  pfs_locker->m_waits_current.m_object_instance_addr= pfs_file;
-  pfs_locker->m_waits_current.m_object_name= pfs_file->m_filename;
-  pfs_locker->m_waits_current.m_object_name_length=
-    pfs_file->m_filename_length;
-  pfs_locker->m_waits_current.m_event_id= pfs_thread->m_event_id++;
-  pfs_locker->m_waits_current.m_operation=
-    file_operation_map[static_cast<int> (op)];
-  pfs_locker->m_waits_current.m_wait_class= WAIT_CLASS_FILE;
 
-  pfs_thread->m_wait_locker_count++;
-  return reinterpret_cast<PSI_file_locker*> (pfs_locker);
+  state->m_flags= flags;
+  state->m_file= reinterpret_cast<PSI_file*> (pfs_file);
+  state->m_operation= op;
+  return reinterpret_cast<PSI_file_locker*> (state);
 }
 
 static PSI_file_locker*
@@ -1706,78 +1964,98 @@ get_thread_file_descriptor_locker_v1(PSI
                                      File file, PSI_file_operation op)
 {
   int index= static_cast<int> (file);
-
   DBUG_ASSERT(static_cast<int> (op) >= 0);
   DBUG_ASSERT(static_cast<uint> (op) < array_elements(file_operation_map));
+  DBUG_ASSERT(state != NULL);
 
-  if (! flag_events_waits_current)
+  if (! flag_global_instrumentation)
     return NULL;
-  if (likely((index >= 0) && (index < file_handle_max)))
+
+  if (unlikely((index < 0) || (index >= file_handle_max)))
+    return NULL;
+
+  PFS_file *pfs_file= file_handle_array[index];
+  if (unlikely(pfs_file == NULL))
+    return NULL;
+
+  /*
+    We are about to close a file by descriptor number,
+    and the calling code still holds the descriptor.
+    Cleanup the file descriptor <--> file instrument association.
+    Remove the instrumentation *before* the close to avoid race
+    conditions with another thread opening a file
+    (that could be given the same descriptor).
+  */
+  if (op == PSI_FILE_CLOSE)
+    file_handle_array[index]= NULL;
+
+  DBUG_ASSERT(pfs_file->m_class != NULL);
+  PFS_instr_class *klass= pfs_file->m_class;
+  if (! klass->m_enabled)
+    return NULL;
+
+  register uint flags;
+
+  if (flag_thread_instrumentation)
   {
-    PFS_file *pfs_file= file_handle_array[index];
-    if (likely(pfs_file != NULL))
-    {
-      PFS_thread *pfs_thread;
+    PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
+    if (unlikely(pfs_thread == NULL))
+      return NULL;
+    if (! pfs_thread->m_enabled)
+      return NULL;
+    state->m_thread= reinterpret_cast<PSI_thread *> (pfs_thread);
+    flags= STATE_FLAG_THREAD;
 
-      /*
-        We are about to close a file by descriptor number,
-        and the calling code still holds the descriptor.
-        Cleanup the file descriptor <--> file instrument association.
-        Remove the instrumentation *before* the close to avoid race
-        conditions with another thread opening a file
-        (that could be given the same descriptor).
-      */
-      if (op == PSI_FILE_CLOSE)
-        file_handle_array[index]= NULL;
+    if (klass->m_timed)
+      flags|= STATE_FLAG_TIMED;
 
-      DBUG_ASSERT(pfs_file->m_class != NULL);
-      if (! pfs_file->m_class->m_enabled)
-        return NULL;
-      pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
-      if (unlikely(pfs_thread == NULL))
-        return NULL;
-      if (! pfs_thread->m_enabled)
-        return NULL;
-      if (unlikely(pfs_thread->m_wait_locker_count >= LOCKER_STACK_SIZE))
+    if (flag_events_waits_current)
+    {
+      if (unlikely(pfs_thread->m_events_waits_count >= WAIT_STACK_SIZE))
       {
         locker_lost++;
         return NULL;
       }
-      PFS_wait_locker *pfs_locker= &pfs_thread->m_wait_locker_stack
-        [pfs_thread->m_wait_locker_count];
-      if (likely(pfs_thread->m_wait_locker_count == 0))
-        pfs_locker->m_waits_current.m_nesting_event_id= 0;
-      else
-      {
-        PFS_wait_locker *parent_locker= pfs_locker-1;
-        pfs_locker->m_waits_current.m_nesting_event_id=
-          parent_locker->m_waits_current.m_event_id;
-      }
+      PFS_events_waits *wait= &pfs_thread->m_events_waits_stack[pfs_thread->m_events_waits_count];
+      state->m_wait= wait;
+      flags|= STATE_FLAG_WAIT;
 
-      pfs_locker->m_target.m_file= pfs_file;
-      pfs_locker->m_waits_current.m_thread= pfs_thread;
-      pfs_locker->m_waits_current.m_class= pfs_file->m_class;
-      if (pfs_file->m_class->m_timed)
-      {
-        pfs_locker->m_timer_name= wait_timer;
-        pfs_locker->m_waits_current.m_timer_state= TIMER_STATE_STARTING;
-      }
-      else
-        pfs_locker->m_waits_current.m_timer_state= TIMER_STATE_UNTIMED;
-      pfs_locker->m_waits_current.m_object_instance_addr= pfs_file;
-      pfs_locker->m_waits_current.m_object_name= pfs_file->m_filename;
-      pfs_locker->m_waits_current.m_object_name_length=
-        pfs_file->m_filename_length;
-      pfs_locker->m_waits_current.m_event_id= pfs_thread->m_event_id++;
-      pfs_locker->m_waits_current.m_operation=
-        file_operation_map[static_cast<int> (op)];
-      pfs_locker->m_waits_current.m_wait_class= WAIT_CLASS_FILE;
+#ifdef HAVE_NESTED_EVENTS
+      wait->m_nesting_event_id= (wait - 1)->m_event_id;
+#endif
+
+      wait->m_thread= pfs_thread;
+      wait->m_class= klass;
+      wait->m_timer_start= 0;
+      wait->m_timer_end= 0;
+      wait->m_object_instance_addr= pfs_file;
+      wait->m_object_name= pfs_file->m_filename;
+      wait->m_object_name_length= pfs_file->m_filename_length;
+      wait->m_event_id= pfs_thread->m_event_id++;
+      wait->m_operation= file_operation_map[static_cast<int> (op)];
+      wait->m_wait_class= WAIT_CLASS_FILE;
 
-      pfs_thread->m_wait_locker_count++;
-      return reinterpret_cast<PSI_file_locker*> (pfs_locker);
+      pfs_thread->m_events_waits_count++;
     }
   }
-  return NULL;
+  else
+  {
+    state->m_thread= NULL;
+    if (klass->m_timed)
+    {
+      flags= STATE_FLAG_TIMED;
+    }
+    else
+    {
+      /* TODO: consider a shortcut. */
+      flags= 0;
+    }
+  }
+
+  state->m_flags= flags;
+  state->m_file= reinterpret_cast<PSI_file*> (pfs_file);
+  state->m_operation= op;
+  return reinterpret_cast<PSI_file_locker*> (state);
 }
 
 static void unlock_mutex_v1(PSI_mutex *mutex)
@@ -1813,7 +2091,7 @@ static void unlock_mutex_v1(PSI_mutex *m
   if (pfs_mutex->m_class->m_timed)
   {
     ulonglong locked_time;
-    locked_time= get_timer_value(wait_timer) - pfs_mutex->m_last_locked;
+    locked_time= get_timer_pico_value(wait_timer) - pfs_mutex->m_last_locked;
     aggregate_single_stat_chain(&pfs_mutex->m_lock_stat, locked_time);
   }
 #endif
@@ -1880,7 +2158,7 @@ static void unlock_rwlock_v1(PSI_rwlock
   {
     if (pfs_rwlock->m_class->m_timed)
     {
-      locked_time= get_timer_value(wait_timer) - pfs_rwlock->m_last_written;
+      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);
     }
   }
@@ -1888,7 +2166,7 @@ static void unlock_rwlock_v1(PSI_rwlock
   {
     if (pfs_rwlock->m_class->m_timed)
     {
-      locked_time= get_timer_value(wait_timer) - pfs_rwlock->m_last_read;
+      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);
     }
   }
@@ -1914,90 +2192,130 @@ static void broadcast_cond_v1(PSI_cond*
 static void start_mutex_wait_v1(PSI_mutex_locker* locker,
                                 const char *src_file, uint src_line)
 {
-  PFS_wait_locker *pfs_locker= reinterpret_cast<PFS_wait_locker*> (locker);
-  DBUG_ASSERT(pfs_locker != NULL);
+  PSI_mutex_locker_state *state= reinterpret_cast<PSI_mutex_locker_state*> (locker);
+  DBUG_ASSERT(state != NULL);
+
+  register uint flags= state->m_flags;
+
+  if (flags & STATE_FLAG_TIMED)
+    state->m_timer_start= get_timer_raw_value_and_function(wait_timer, & state->m_timer);
 
-  PFS_events_waits *wait= &pfs_locker->m_waits_current;
-  if (wait->m_timer_state == TIMER_STATE_STARTING)
+  if (flags & STATE_FLAG_WAIT)
   {
-    wait->m_timer_start= get_timer_value(pfs_locker->m_timer_name);
-    wait->m_timer_state= TIMER_STATE_STARTED;
+    PFS_events_waits *wait= reinterpret_cast<PFS_events_waits*> (state->m_wait);
+    DBUG_ASSERT(wait != NULL);
+
+    wait->m_timer_start= state->m_timer_start;
+    wait->m_source_file= src_file;
+    wait->m_source_line= src_line;
   }
-  wait->m_source_file= src_file;
-  wait->m_source_line= src_line;
 }
 
 static void end_mutex_wait_v1(PSI_mutex_locker* locker, int rc)
 {
-  PFS_wait_locker *pfs_locker= reinterpret_cast<PFS_wait_locker*> (locker);
-  DBUG_ASSERT(pfs_locker != NULL);
-  PFS_events_waits *wait= &pfs_locker->m_waits_current;
-
-  if (wait->m_timer_state == TIMER_STATE_STARTED)
-  {
-    wait->m_timer_end= get_timer_value(pfs_locker->m_timer_name);
-    wait->m_timer_state= TIMER_STATE_TIMED;
-  }
-  if (flag_events_waits_history)
-    insert_events_waits_history(wait->m_thread, wait);
-  if (flag_events_waits_history_long)
-    insert_events_waits_history_long(wait);
+  PSI_mutex_locker_state *state= reinterpret_cast<PSI_mutex_locker_state*> (locker);
+  DBUG_ASSERT(state != NULL);
+  ulonglong timer_end= 0;
+  ulonglong wait_time= 0;
+
+  PFS_mutex *mutex= reinterpret_cast<PFS_mutex *> (state->m_mutex);
+  DBUG_ASSERT(mutex != NULL);
+  PFS_thread *thread= reinterpret_cast<PFS_thread *> (state->m_thread);
+
+  register uint flags= state->m_flags;
+
+  if (flags & STATE_FLAG_TIMED)
+  {
+    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_timed(wait_time);
+  }
+  else
+  {
+    /* Aggregate to EVENTS_WAITS_SUMMARY_BY_INSTANCE (counted) */
+    mutex->m_wait_stat.aggregate_counted();
+  }
 
-  if (rc == 0)
+  if (likely(rc == 0))
   {
-    /* Thread safe: we are protected by the instrumented mutex */
-    PFS_mutex *mutex= pfs_locker->m_target.m_mutex;
-    PFS_single_stat_chain *stat= find_per_thread_mutex_class_wait_stat(wait->m_thread, mutex->m_class);
-    mutex->m_owner= wait->m_thread;
-    mutex->m_last_locked= wait->m_timer_end;
-
-    /* If timed then aggregate stats, else increment the value counts only */
-    if (wait->m_timer_state == TIMER_STATE_TIMED)
-    {
-      ulonglong wait_time= wait->m_timer_end - wait->m_timer_start;
-      aggregate_single_stat_chain(&mutex->m_wait_stat, wait_time);
-      aggregate_single_stat_chain(stat, wait_time);
+    mutex->m_owner= thread;
+    mutex->m_last_locked= timer_end;
+  }
+
+  if (flags & STATE_FLAG_THREAD)
+  {
+    PFS_single_stat *event_name_array;
+    event_name_array= thread->m_instr_class_wait_stats;
+    uint index= mutex->m_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_timed(wait_time);
     }
     else
     {
-      increment_single_stat_chain(&mutex->m_wait_stat);
-      increment_single_stat_chain(stat);
+      /* Aggregate to EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME (counted) */
+      event_name_array[index].aggregate_counted();
+    }
+
+    if (flags & STATE_FLAG_WAIT)
+    {
+      PFS_events_waits *wait= reinterpret_cast<PFS_events_waits*> (state->m_wait);
+      DBUG_ASSERT(wait != NULL);
+
+      wait->m_timer_end= timer_end;
+      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_count--;
     }
   }
-  wait->m_thread->m_wait_locker_count--;
 }
 
 static void start_rwlock_rdwait_v1(PSI_rwlock_locker* locker,
                                    const char *src_file, uint src_line)
 {
-  PFS_wait_locker *pfs_locker= reinterpret_cast<PFS_wait_locker*> (locker);
-  DBUG_ASSERT(pfs_locker != NULL);
+  PSI_rwlock_locker_state *state= reinterpret_cast<PSI_rwlock_locker_state*> (locker);
+  DBUG_ASSERT(state != NULL);
+
+  if (state->m_flags & STATE_FLAG_TIMED)
+    state->m_timer_start= get_timer_raw_value_and_function(wait_timer, & state->m_timer);
 
-  PFS_events_waits *wait= &pfs_locker->m_waits_current;
-  if (wait->m_timer_state == TIMER_STATE_STARTING)
+  if (state->m_flags & STATE_FLAG_WAIT)
   {
-    wait->m_timer_start= get_timer_value(pfs_locker->m_timer_name);
-    wait->m_timer_state= TIMER_STATE_STARTED;
+    PFS_events_waits *wait= reinterpret_cast<PFS_events_waits*> (state->m_wait);
+    DBUG_ASSERT(wait != NULL);
+
+    wait->m_timer_start= state->m_timer_start;
+    wait->m_source_file= src_file;
+    wait->m_source_line= src_line;
   }
-  wait->m_source_file= src_file;
-  wait->m_source_line= src_line;
 }
 
 static void end_rwlock_rdwait_v1(PSI_rwlock_locker* locker, int rc)
 {
-  PFS_wait_locker *pfs_locker= reinterpret_cast<PFS_wait_locker*> (locker);
-  DBUG_ASSERT(pfs_locker != NULL);
-  PFS_events_waits *wait= &pfs_locker->m_waits_current;
-
-  if (wait->m_timer_state == TIMER_STATE_STARTED)
-  {
-    wait->m_timer_end= get_timer_value(pfs_locker->m_timer_name);
-    wait->m_timer_state= TIMER_STATE_TIMED;
-  }
-  if (flag_events_waits_history)
-    insert_events_waits_history(wait->m_thread, wait);
-  if (flag_events_waits_history_long)
-    insert_events_waits_history_long(wait);
+  PSI_rwlock_locker_state *state= reinterpret_cast<PSI_rwlock_locker_state*> (locker);
+  DBUG_ASSERT(state != NULL);
+  ulonglong timer_end= 0;
+  ulonglong wait_time= 0;
+
+  PFS_rwlock *rwlock= reinterpret_cast<PFS_rwlock *> (state->m_rwlock);
+
+  if (state->m_flags & STATE_FLAG_TIMED)
+  {
+    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_timed(wait_time);
+  }
+  else
+  {
+    /* Aggregate to EVENTS_WAITS_SUMMARY_BY_INSTANCE (counted) */
+    rwlock->m_wait_stat.aggregate_counted();
+  }
 
   if (rc == 0)
   {
@@ -2008,225 +2326,324 @@ static void end_rwlock_rdwait_v1(PSI_rwl
       The statistics generated are not safe, which is why they are
       just statistics, not facts.
     */
-    PFS_rwlock *rwlock= pfs_locker->m_target.m_rwlock;
-    PFS_single_stat_chain *stat= find_per_thread_rwlock_class_wait_stat(wait->m_thread, rwlock->m_class);
-
     if (rwlock->m_readers == 0)
-      rwlock->m_last_read= wait->m_timer_end;
+      rwlock->m_last_read= timer_end;
     rwlock->m_writer= NULL;
     rwlock->m_readers++;
+  }
+
+  if (state->m_flags & STATE_FLAG_THREAD)
+  {
+    PFS_thread *thread= reinterpret_cast<PFS_thread *> (state->m_thread);
+    DBUG_ASSERT(thread != NULL);
 
-    /* If timed then aggregate stats, else increment the value counts only */
-    if (wait->m_timer_state == TIMER_STATE_TIMED)
+    PFS_single_stat *event_name_array;
+    event_name_array= thread->m_instr_class_wait_stats;
+    uint index= rwlock->m_class->m_event_name_index;
+
+    if (state->m_flags & STATE_FLAG_TIMED)
     {
-      ulonglong wait_time= wait->m_timer_end - wait->m_timer_start;
-      aggregate_single_stat_chain(&rwlock->m_wait_stat, wait_time);
-      aggregate_single_stat_chain(stat, wait_time);
+      /* Aggregate to EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME (timed) */
+      event_name_array[index].aggregate_timed(wait_time);
     }
     else
     {
-      increment_single_stat_chain(&rwlock->m_wait_stat);
-      increment_single_stat_chain(stat);
+      /* Aggregate to EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME (counted) */
+      event_name_array[index].aggregate_counted();
+    }
+
+    if (state->m_flags & STATE_FLAG_WAIT)
+    {
+      PFS_events_waits *wait= reinterpret_cast<PFS_events_waits*> (state->m_wait);
+      DBUG_ASSERT(wait != NULL);
+
+      wait->m_timer_end= timer_end;
+      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_count--;
     }
   }
-  wait->m_thread->m_wait_locker_count--;
 }
 
 static void start_rwlock_wrwait_v1(PSI_rwlock_locker* locker,
                                    const char *src_file, uint src_line)
 {
-  PFS_wait_locker *pfs_locker= reinterpret_cast<PFS_wait_locker*> (locker);
-  DBUG_ASSERT(pfs_locker != NULL);
+  PSI_rwlock_locker_state *state= reinterpret_cast<PSI_rwlock_locker_state*> (locker);
+  DBUG_ASSERT(state != NULL);
+
+  if (state->m_flags & STATE_FLAG_TIMED)
+    state->m_timer_start= get_timer_raw_value_and_function(wait_timer, & state->m_timer);
 
-  PFS_events_waits *wait= &pfs_locker->m_waits_current;
-  if (wait->m_timer_state == TIMER_STATE_STARTING)
+  if (state->m_flags & STATE_FLAG_WAIT)
   {
-    wait->m_timer_start= get_timer_value(pfs_locker->m_timer_name);
-    wait->m_timer_state= TIMER_STATE_STARTED;
+    PFS_events_waits *wait= reinterpret_cast<PFS_events_waits*> (state->m_wait);
+    DBUG_ASSERT(wait != NULL);
+
+    wait->m_timer_start= state->m_timer_start;
+    wait->m_source_file= src_file;
+    wait->m_source_line= src_line;
   }
-  wait->m_source_file= src_file;
-  wait->m_source_line= src_line;
 }
 
 static void end_rwlock_wrwait_v1(PSI_rwlock_locker* locker, int rc)
 {
-  PFS_wait_locker *pfs_locker= reinterpret_cast<PFS_wait_locker*> (locker);
-  DBUG_ASSERT(pfs_locker != NULL);
-  PFS_events_waits *wait= &pfs_locker->m_waits_current;
-
-  if (wait->m_timer_state == TIMER_STATE_STARTED)
-  {
-    wait->m_timer_end= get_timer_value(pfs_locker->m_timer_name);
-    wait->m_timer_state= TIMER_STATE_TIMED;
-  }
-  if (flag_events_waits_history)
-    insert_events_waits_history(wait->m_thread, wait);
-  if (flag_events_waits_history_long)
-    insert_events_waits_history_long(wait);
+  PSI_rwlock_locker_state *state= reinterpret_cast<PSI_rwlock_locker_state*> (locker);
+  DBUG_ASSERT(state != NULL);
+  ulonglong timer_end= 0;
+  ulonglong wait_time= 0;
+
+  PFS_rwlock *rwlock= reinterpret_cast<PFS_rwlock *> (state->m_rwlock);
+  PFS_thread *thread= reinterpret_cast<PFS_thread *> (state->m_thread);
+
+  if (state->m_flags & STATE_FLAG_TIMED)
+  {
+    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_timed(wait_time);
+  }
+  else
+  {
+    /* Aggregate to EVENTS_WAITS_SUMMARY_BY_INSTANCE (counted) */
+    rwlock->m_wait_stat.aggregate_counted();
+  }
 
-  if (rc == 0)
+  if (likely(rc == 0))
   {
     /* Thread safe : we are protected by the instrumented rwlock */
-    PFS_rwlock *rwlock= pfs_locker->m_target.m_rwlock;
-    PFS_single_stat_chain *stat= find_per_thread_rwlock_class_wait_stat(wait->m_thread, rwlock->m_class);
-    rwlock->m_writer= wait->m_thread;
-    rwlock->m_last_written= wait->m_timer_end;
+    rwlock->m_writer= thread;
+    rwlock->m_last_written= timer_end;
     /* Reset the readers stats, they could be off */
     rwlock->m_readers= 0;
     rwlock->m_last_read= 0;
+  }
 
-    /* If timed then aggregate stats, else increment the value counts only */
-    if (wait->m_timer_state == TIMER_STATE_TIMED)
+  if (state->m_flags & STATE_FLAG_THREAD)
+  {
+    PFS_single_stat *event_name_array;
+    event_name_array= thread->m_instr_class_wait_stats;
+    uint index= rwlock->m_class->m_event_name_index;
+
+    if (state->m_flags & STATE_FLAG_TIMED)
     {
-      ulonglong wait_time= wait->m_timer_end - wait->m_timer_start;
-      aggregate_single_stat_chain(&rwlock->m_wait_stat, wait_time);
-      aggregate_single_stat_chain(stat, wait_time);
+      /* Aggregate to EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME (timed) */
+      event_name_array[index].aggregate_timed(wait_time);
     }
     else
     {
-      increment_single_stat_chain(&rwlock->m_wait_stat);
-      increment_single_stat_chain(stat);
+      /* Aggregate to EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME (counted) */
+      event_name_array[index].aggregate_counted();
+    }
+
+    if (state->m_flags & STATE_FLAG_WAIT)
+    {
+      PFS_events_waits *wait= reinterpret_cast<PFS_events_waits*> (state->m_wait);
+      DBUG_ASSERT(wait != NULL);
+
+      wait->m_timer_end= timer_end;
+      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_count--;
     }
   }
-  wait->m_thread->m_wait_locker_count--;
 }
 
 static void start_cond_wait_v1(PSI_cond_locker* locker,
                                const char *src_file, uint src_line)
 {
-  PFS_wait_locker *pfs_locker= reinterpret_cast<PFS_wait_locker*> (locker);
-  DBUG_ASSERT(pfs_locker != NULL);
+  PSI_cond_locker_state *state= reinterpret_cast<PSI_cond_locker_state*> (locker);
+  DBUG_ASSERT(state != NULL);
 
-  PFS_events_waits *wait= &pfs_locker->m_waits_current;
-  if (wait->m_timer_state == TIMER_STATE_STARTING)
+  if (state->m_flags & STATE_FLAG_TIMED)
+    state->m_timer_start= get_timer_raw_value_and_function(wait_timer, & state->m_timer);
+
+  if (state->m_flags & STATE_FLAG_WAIT)
   {
-    wait->m_timer_start= get_timer_value(pfs_locker->m_timer_name);
-    wait->m_timer_state= TIMER_STATE_STARTED;
+    PFS_events_waits *wait= reinterpret_cast<PFS_events_waits*> (state->m_wait);
+    DBUG_ASSERT(wait != NULL);
+
+    wait->m_timer_start= state->m_timer_start;
+    wait->m_source_file= src_file;
+    wait->m_source_line= src_line;
   }
-  wait->m_source_file= src_file;
-  wait->m_source_line= src_line;
 }
 
 static void end_cond_wait_v1(PSI_cond_locker* locker, int rc)
 {
-  PFS_wait_locker *pfs_locker= reinterpret_cast<PFS_wait_locker*> (locker);
-  DBUG_ASSERT(pfs_locker != NULL);
-  PFS_events_waits *wait= &pfs_locker->m_waits_current;
-
-  if (wait->m_timer_state == TIMER_STATE_STARTED)
-  {
-    wait->m_timer_end= get_timer_value(pfs_locker->m_timer_name);
-    wait->m_timer_state= TIMER_STATE_TIMED;
-  }
-  if (flag_events_waits_history)
-    insert_events_waits_history(wait->m_thread, wait);
-  if (flag_events_waits_history_long)
-    insert_events_waits_history_long(wait);
+  PSI_cond_locker_state *state= reinterpret_cast<PSI_cond_locker_state*> (locker);
+  DBUG_ASSERT(state != NULL);
+  ulonglong timer_end= 0;
+  ulonglong wait_time= 0;
+
+  PFS_cond *cond= reinterpret_cast<PFS_cond *> (state->m_cond);
+  /* PFS_mutex *mutex= reinterpret_cast<PFS_mutex *> (state->m_mutex); */
+
+  if (state->m_flags & STATE_FLAG_TIMED)
+  {
+    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_timed(wait_time);
+  }
+  else
+  {
+    /* Aggregate to EVENTS_WAITS_SUMMARY_BY_INSTANCE (counted) */
+    cond->m_wait_stat.aggregate_counted();
+  }
 
-  if (rc == 0)
+  if (state->m_flags & STATE_FLAG_THREAD)
   {
-    /*
-      Not thread safe, race conditions will occur.
-      A first race condition is:
-      - thread 1 waits on cond A
-      - thread 2 waits on cond A
-      threads 1 and 2 compete when updating the same cond A
-      statistics, possibly missing a min / max / sum / count.
-      A second race condition is:
-      - thread 1 waits on cond A
-      - thread 2 destroys cond A
-      - thread 2 or 3 creates cond B in the same condition slot
-      thread 1 will then aggregate statistics about defunct A
-      in condition B.
-      This is accepted, the data will be slightly inaccurate.
-    */
-    PFS_cond *cond= pfs_locker->m_target.m_cond;
-    PFS_single_stat_chain *stat= find_per_thread_cond_class_wait_stat(wait->m_thread, cond->m_class);
+    PFS_thread *thread= reinterpret_cast<PFS_thread *> (state->m_thread);
+    DBUG_ASSERT(thread != NULL);
 
-    /* If timed then aggregate stats, else increment the value counts only */
-    if (wait->m_timer_state == TIMER_STATE_TIMED)
+    PFS_single_stat *event_name_array;
+    event_name_array= thread->m_instr_class_wait_stats;
+    uint index= cond->m_class->m_event_name_index;
+
+    if (state->m_flags & STATE_FLAG_TIMED)
     {
-      ulonglong wait_time= wait->m_timer_end - wait->m_timer_start;
-      aggregate_single_stat_chain(&cond->m_wait_stat, wait_time);
-      aggregate_single_stat_chain(stat, wait_time);
+      /* Aggregate to EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME (timed) */
+      event_name_array[index].aggregate_timed(wait_time);
     }
     else
     {
-      increment_single_stat_chain(&cond->m_wait_stat);
-      increment_single_stat_chain(stat);
+      /* Aggregate to EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME (counted) */
+      event_name_array[index].aggregate_counted();
+    }
+
+    if (state->m_flags & STATE_FLAG_WAIT)
+    {
+      PFS_events_waits *wait= reinterpret_cast<PFS_events_waits*> (state->m_wait);
+      DBUG_ASSERT(wait != NULL);
+
+      wait->m_timer_end= timer_end;
+      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_count--;
     }
   }
-  wait->m_thread->m_wait_locker_count--;
 }
 
 static void start_table_wait_v1(PSI_table_locker* locker, uint index,
                                 const char *src_file, uint src_line)
 {
-  PFS_wait_locker *pfs_locker= reinterpret_cast<PFS_wait_locker*> (locker);
-  DBUG_ASSERT(pfs_locker != NULL);
+  PSI_table_locker_state *state= reinterpret_cast<PSI_table_locker_state*> (locker);
+  DBUG_ASSERT(state != NULL);
+
+  register uint flags= state->m_flags;
+
+  if (flags & STATE_FLAG_TIMED)
+    state->m_timer_start= get_timer_raw_value_and_function(wait_timer, & state->m_timer);
 
-  PFS_events_waits *wait= &pfs_locker->m_waits_current;
-  if (wait->m_timer_state == TIMER_STATE_STARTING)
+  if (flags & STATE_FLAG_WAIT)
   {
-    wait->m_timer_start= get_timer_value(pfs_locker->m_timer_name);
-    wait->m_timer_state= TIMER_STATE_STARTED;
+    PFS_events_waits *wait= reinterpret_cast<PFS_events_waits*> (state->m_wait);
+    DBUG_ASSERT(wait != NULL);
+
+    wait->m_timer_start= state->m_timer_start;
+    wait->m_source_file= src_file;
+    wait->m_source_line= src_line;
   }
-  wait->m_source_file= src_file;
-  wait->m_source_line= src_line;
-  PFS_table_share *share= pfs_locker->m_target.m_table->m_share;
-  wait->m_object_type= share->get_object_type();
-  wait->m_schema_name= share->m_schema_name;
-  wait->m_schema_name_length= share->m_schema_name_length;
-  wait->m_object_name= share->m_table_name;
-  wait->m_object_name_length= share->m_table_name_length;
-  /* FIXME: revise this */
-  if (share->get_object_type() == OBJECT_TYPE_TEMPORARY_TABLE)
-    wait->m_index= MAX_KEY;
-  else
-    wait->m_index= index;
+
+  state->m_index= index;
 }
 
 static void end_table_wait_v1(PSI_table_locker* locker)
 {
-  PFS_wait_locker *pfs_locker= reinterpret_cast<PFS_wait_locker*> (locker);
-  DBUG_ASSERT(pfs_locker != NULL);
-  PFS_events_waits *wait= &pfs_locker->m_waits_current;
-
-  if (wait->m_timer_state == TIMER_STATE_STARTED)
-  {
-    wait->m_timer_end= get_timer_value(pfs_locker->m_timer_name);
-    wait->m_timer_state= TIMER_STATE_TIMED;
+  PSI_table_locker_state *state= reinterpret_cast<PSI_table_locker_state*> (locker);
+  DBUG_ASSERT(state != NULL);
+  ulonglong timer_end= 0;
+  ulonglong wait_time= 0;
+
+  PFS_table *table= reinterpret_cast<PFS_table *> (state->m_table);
+  DBUG_ASSERT(table != NULL);
+  PFS_instr_class *klass= reinterpret_cast<PFS_instr_class *> (state->m_class);
+  DBUG_ASSERT(klass != NULL);
+
+  PFS_single_stat *stat;
+
+  switch (state->m_operation)
+  {
+  case PSI_TABLE_FETCH_ROW:
+    DBUG_ASSERT((state->m_index < table->m_share->m_key_count) ||
+                (state->m_index == MAX_KEY));
+    stat= & table->m_table_stat.m_index_stat[state->m_index].m_fetch;
+    break;
+  case PSI_TABLE_WRITE_ROW:
+    DBUG_ASSERT((state->m_index < table->m_share->m_key_count) ||
+                (state->m_index == MAX_KEY));
+    stat= & table->m_table_stat.m_index_stat[state->m_index].m_insert;
+    break;
+  case PSI_TABLE_UPDATE_ROW:
+    DBUG_ASSERT((state->m_index < table->m_share->m_key_count) ||
+                (state->m_index == MAX_KEY));
+    stat= & table->m_table_stat.m_index_stat[state->m_index].m_update;
+    break;
+  case PSI_TABLE_DELETE_ROW:
+    DBUG_ASSERT((state->m_index < table->m_share->m_key_count) ||
+                (state->m_index == MAX_KEY));
+    stat= & table->m_table_stat.m_index_stat[state->m_index].m_delete;
+    break;
+  case PSI_TABLE_LOCK:
+  case PSI_TABLE_EXTERNAL_LOCK:
+  default:
+    DBUG_ASSERT(false);
+    stat= NULL;
+    break;
   }
-  if (flag_events_waits_history)
-    insert_events_waits_history(wait->m_thread, wait);
-  if (flag_events_waits_history_long)
-    insert_events_waits_history_long(wait);
 
-  PFS_table *table= pfs_locker->m_target.m_table;
+  register uint flags= state->m_flags;
 
-  /* If timed then aggregate stats, else increment the value counts only */
-  if (wait->m_timer_state == TIMER_STATE_TIMED)
+  if (flags & STATE_FLAG_TIMED)
   {
-    ulonglong wait_time= wait->m_timer_end - wait->m_timer_start;
-    aggregate_single_stat_chain(&table->m_wait_stat, wait_time);
+    timer_end= state->m_timer();
+    wait_time= timer_end - state->m_timer_start;
+    stat->aggregate_timed(wait_time);
   }
   else
   {
-    increment_single_stat_chain(&table->m_wait_stat);
+    stat->aggregate_counted();
   }
 
-  /*
-    There is currently no per table and per thread aggregation.
-    The number of tables in the application is arbitrary, and may be high.
-    The number of slots per thread to hold aggregates is fixed,
-    and is constrained by memory.
-    Implementing a per thread and per table aggregate has not been
-    decided yet.
-    If it's implemented, it's likely that the user will have to specify,
-    per table name, if the aggregate per thread is to be computed or not.
-    This will mean a SETUP_ table.
-  */
-  wait->m_thread->m_wait_locker_count--;
+  if (flags & STATE_FLAG_THREAD)
+  {
+    PFS_thread *thread= reinterpret_cast<PFS_thread *> (state->m_thread);
+    DBUG_ASSERT(thread != NULL);
+
+    PFS_single_stat *event_name_array;
+    event_name_array= thread->m_instr_class_wait_stats;
+    uint index= klass->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_timed(wait_time);
+    }
+    else
+    {
+      /* Aggregate to EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME (counted) */
+      event_name_array[index].aggregate_counted();
+    }
+
+    if (flags & STATE_FLAG_WAIT)
+    {
+      PFS_events_waits *wait= reinterpret_cast<PFS_events_waits*> (state->m_wait);
+      DBUG_ASSERT(wait != NULL);
+
+      wait->m_timer_end= timer_end;
+      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_count--;
+    }
+  }
 }
 
 static void start_file_wait_v1(PSI_file_locker *locker,
@@ -2241,13 +2658,12 @@ static PSI_file* start_file_open_wait_v1
                                          const char *src_file,
                                          uint src_line)
 {
-  PFS_wait_locker *pfs_locker= reinterpret_cast<PFS_wait_locker*> (locker);
-  DBUG_ASSERT(pfs_locker != NULL);
+  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);
 
-  PFS_file *pfs_file= pfs_locker->m_target.m_file;
-  return reinterpret_cast<PSI_file*> (pfs_file);
+  return state->m_file;
 }
 
 static void end_file_open_wait_v1(PSI_file_locker *locker)
@@ -2259,12 +2675,12 @@ static void end_file_open_wait_and_bind_
   (PSI_file_locker *locker, File file)
 {
   int index= (int) file;
-  PFS_wait_locker *pfs_locker= reinterpret_cast<PFS_wait_locker*> (locker);
-  DBUG_ASSERT(pfs_locker != NULL);
+  PSI_file_locker_state *state= reinterpret_cast<PSI_file_locker_state*> (locker);
+  DBUG_ASSERT(state != NULL);
 
   end_file_wait_v1(locker, 0);
 
-  PFS_file *pfs_file= pfs_locker->m_target.m_file;
+  PFS_file *pfs_file= reinterpret_cast<PFS_file*> (state->m_file);
   DBUG_ASSERT(pfs_file != NULL);
 
   if (likely(index >= 0))
@@ -2275,7 +2691,9 @@ static void end_file_open_wait_and_bind_
       file_handle_lost++;
   }
   else
+  {
     release_file(pfs_file);
+  }
 }
 
 static void start_file_wait_v1(PSI_file_locker *locker,
@@ -2283,83 +2701,108 @@ static void start_file_wait_v1(PSI_file_
                                const char *src_file,
                                uint src_line)
 {
-  PFS_wait_locker *pfs_locker= reinterpret_cast<PFS_wait_locker*> (locker);
-  DBUG_ASSERT(pfs_locker != NULL);
+  PSI_file_locker_state *state= reinterpret_cast<PSI_file_locker_state*> (locker);
+  DBUG_ASSERT(state != NULL);
+
+  register uint flags= state->m_flags;
+
+  if (flags & STATE_FLAG_TIMED)
+    state->m_timer_start= get_timer_raw_value_and_function(wait_timer, & state->m_timer);
 
-  PFS_events_waits *wait= &pfs_locker->m_waits_current;
-  if (wait->m_timer_state == TIMER_STATE_STARTING)
+  if (flags & STATE_FLAG_WAIT)
   {
-    wait->m_timer_start= get_timer_value(pfs_locker->m_timer_name);
-    wait->m_timer_state= TIMER_STATE_STARTED;
+    PFS_events_waits *wait= reinterpret_cast<PFS_events_waits*> (state->m_wait);
+    DBUG_ASSERT(wait != NULL);
+
+    wait->m_timer_start= state->m_timer_start;
+    wait->m_source_file= src_file;
+    wait->m_source_line= src_line;
+    wait->m_number_of_bytes= count;
   }
-  wait->m_source_file= src_file;
-  wait->m_source_line= src_line;
-  wait->m_number_of_bytes= count;
 }
 
 static void end_file_wait_v1(PSI_file_locker *locker,
                              size_t count)
 {
-  PFS_wait_locker *pfs_locker= reinterpret_cast<PFS_wait_locker*> (locker);
-  DBUG_ASSERT(pfs_locker != NULL);
-  PFS_events_waits *wait= &pfs_locker->m_waits_current;
-
-  wait->m_number_of_bytes= count;
-  if (wait->m_timer_state == TIMER_STATE_STARTED)
-  {
-    wait->m_timer_end= get_timer_value(pfs_locker->m_timer_name);
-    wait->m_timer_state= TIMER_STATE_TIMED;
-  }
-  if (flag_events_waits_history)
-    insert_events_waits_history(wait->m_thread, wait);
-  if (flag_events_waits_history_long)
-    insert_events_waits_history_long(wait);
-
-  PFS_file *file= pfs_locker->m_target.m_file;
-  PFS_single_stat_chain *stat= find_per_thread_file_class_wait_stat(wait->m_thread, file->m_class);
-
-  /* If timed then aggregate stats, else increment the value counts only */
-  if (wait->m_timer_state == TIMER_STATE_TIMED)
-  {
-    ulonglong wait_time= wait->m_timer_end - wait->m_timer_start;
-    aggregate_single_stat_chain(&file->m_wait_stat, wait_time);
-    aggregate_single_stat_chain(stat, wait_time);
+  PSI_file_locker_state *state= reinterpret_cast<PSI_file_locker_state*> (locker);
+  DBUG_ASSERT(state != NULL);
+  ulonglong timer_end= 0;
+  ulonglong wait_time= 0;
+
+  PFS_file *file= reinterpret_cast<PFS_file *> (state->m_file);
+  DBUG_ASSERT(file != NULL);
+  PFS_thread *thread= reinterpret_cast<PFS_thread *> (state->m_thread);
+
+  register uint flags= state->m_flags;
+
+  if (flags & STATE_FLAG_TIMED)
+  {
+    timer_end= state->m_timer();
+    wait_time= timer_end - state->m_timer_start;
+    /* Aggregate to EVENTS_WAITS_SUMMARY_BY_INSTANCE (timed) */
+    file->m_wait_stat.aggregate_timed(wait_time);
   }
   else
   {
-    increment_single_stat_chain(&file->m_wait_stat);
-    increment_single_stat_chain(stat);
+    /* Aggregate to EVENTS_WAITS_SUMMARY_BY_INSTANCE (counted) */
+    file->m_wait_stat.aggregate_counted();
   }
 
-  PFS_file_class *klass= file->m_class;
+  if (flags & STATE_FLAG_THREAD)
+  {
+    DBUG_ASSERT(thread != NULL);
+
+    PFS_single_stat *event_name_array;
+    event_name_array= thread->m_instr_class_wait_stats;
+    uint index= file->m_class->m_event_name_index;
 
-  switch(wait->m_operation)
+    if (flags & STATE_FLAG_TIMED)
+    {
+      /* Aggregate to EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME (timed) */
+      event_name_array[index].aggregate_timed(wait_time);
+    }
+    else
+    {
+      /* Aggregate to EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME (counted) */
+      event_name_array[index].aggregate_counted();
+    }
+
+    if (state->m_flags & STATE_FLAG_WAIT)
+    {
+      PFS_events_waits *wait= reinterpret_cast<PFS_events_waits*> (state->m_wait);
+      DBUG_ASSERT(wait != NULL);
+
+      wait->m_timer_end= timer_end;
+      wait->m_number_of_bytes= count;
+      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_count--;
+    }
+  }
+
+  /* FIXME: Have file aggregates for every operation */
+  switch(state->m_operation)
   {
-  case OPERATION_TYPE_FILEREAD:
-    file->m_file_stat.m_count_read++;
-    file->m_file_stat.m_read_bytes+= count;
-    klass->m_file_stat.m_count_read++;
-    klass->m_file_stat.m_read_bytes+= count;
+  case PSI_FILE_READ:
+    file->m_file_stat.m_io_stat.aggregate_read(count);
     break;
-  case OPERATION_TYPE_FILEWRITE:
-    file->m_file_stat.m_count_write++;
-    file->m_file_stat.m_write_bytes+= count;
-    klass->m_file_stat.m_count_write++;
-    klass->m_file_stat.m_write_bytes+= count;
+  case PSI_FILE_WRITE:
+    file->m_file_stat.m_io_stat.aggregate_write(count);
     break;
-  case OPERATION_TYPE_FILECLOSE:
-  case OPERATION_TYPE_FILESTREAMCLOSE:
-  case OPERATION_TYPE_FILESTAT:
-    release_file(pfs_locker->m_target.m_file);
+  case PSI_FILE_CLOSE:
+  case PSI_FILE_STREAM_CLOSE:
+  case PSI_FILE_STAT:
+    release_file(file);
     break;
-  case OPERATION_TYPE_FILEDELETE:
-    destroy_file(wait->m_thread, pfs_locker->m_target.m_file);
+  case PSI_FILE_DELETE:
+    DBUG_ASSERT(thread != NULL);
+    destroy_file(thread, file);
     break;
   default:
     break;
   }
-
-  wait->m_thread->m_wait_locker_count--;
 }
 
 PSI_v1 PFS_v1=

=== modified file 'storage/perfschema/pfs_defaults.cc'
--- a/storage/perfschema/pfs_defaults.cc	2010-07-02 16:15:37 +0000
+++ b/storage/perfschema/pfs_defaults.cc	2010-09-23 16:08:54 +0000
@@ -22,6 +22,7 @@
 #include "pfs_defaults.h"
 #include "pfs_instr.h"
 #include "pfs_setup_actor.h"
+#include "pfs_setup_object.h"
 
 static PSI_thread_key key;
 static PSI_thread_info info= { &key, "setup", PSI_FLAG_GLOBAL };
@@ -44,6 +45,23 @@ void install_default_setup(PSI_bootstrap
   /* Enable all users on all hosts by default */
   insert_setup_actor(&percent, &percent, &percent);
 
+#if 0
+  /* Disable system tables by default */
+  String mysql_db("mysql", 5, &my_charset_utf8_bin);
+  insert_setup_object(OBJECT_TYPE_TABLE, &mysql_db, &percent, false, false);
+#endif
+  /* Disable performance/information schema tables. */
+  String PS_db("performance_schema", 18, &my_charset_utf8_bin);
+  String IS_db("information_schema", 18, &my_charset_utf8_bin);
+  insert_setup_object(OBJECT_TYPE_TABLE, &PS_db, &percent, false, false);
+  insert_setup_object(OBJECT_TYPE_TABLE, &IS_db, &percent, false, false);
+  /* Enable every other tables */
+  insert_setup_object(OBJECT_TYPE_TABLE, &percent, &percent, true, true);
+#if 0
+  /* Disable every temporary tables */
+  insert_setup_object(OBJECT_TYPE_TEMPORARY_TABLE, &percent, &percent, false, false);
+#endif
+
   psi->delete_current_thread();
 }
 

=== modified file 'storage/perfschema/pfs_engine_table.cc'
--- a/storage/perfschema/pfs_engine_table.cc	2010-09-01 22:59:33 +0000
+++ b/storage/perfschema/pfs_engine_table.cc	2010-09-23 16:08:54 +0000
@@ -24,11 +24,13 @@
 #include "table_setup_actors.h"
 #include "table_setup_consumers.h"
 #include "table_setup_instruments.h"
+#include "table_setup_objects.h"
 #include "table_setup_timers.h"
 #include "table_performance_timers.h"
-#include "table_threads.h"
 #include "table_events_waits_summary.h"
+#include "table_ews_by_thread_by_event_name.h"
 #include "table_ews_global_by_event_name.h"
+#include "table_os_global_by_type.h"
 #include "table_sync_instances.h"
 #include "table_file_instances.h"
 #include "table_file_summary.h"
@@ -38,6 +40,7 @@
 #include "pfs_column_values.h"
 #include "pfs_instr.h"
 #include "pfs_setup_actor.h"
+#include "pfs_setup_object.h"
 #include "pfs_global.h"
 
 #include "sql_base.h"                           // close_thread_tables
@@ -55,17 +58,19 @@ static PFS_engine_table_share *all_share
   &table_events_waits_history_long::m_share,
   &table_events_waits_history::m_share,
   &table_events_waits_summary_by_instance::m_share,
-  &table_events_waits_summary_by_thread_by_event_name::m_share,
+  &table_ews_by_thread_by_event_name::m_share,
   &table_ews_global_by_event_name::m_share,
   &table_file_instances::m_share,
   &table_file_summary_by_event_name::m_share,
   &table_file_summary_by_instance::m_share,
   &table_mutex_instances::m_share,
+  &table_os_global_by_type::m_share,
   &table_performance_timers::m_share,
   &table_rwlock_instances::m_share,
   &table_setup_actors::m_share,
   &table_setup_consumers::m_share,
   &table_setup_instruments::m_share,
+  &table_setup_objects::m_share,
   &table_setup_timers::m_share,
   &table_threads::m_share,
   NULL
@@ -82,7 +87,7 @@ void PFS_engine_table_share::check_all_t
   DBUG_EXECUTE_IF("tampered_perfschema_table1",
                   {
                     /* Hack SETUP_INSTRUMENT, incompatible change. */
-                    all_shares[15]->m_field_def->count++;
+                    all_shares[16]->m_field_def->count++;
                   });
 
   for (current= &all_shares[0]; (*current) != NULL; current++)
@@ -636,11 +641,11 @@ bool pfs_show_status(handlerton *hton, T
     switch (i){
     case 0:
       name= "EVENTS_WAITS_CURRENT.ROW_SIZE";
-      size= sizeof(PFS_wait_locker);
+      size= sizeof(PFS_events_waits);
       break;
     case 1:
       name= "EVENTS_WAITS_CURRENT.ROW_COUNT";
-      size= LOCKER_STACK_SIZE * thread_max;
+      size= WAIT_STACK_SIZE * thread_max;
       break;
     case 2:
       name= "EVENTS_WAITS_HISTORY.ROW_SIZE";
@@ -814,15 +819,15 @@ bool pfs_show_status(handlerton *hton, T
       break;
     case 41:
       name= "EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME.ROW_SIZE";
-      size= sizeof(PFS_single_stat_chain);
+      size= sizeof(PFS_single_stat);
       break;
     case 42:
       name= "EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME.ROW_COUNT";
-      size= thread_max * instr_class_per_thread;
+      size= thread_max * max_instrument_class;
       break;
     case 43:
       name= "EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME.MEMORY";
-      size= thread_max * instr_class_per_thread * sizeof(PFS_single_stat_chain);
+      size= thread_max * max_instrument_class * sizeof(PFS_single_stat);
       total_memory+= size;
       break;
     case 44:
@@ -864,11 +869,37 @@ bool pfs_show_status(handlerton *hton, T
       size= setup_actor_max * sizeof(PFS_setup_actor);
       total_memory+= size;
       break;
+    case 53:
+      name= "SETUP_OBJECTS.ROW_SIZE";
+      size= sizeof(PFS_setup_object);
+      break;
+    case 54:
+      name= "SETUP_OBJECTS.ROW_COUNT";
+      size= setup_object_max;
+      break;
+    case 55:
+      name= "SETUP_OBJECTS.MEMORY";
+      size= setup_object_max * sizeof(PFS_setup_object);
+      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= max_instrument_class;
+      break;
+    case 58:
+      name= "EVENTS_WAITS_SUMMARY_GLOBAL_BY_EVENT_NAME.MEMORY";
+      size= max_instrument_class * sizeof(PFS_single_stat);
+      total_memory+= size;
+      break;
     /*
       This case must be last,
       for aggregation in total_memory.
     */
-    case 53:
+    case 59:
       name= "PERFORMANCE_SCHEMA.MEMORY";
       size= total_memory;
       /* This will fail if something is not advertised here */

=== modified file 'storage/perfschema/pfs_events_waits.cc'
--- a/storage/perfschema/pfs_events_waits.cc	2010-08-12 10:21:22 +0000
+++ b/storage/perfschema/pfs_events_waits.cc	2010-09-23 16:08:54 +0000
@@ -33,18 +33,10 @@ bool flag_events_waits_current= true;
 bool flag_events_waits_history= true;
 /** Consumer flag for table EVENTS_WAITS_HISTORY_LONG. */
 bool flag_events_waits_history_long= true;
-/** Consumer flag for table EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME. */
-bool flag_events_waits_summary_by_thread_by_event_name= true;
-/** Consumer flag for table EVENTS_WAITS_SUMMARY_BY_EVENT_NAME. */
-bool flag_events_waits_summary_by_event_name= true;
-/** Consumer flag for table EVENTS_WAITS_SUMMARY_BY_INSTANCE. */
-bool flag_events_waits_summary_by_instance= true;
-bool flag_events_locks_summary_by_event_name= true;
-bool flag_events_locks_summary_by_instance= true;
-/** Consumer flag for table FILE_SUMMARY_BY_EVENT_NAME. */
-bool flag_file_summary_by_event_name= true;
-/** Consumer flag for table FILE_SUMMARY_BY_INSTANCE. */
-bool flag_file_summary_by_instance= true;
+/** Consumer flag for the global instrumentation. */
+bool flag_global_instrumentation= true;
+/** Consumer flag for the per thread instrumentation. */
+bool flag_thread_instrumentation= true;
 
 /** True if EVENTS_WAITS_HISTORY_LONG circular buffer is full. */
 bool events_waits_history_long_full= false;
@@ -138,11 +130,11 @@ void reset_events_waits_current(void)
 
   for ( ; pfs_thread < pfs_thread_last; pfs_thread++)
   {
-    PFS_wait_locker *locker= pfs_thread->m_wait_locker_stack;
-    PFS_wait_locker *locker_last= locker + LOCKER_STACK_SIZE;
+    PFS_events_waits *pfs_wait= pfs_thread->m_events_waits_stack;
+    PFS_events_waits *pfs_wait_last= pfs_wait + WAIT_STACK_SIZE;
 
-    for ( ; locker < locker_last; locker++)
-      locker->m_waits_current.m_wait_class= NO_WAIT_CLASS;
+    for ( ; pfs_wait < pfs_wait_last; pfs_wait++)
+      pfs_wait->m_wait_class= NO_WAIT_CLASS;
   }
 }
 

=== modified file 'storage/perfschema/pfs_events_waits.h'
--- a/storage/perfschema/pfs_events_waits.h	2010-08-12 10:21:22 +0000
+++ b/storage/perfschema/pfs_events_waits.h	2010-09-23 16:08:54 +0000
@@ -43,31 +43,6 @@ enum events_waits_class
   WAIT_CLASS_FILE
 };
 
-/** State of a timer. */
-enum timer_state
-{
-  /**
-    Not timed.
-    In this state, TIMER_START, TIMER_END and TIMER_WAIT are NULL.
-  */
-  TIMER_STATE_UNTIMED,
-  /**
-    About to start.
-    In this state, TIMER_START, TIMER_END and TIMER_WAIT are NULL.
-  */
-  TIMER_STATE_STARTING,
-  /**
-    Started, but not yet ended.
-    In this state, TIMER_START has a value, TIMER_END and TIMER_WAIT are NULL.
-  */
-  TIMER_STATE_STARTED,
-  /**
-    Ended.
-    In this state, TIMER_START, TIMER_END and TIMER_WAIT have a value.
-  */
-  TIMER_STATE_TIMED
-};
-
 /** Target object a wait event is waiting on. */
 union events_waits_target
 {
@@ -102,8 +77,6 @@ struct PFS_events_waits
   PFS_thread *m_thread;
   /** Instrument metadata. */
   PFS_instr_class *m_class;
-  /** Timer state. */
-  enum timer_state m_timer_state;
   /** Event id. */
   ulonglong m_event_id;
   /** Nesting event id. */
@@ -150,21 +123,6 @@ struct PFS_events_waits
   ulong m_flags;
 };
 
-/**
-  A wait locker.
-  A locker is a transient helper structure used by the instrumentation
-  during the recording of a wait.
-*/
-struct PFS_wait_locker
-{
-  /** The timer used to measure the wait. */
-  enum_timer_name m_timer_name;
-  /** The object waited on. */
-  events_waits_target m_target;
-  /** The wait data recorded. */
-  PFS_events_waits m_waits_current;
-};
-
 void insert_events_waits_history(PFS_thread *thread, PFS_events_waits *wait);
 
 void insert_events_waits_history_long(PFS_events_waits *wait);
@@ -172,14 +130,9 @@ void insert_events_waits_history_long(PF
 extern bool flag_events_waits_current;
 extern bool flag_events_waits_history;
 extern bool flag_events_waits_history_long;
-extern bool flag_events_waits_summary_by_thread_by_event_name;
-extern bool flag_events_waits_summary_by_event_name;
-extern bool flag_events_waits_summary_by_instance;
-extern bool flag_events_locks_summary_by_thread_by_name;
-extern bool flag_events_locks_summary_by_event_name;
-extern bool flag_events_locks_summary_by_instance;
-extern bool flag_file_summary_by_event_name;
-extern bool flag_file_summary_by_instance;
+extern bool flag_global_instrumentation;
+extern bool flag_thread_instrumentation;
+
 extern bool events_waits_history_long_full;
 extern volatile uint32 events_waits_history_long_index;
 extern PFS_events_waits *events_waits_history_long_array;

=== modified file 'storage/perfschema/pfs_instr.cc'
--- a/storage/perfschema/pfs_instr.cc	2010-07-30 09:02:32 +0000
+++ b/storage/perfschema/pfs_instr.cc	2010-09-23 16:08:54 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2010 Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2010, 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,6 +26,7 @@
 #include "pfs_stat.h"
 #include "pfs_instr.h"
 #include "pfs_global.h"
+#include "pfs_instr_class.h"
 
 /**
   @addtogroup Performance_schema_buffers
@@ -65,8 +66,6 @@ ulong table_max;
 ulong table_lost;
 /** Number of EVENTS_WAITS_HISTORY records per thread. */
 ulong events_waits_history_per_thread;
-/** Number of instruments class per thread. */
-ulong instr_class_per_thread;
 /** Number of locker lost. @sa LOCKER_STACK_SIZE. */
 ulong locker_lost= 0;
 
@@ -120,13 +119,12 @@ PFS_file **file_handle_array= NULL;
 */
 PFS_table *table_array= NULL;
 
+PFS_single_stat *global_instr_class_waits_array= NULL;
+
 static volatile uint32 thread_internal_id_counter= 0;
 
-static uint per_thread_rwlock_class_start;
-static uint per_thread_cond_class_start;
-static uint per_thread_file_class_start;
 static uint thread_instr_class_waits_sizing;
-static PFS_single_stat_chain *thread_instr_class_waits_array= NULL;
+static PFS_single_stat *thread_instr_class_waits_array= NULL;
 
 static PFS_events_waits *thread_history_array= NULL;
 
@@ -149,6 +147,9 @@ int init_instruments(const PFS_global_pa
   uint thread_history_sizing;
   uint index;
 
+  /* Make sure init_event_name_sizing is called */
+  DBUG_ASSERT(max_instrument_class != 0);
+
   mutex_max= param->m_mutex_sizing;
   mutex_lost= 0;
   rwlock_max= param->m_rwlock_sizing;
@@ -168,16 +169,8 @@ int init_instruments(const PFS_global_pa
   thread_history_sizing= param->m_thread_sizing
     * events_waits_history_per_thread;
 
-  per_thread_rwlock_class_start= param->m_mutex_class_sizing;
-  per_thread_cond_class_start= per_thread_rwlock_class_start
-    + param->m_rwlock_class_sizing;
-  per_thread_file_class_start= per_thread_cond_class_start
-    + param->m_cond_class_sizing;
-  instr_class_per_thread= per_thread_file_class_start
-    + param->m_file_class_sizing;
-
   thread_instr_class_waits_sizing= param->m_thread_sizing
-    * instr_class_per_thread;
+    * max_instrument_class;
 
   mutex_array= NULL;
   rwlock_array= NULL;
@@ -252,21 +245,12 @@ int init_instruments(const PFS_global_pa
   {
     thread_instr_class_waits_array=
       PFS_MALLOC_ARRAY(thread_instr_class_waits_sizing,
-                       PFS_single_stat_chain, MYF(MY_ZEROFILL));
+                       PFS_single_stat, MYF(MY_ZEROFILL));
     if (unlikely(thread_instr_class_waits_array == NULL))
       return 1;
-  }
 
-  for (index= 0; index < thread_instr_class_waits_sizing; index++)
-  {
-    /*
-      Currently, this chain is of length 1,
-      but it's still implemented as a stat chain,
-      since more aggregations are planned to be implemented in m_parent.
-    */
-    thread_instr_class_waits_array[index].m_control_flag=
-      &flag_events_waits_summary_by_thread_by_event_name;
-    thread_instr_class_waits_array[index].m_parent= NULL;
+    for (index= 0; index < thread_instr_class_waits_sizing; index++)
+      thread_instr_class_waits_array[index].reset();
   }
 
   for (index= 0; index < thread_max; index++)
@@ -274,111 +258,35 @@ int init_instruments(const PFS_global_pa
     thread_array[index].m_waits_history=
       &thread_history_array[index * events_waits_history_per_thread];
     thread_array[index].m_instr_class_wait_stats=
-      &thread_instr_class_waits_array[index * instr_class_per_thread];
+      &thread_instr_class_waits_array[index * max_instrument_class];
   }
 
-  return 0;
-}
-
-/**
-  Find the per-thread wait statistics for a mutex class.
-  @param thread                       input thread
-  @param klass                        mutex class
-  @return the per thread per mutex class wait stat
-*/
-PFS_single_stat_chain *
-find_per_thread_mutex_class_wait_stat(PFS_thread *thread,
-                                      PFS_mutex_class *klass)
-{
-  PFS_single_stat_chain *stat;
-  uint index;
-
-  DBUG_ASSERT(thread != NULL);
-  DBUG_ASSERT(klass != NULL);
-  index= klass->m_index;
-  DBUG_ASSERT(index < mutex_class_max);
-
-  stat= &(thread->m_instr_class_wait_stats[index]);
-  return stat;
-}
-
-/**
-  Find the per-thread wait statistics for a rwlock class.
-  @param thread                       input thread
-  @param klass                        rwlock class
-  @return the per thread per rwlock class wait stat
-*/
-PFS_single_stat_chain *
-find_per_thread_rwlock_class_wait_stat(PFS_thread *thread,
-                                       PFS_rwlock_class *klass)
-{
-  PFS_single_stat_chain *stat;
-  uint index;
-
-  DBUG_ASSERT(thread != NULL);
-  DBUG_ASSERT(klass != NULL);
-  index= klass->m_index;
-  DBUG_ASSERT(index < rwlock_class_max);
-
-  stat= &(thread->m_instr_class_wait_stats
-          [per_thread_rwlock_class_start + index]);
-  return stat;
-}
-
-/**
-  Find the per-thread wait statistics for a condition class.
-  @param thread                       input thread
-  @param klass                        condition class
-  @return the per thread per condition class wait stat
-*/
-PFS_single_stat_chain *
-find_per_thread_cond_class_wait_stat(PFS_thread *thread,
-                                     PFS_cond_class *klass)
-{
-  PFS_single_stat_chain *stat;
-  uint index;
-
-  DBUG_ASSERT(thread != NULL);
-  DBUG_ASSERT(klass != NULL);
-  index= klass->m_index;
-  DBUG_ASSERT(index < cond_class_max);
-
-  stat= &(thread->m_instr_class_wait_stats
-          [per_thread_cond_class_start + index]);
-  return stat;
-}
+  if (max_instrument_class > 0)
+  {
+    global_instr_class_waits_array=
+      PFS_MALLOC_ARRAY(max_instrument_class,
+                       PFS_single_stat, MYF(MY_ZEROFILL));
+    if (unlikely(global_instr_class_waits_array == NULL))
+      return 1;
 
-/**
-  Find the per-thread wait statistics for a file class.
-  @param thread                       input thread
-  @param klass                        file class
-  @return the per thread per file class wait stat
-*/
-PFS_single_stat_chain *
-find_per_thread_file_class_wait_stat(PFS_thread *thread,
-                                     PFS_file_class *klass)
-{
-  PFS_single_stat_chain *stat;
-  uint index;
+    for (index= 0; index < max_instrument_class; index++)
+      global_instr_class_waits_array[index].reset();
+  }
 
-  DBUG_ASSERT(thread != NULL);
-  DBUG_ASSERT(klass != NULL);
-  index= klass->m_index;
-  DBUG_ASSERT(index < file_class_max);
-
-  stat= &(thread->m_instr_class_wait_stats
-          [per_thread_file_class_start + index]);
-  return stat;
+  return 0;
 }
 
 /** Reset the wait statistics per thread. */
 void reset_per_thread_wait_stat(void)
 {
-  PFS_single_stat_chain *stat= thread_instr_class_waits_array;
-  PFS_single_stat_chain *stat_last= stat + thread_instr_class_waits_sizing;
+  PFS_thread *thread= thread_array;
+  PFS_thread *thread_last= thread_array + thread_max;
 
-  for ( ; stat < stat_last; stat++)
-    reset_single_stat_link(stat);
+  for ( ; thread < thread_last; thread++)
+  {
+    if (thread->m_lock.is_populated())
+      aggregate_thread(thread);
+  }
 }
 
 /** Cleanup all the instruments buffers. */
@@ -409,6 +317,8 @@ void cleanup_instruments(void)
   thread_history_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;
 }
 
 extern "C"
@@ -548,14 +458,8 @@ PFS_mutex* create_mutex(PFS_mutex_class
         {
           pfs->m_identity= identity;
           pfs->m_class= klass;
-          pfs->m_wait_stat.m_control_flag=
-            &flag_events_waits_summary_by_instance;
-          pfs->m_wait_stat.m_parent= &klass->m_wait_stat;
-          reset_single_stat_link(&pfs->m_wait_stat);
-          pfs->m_lock_stat.m_control_flag=
-            &flag_events_locks_summary_by_instance;
-          pfs->m_lock_stat.m_parent= &klass->m_lock_stat;
-          reset_single_stat_link(&pfs->m_lock_stat);
+          pfs->m_wait_stat.reset();
+          pfs->m_lock_stat.reset();
           pfs->m_owner= NULL;
           pfs->m_last_locked= 0;
           pfs->m_lock.dirty_to_allocated();
@@ -576,6 +480,10 @@ PFS_mutex* create_mutex(PFS_mutex_class
 void destroy_mutex(PFS_mutex *pfs)
 {
   DBUG_ASSERT(pfs != NULL);
+  /* Aggregate to EVENTS_WAITS_SUMMARY_BY_EVENT_NAME */
+  uint index= pfs->m_class->m_event_name_index;
+  global_instr_class_waits_array[index].aggregate(& pfs->m_wait_stat);
+  pfs->m_wait_stat.reset();
   pfs->m_lock.allocated_to_free();
 }
 
@@ -604,19 +512,10 @@ PFS_rwlock* create_rwlock(PFS_rwlock_cla
         {
           pfs->m_identity= identity;
           pfs->m_class= klass;
-          pfs->m_wait_stat.m_control_flag=
-            &flag_events_waits_summary_by_instance;
-          pfs->m_wait_stat.m_parent= &klass->m_wait_stat;
-          reset_single_stat_link(&pfs->m_wait_stat);
+          pfs->m_wait_stat.reset();
           pfs->m_lock.dirty_to_allocated();
-          pfs->m_read_lock_stat.m_control_flag=
-            &flag_events_locks_summary_by_instance;
-          pfs->m_read_lock_stat.m_parent= &klass->m_read_lock_stat;
-          reset_single_stat_link(&pfs->m_read_lock_stat);
-          pfs->m_write_lock_stat.m_control_flag=
-            &flag_events_locks_summary_by_instance;
-          pfs->m_write_lock_stat.m_parent= &klass->m_write_lock_stat;
-          reset_single_stat_link(&pfs->m_write_lock_stat);
+          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;
@@ -638,6 +537,10 @@ PFS_rwlock* create_rwlock(PFS_rwlock_cla
 void destroy_rwlock(PFS_rwlock *pfs)
 {
   DBUG_ASSERT(pfs != NULL);
+  /* Aggregate to EVENTS_WAITS_SUMMARY_BY_EVENT_NAME */
+  uint index= pfs->m_class->m_event_name_index;
+  global_instr_class_waits_array[index].aggregate(& pfs->m_wait_stat);
+  pfs->m_wait_stat.reset();
   pfs->m_lock.allocated_to_free();
 }
 
@@ -668,10 +571,7 @@ PFS_cond* create_cond(PFS_cond_class *kl
           pfs->m_class= klass;
           pfs->m_cond_stat.m_signal_count= 0;
           pfs->m_cond_stat.m_broadcast_count= 0;
-          pfs->m_wait_stat.m_control_flag=
-            &flag_events_waits_summary_by_instance;
-          pfs->m_wait_stat.m_parent= &klass->m_wait_stat;
-          reset_single_stat_link(&pfs->m_wait_stat);
+          pfs->m_wait_stat.reset();
           pfs->m_lock.dirty_to_allocated();
           return pfs;
         }
@@ -690,6 +590,10 @@ PFS_cond* create_cond(PFS_cond_class *kl
 void destroy_cond(PFS_cond *pfs)
 {
   DBUG_ASSERT(pfs != NULL);
+  /* Aggregate to EVENTS_WAITS_SUMMARY_BY_EVENT_NAME */
+  uint index= pfs->m_class->m_event_name_index;
+  global_instr_class_waits_array[index].aggregate(& pfs->m_wait_stat);
+  pfs->m_wait_stat.reset();
   pfs->m_lock.allocated_to_free();
 }
 
@@ -733,17 +637,18 @@ PFS_thread* create_thread(PFS_thread_cla
           pfs->m_event_id= 1;
           pfs->m_enabled= true;
           pfs->m_class= klass;
-          pfs->m_wait_locker_count= 0;
+          pfs->m_events_waits_count= 0;
           pfs->m_waits_history_full= false;
           pfs->m_waits_history_index= 0;
 
-          PFS_single_stat_chain *stat= pfs->m_instr_class_wait_stats;
-          PFS_single_stat_chain *stat_last= stat + instr_class_per_thread;
+          PFS_single_stat *stat= pfs->m_instr_class_wait_stats;
+          PFS_single_stat *stat_last= stat + max_instrument_class;
           for ( ; stat < stat_last; stat++)
-            reset_single_stat_link(stat);
+            stat->reset();
           pfs->m_filename_hash_pins= NULL;
           pfs->m_table_share_hash_pins= NULL;
           pfs->m_setup_actor_hash_pins= NULL;
+          pfs->m_setup_object_hash_pins= NULL;
 
           pfs->m_username_length= 0;
           pfs->m_hostname_length= 0;
@@ -798,6 +703,16 @@ void destroy_thread(PFS_thread *pfs)
     lf_hash_put_pins(pfs->m_table_share_hash_pins);
     pfs->m_table_share_hash_pins= NULL;
   }
+  if (pfs->m_setup_actor_hash_pins)
+  {
+    lf_hash_put_pins(pfs->m_setup_actor_hash_pins);
+    pfs->m_setup_actor_hash_pins= NULL;
+  }
+  if (pfs->m_setup_object_hash_pins)
+  {
+    lf_hash_put_pins(pfs->m_setup_object_hash_pins);
+    pfs->m_setup_object_hash_pins= NULL;
+  }
   pfs->m_lock.allocated_to_free();
 }
 
@@ -947,11 +862,9 @@ 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_wait_stat.m_control_flag=
-            &flag_events_waits_summary_by_instance;
-          pfs->m_wait_stat.m_parent= &klass->m_wait_stat;
-          reset_single_stat_link(&pfs->m_wait_stat);
+          pfs->m_file_stat.m_io_stat.reset();
 
           int res;
           res= lf_hash_insert(&filename_hash, thread->m_filename_hash_pins,
@@ -1008,6 +921,16 @@ void destroy_file(PFS_thread *thread, PF
   DBUG_ASSERT(thread != NULL);
   DBUG_ASSERT(thread->m_filename_hash_pins != NULL);
   DBUG_ASSERT(pfs != NULL);
+
+  /* Aggregate to EVENTS_WAITS_SUMMARY_BY_EVENT_NAME */
+  uint index= pfs->m_class->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 */
+  pfs->m_class->m_file_stat.m_io_stat.aggregate(& pfs->m_file_stat.m_io_stat);
+  pfs->m_file_stat.m_io_stat.reset();
+  
   lf_hash_delete(&filename_hash, thread->m_filename_hash_pins,
                  pfs->m_filename, pfs->m_filename_length);
   pfs->m_lock.allocated_to_free();
@@ -1041,10 +964,7 @@ PFS_table* create_table(PFS_table_share
           pfs->m_identity= identity;
           pfs->m_share= share;
           share->m_refcount++;
-          pfs->m_wait_stat.m_control_flag=
-            &flag_events_waits_summary_by_instance;
-          pfs->m_wait_stat.m_parent= &share->m_wait_stat;
-          reset_single_stat_link(&pfs->m_wait_stat);
+          pfs->m_table_stat.reset();
           pfs->m_opening_thread= opening_thread;
           pfs->m_lock.dirty_to_allocated();
           return pfs;
@@ -1064,6 +984,7 @@ PFS_table* create_table(PFS_table_share
 void destroy_table(PFS_table *pfs)
 {
   DBUG_ASSERT(pfs != NULL);
+  pfs->m_share->m_refcount--;
   pfs->m_lock.allocated_to_free();
 }
 
@@ -1073,7 +994,7 @@ static void reset_mutex_waits_by_instanc
   PFS_mutex *pfs_last= mutex_array + mutex_max;
 
   for ( ; pfs < pfs_last; pfs++)
-    reset_single_stat_link(&pfs->m_wait_stat);
+    pfs->m_wait_stat.reset();
 }
 
 static void reset_rwlock_waits_by_instance(void)
@@ -1082,7 +1003,7 @@ static void reset_rwlock_waits_by_instan
   PFS_rwlock *pfs_last= rwlock_array + rwlock_max;
 
   for ( ; pfs < pfs_last; pfs++)
-    reset_single_stat_link(&pfs->m_wait_stat);
+    pfs->m_wait_stat.reset();
 }
 
 static void reset_cond_waits_by_instance(void)
@@ -1091,7 +1012,7 @@ static void reset_cond_waits_by_instance
   PFS_cond *pfs_last= cond_array + cond_max;
 
   for ( ; pfs < pfs_last; pfs++)
-    reset_single_stat_link(&pfs->m_wait_stat);
+    pfs->m_wait_stat.reset();
 }
 
 static void reset_file_waits_by_instance(void)
@@ -1100,7 +1021,7 @@ static void reset_file_waits_by_instance
   PFS_file *pfs_last= file_array + file_max;
 
   for ( ; pfs < pfs_last; pfs++)
-    reset_single_stat_link(&pfs->m_wait_stat);
+    pfs->m_wait_stat.reset();
 }
 
 /** Reset the wait statistics per object instance. */
@@ -1119,7 +1040,78 @@ void reset_file_instance_io(void)
   PFS_file *pfs_last= file_array + file_max;
 
   for ( ; pfs < pfs_last; pfs++)
-    reset_file_stat(&pfs->m_file_stat);
+    pfs->m_file_stat.m_io_stat.reset();
+}
+
+void reset_global_wait_stat()
+{
+  PFS_single_stat *stat= global_instr_class_waits_array;
+  PFS_single_stat *stat_last= global_instr_class_waits_array + max_instrument_class;
+
+  for ( ; stat < stat_last; stat++)
+    stat->reset();
+}
+
+void aggregate_all_event_names(PFS_single_stat *from_array,
+                               PFS_single_stat *to_array)
+{
+  PFS_single_stat *from;
+  PFS_single_stat *from_last;
+  PFS_single_stat *to;
+  PFS_single_stat *to_last;
+
+  from= from_array;
+  from_last= from_array + max_instrument_class;
+  to= to_array;
+  to_last= to_array + max_instrument_class;
+
+  for ( ; from < from_last ; from++, to++)
+  {
+    if (from->m_count > 0)
+    {
+      to->aggregate(from);
+      from->reset();
+    }
+  }
+}
+
+void aggregate_all_event_names(PFS_single_stat *from_array,
+                               PFS_single_stat *to_array_1,
+                               PFS_single_stat *to_array_2)
+{
+  PFS_single_stat *from;
+  PFS_single_stat *from_last;
+  PFS_single_stat *to_1;
+  PFS_single_stat *to_1_last;
+  PFS_single_stat *to_2;
+  PFS_single_stat *to_2_last;
+
+  from= from_array;
+  from_last= from_array + max_instrument_class;
+  to_1= to_array_1;
+  to_1_last= to_array_1 + max_instrument_class;
+  to_2= to_array_2;
+  to_2_last= to_array_2 + max_instrument_class;
+
+  for ( ; from < from_last ; from++, to_1++, to_2++)
+  {
+    if (from->m_count > 0)
+    {
+      to_1->aggregate(from);
+      to_2->aggregate(from);
+      from->reset();
+    }
+  }
+}
+
+void aggregate_thread(PFS_thread *thread)
+{
+  /* FIXME */
+
+  PFS_single_stat *stat= thread->m_instr_class_wait_stats;
+  PFS_single_stat *stat_last= stat + max_instrument_class;
+  for ( ; stat < stat_last; stat++)
+    stat->reset();
 }
 
 /** @} */

=== modified file 'storage/perfschema/pfs_instr.h'
--- a/storage/perfschema/pfs_instr.h	2010-07-30 09:02:32 +0000
+++ b/storage/perfschema/pfs_instr.h	2010-09-23 16:08:54 +0000
@@ -21,7 +21,15 @@
   Performance schema instruments (declarations).
 */
 
+struct PFS_mutex_class;
+struct PFS_rwlock_class;
+struct PFS_cond_class;
+struct PFS_file_class;
+struct PFS_table_share;
+struct PFS_thread_class;
+
 #include "pfs_lock.h"
+#include "pfs_stat.h"
 #include "pfs_instr_class.h"
 #include "pfs_events_waits.h"
 #include "pfs_server.h"
@@ -38,8 +46,8 @@ struct PFS_instr
 {
   /** Internal lock. */
   pfs_lock m_lock;
-  /** Instrument wait statistics chain. */
-  PFS_single_stat_chain m_wait_stat;
+  /** Instrument wait statistics. */
+  PFS_single_stat m_wait_stat;
 };
 
 /** Instrumented mutex implementation. @see PSI_mutex. */
@@ -50,10 +58,10 @@ struct PFS_mutex : public PFS_instr
   /** Mutex class. */
   PFS_mutex_class *m_class;
   /**
-    Mutex lock usage statistics chain.
+    Mutex lock usage statistics.
     This statistic is not exposed in user visible tables yet.
   */
-  PFS_single_stat_chain m_lock_stat;
+  PFS_single_stat m_lock_stat;
   /** Current owner. */
   PFS_thread *m_owner;
   /**
@@ -71,15 +79,15 @@ struct PFS_rwlock : public PFS_instr
   /** RWLock class. */
   PFS_rwlock_class *m_class;
   /**
-    RWLock read lock usage statistics chain.
+    RWLock read lock usage statistics.
     This statistic is not exposed in user visible tables yet.
   */
-  PFS_single_stat_chain m_read_lock_stat;
+  PFS_single_stat m_read_lock_stat;
   /**
-    RWLock write lock usage statistics chain.
+    RWLock write lock usage statistics.
     This statistic is not exposed in user visible tables yet.
   */
-  PFS_single_stat_chain m_write_lock_stat;
+  PFS_single_stat m_write_lock_stat;
   /** Current writer thread. */
   PFS_thread *m_writer;
   /** Current count of readers. */
@@ -121,21 +129,25 @@ struct PFS_file : public PFS_instr
 };
 
 /** Instrumented table implementation. @see PSI_table. */
-struct PFS_table : public PFS_instr
+struct PFS_table
 {
+  /** Internal lock. */
+  pfs_lock m_lock;
   /** Owner. */
   PFS_thread *m_opening_thread;
   /** Table share. */
   PFS_table_share *m_share;
   /** Table identity, typically a handler. */
   const void *m_identity;
+  /** Table statistics. */
+  PFS_table_stat m_table_stat;
 };
 
 /**
-  @def LOCKER_STACK_SIZE
+  @def WAIT_STACK_SIZE
   Maximum number of nested waits.
 */
-#define LOCKER_STACK_SIZE 3
+#define WAIT_STACK_SIZE 3
 
 /**
   @def PFS_MAX_ALLOC_RETRY
@@ -192,6 +204,8 @@ struct PFS_thread
   LF_PINS *m_table_share_hash_pins;
   /** Pins for setup_actor_hash. */
   LF_PINS *m_setup_actor_hash_pins;
+  /** Pins for setup_object_hash. */
+  LF_PINS *m_setup_object_hash_pins;
   /** Event ID counter */
   ulonglong m_event_id;
   /** Thread instrumentation flag. */
@@ -204,10 +218,10 @@ struct PFS_thread
   ulong m_thread_id;
   /** Thread class. */
   PFS_thread_class *m_class;
-  /** Size of @c m_wait_locker_stack. */
-  uint m_wait_locker_count;
+  /** Size of @c m_events_waits_stack. */
+  uint m_events_waits_count;
   /**
-    Stack of wait lockers.
+    Stack of events waits.
     This member holds the data for the table
     PERFORMANCE_SCHEMA.EVENTS_WAITS_CURRENT.
     For most locks, only 1 wait locker is used at a given time.
@@ -215,7 +229,7 @@ struct PFS_thread
     - 1 for a 'logical' wait (for example on the GLOBAL READ LOCK state)
     - 1 for a 'physical' wait (for example on COND_refresh)
   */
-  PFS_wait_locker m_wait_locker_stack[LOCKER_STACK_SIZE];
+  PFS_events_waits m_events_waits_stack[WAIT_STACK_SIZE];
   /** True if the circular buffer @c m_waits_history is full. */
   bool m_waits_history_full;
   /** Current index in the circular buffer @c m_waits_history. */
@@ -231,7 +245,7 @@ struct PFS_thread
     This member holds the data for the table
     PERFORMANCE_SCHEMA.EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME.
   */
-  PFS_single_stat_chain *m_instr_class_wait_stats;
+  PFS_single_stat *m_instr_class_wait_stats;
 
   /** User name. */
   char m_username[USERNAME_LENGTH];
@@ -259,23 +273,9 @@ struct PFS_thread
   uint m_processlist_info_length;
 };
 
-PFS_thread *sanitize_thread(PFS_thread *unsafe);
+extern PFS_single_stat *global_instr_class_waits_array;
 
-PFS_single_stat_chain*
-find_per_thread_mutex_class_wait_stat(PFS_thread *thread,
-                                      PFS_mutex_class *klass);
-
-PFS_single_stat_chain*
-find_per_thread_rwlock_class_wait_stat(PFS_thread *thread,
-                                       PFS_rwlock_class *klass);
-
-PFS_single_stat_chain*
-find_per_thread_cond_class_wait_stat(PFS_thread *thread,
-                                     PFS_cond_class *klass);
-
-PFS_single_stat_chain*
-find_per_thread_file_class_wait_stat(PFS_thread *thread,
-                                     PFS_file_class *klass);
+PFS_thread *sanitize_thread(PFS_thread *unsafe);
 
 int init_instruments(const PFS_global_param *param);
 void cleanup_instruments();
@@ -319,7 +319,6 @@ extern ulong file_handle_lost;
 extern ulong table_max;
 extern ulong table_lost;
 extern ulong events_waits_history_per_thread;
-extern ulong instr_class_per_thread;
 extern ulong locker_lost;
 
 /* Exposing the data directly, for iterators. */
@@ -336,6 +335,16 @@ void reset_events_waits_by_instance();
 void reset_per_thread_wait_stat();
 void reset_file_instance_io();
 
+void reset_global_wait_stat(void);
+
+void aggregate_all_event_names(PFS_single_stat *from_array,
+                               PFS_single_stat *to_array);
+void aggregate_all_event_names(PFS_single_stat *from_array,
+                               PFS_single_stat *to_array_1,
+                               PFS_single_stat *to_array_2);
+
+void aggregate_thread(PFS_thread *thread);
+
 /** @} */
 #endif
 

=== modified file 'storage/perfschema/pfs_instr_class.cc'
--- a/storage/perfschema/pfs_instr_class.cc	2010-07-23 17:08:41 +0000
+++ b/storage/perfschema/pfs_instr_class.cc	2010-09-23 16:08:54 +0000
@@ -26,6 +26,7 @@
 #include "pfs_instr.h"
 #include "pfs_global.h"
 #include "pfs_events_waits.h"
+#include "pfs_setup_object.h"
 #include "pfs_atomic.h"
 #include "mysql/psi/mysql_thread.h"
 #include "lf.h"
@@ -106,15 +107,7 @@ static PFS_thread_class *thread_class_ar
 */
 PFS_table_share *table_share_array= NULL;
 
-PFS_instr_class global_table_class=
-{
-  "wait/io/table/sql/handler", /* name */
-  25, /* name length */
-  0, /* flags */
-  true, /* enabled */
-  true, /* timed */
-  { &flag_events_waits_current, NULL, 0, 0, 0, 0} /* wait stat chain */
-};
+PFS_instr_class global_table_io_class;
 
 /**
   Hash index for instrumented table shares.
@@ -139,6 +132,31 @@ static volatile uint32 file_class_alloca
 
 static PFS_file_class *file_class_array= NULL;
 
+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 max_instrument_class= 0;
+
+void init_event_name_sizing(const PFS_global_param *param)
+{
+  mutex_class_start= 0;
+  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;
+  table_class_start= file_class_start + param->m_file_class_sizing;
+  max_instrument_class= table_class_start + 1; /* global table io */
+
+  memcpy(global_table_io_class.m_name, "wait/io/table/sql/handler", 25);
+  global_table_io_class.m_name_length= 25;
+  global_table_io_class.m_flags= 0;
+  global_table_io_class.m_enabled= true;
+  global_table_io_class.m_timed= true;
+  global_table_io_class.m_event_name_index= table_class_start;
+}
+
+
 /**
   Initialize the instrument synch class buffers.
   @param mutex_class_sizing           max number of mutex class
@@ -325,7 +343,7 @@ LF_PINS* get_table_share_hash_pins(PFS_t
 
 /**
   Set a table share hash key.
-  @param [out] key The key to polulate.
+  @param [out] key The key to populate.
   @param temporary True for TEMPORARY TABLE.
   @param schema_name The table schema name.
   @param schema_name_length The table schema name length.
@@ -339,19 +357,29 @@ static void set_table_share_key(PFS_tabl
 {
   DBUG_ASSERT(schema_name_length <= NAME_LEN);
   DBUG_ASSERT(table_name_length <= NAME_LEN);
+  char *saved_schema_name;
+  char *saved_table_name;
 
   char *ptr= &key->m_hash_key[0];
   ptr[0]= (temporary ? OBJECT_TYPE_TEMPORARY_TABLE : OBJECT_TYPE_TABLE);
   ptr++;
+  saved_schema_name= ptr;
   memcpy(ptr, schema_name, schema_name_length);
   ptr+= schema_name_length;
   ptr[0]= 0;
   ptr++;
+  saved_table_name= ptr;
   memcpy(ptr, table_name, table_name_length);
   ptr+= table_name_length;
   ptr[0]= 0;
   ptr++;
   key->m_key_length= ptr - &key->m_hash_key[0];
+
+  if (lower_case_table_names)
+  {
+    my_casedn_str(files_charset_info, saved_schema_name);
+    my_casedn_str(files_charset_info, saved_table_name);
+  }
 }
 
 /**
@@ -464,15 +492,9 @@ PFS_sync_key register_mutex_class(const
     */
     entry= &mutex_class_array[index];
     init_instr_class(entry, name, name_length, flags);
-    entry->m_wait_stat.m_control_flag=
-      &flag_events_waits_summary_by_event_name;
-    entry->m_wait_stat.m_parent= NULL;
-    reset_single_stat_link(&entry->m_wait_stat);
-    entry->m_lock_stat.m_control_flag=
-      &flag_events_locks_summary_by_event_name;
-    entry->m_lock_stat.m_parent= NULL;
-    reset_single_stat_link(&entry->m_lock_stat);
+    entry->m_lock_stat.reset();
     entry->m_index= index;
+    entry->m_event_name_index= mutex_class_start + index;
     /*
       Now that this entry is populated, advertise it
 
@@ -530,19 +552,10 @@ PFS_sync_key register_rwlock_class(const
   {
     entry= &rwlock_class_array[index];
     init_instr_class(entry, name, name_length, flags);
-    entry->m_wait_stat.m_control_flag=
-      &flag_events_waits_summary_by_event_name;
-    entry->m_wait_stat.m_parent= NULL;
-    reset_single_stat_link(&entry->m_wait_stat);
-    entry->m_read_lock_stat.m_control_flag=
-      &flag_events_locks_summary_by_event_name;
-    entry->m_read_lock_stat.m_parent= NULL;
-    reset_single_stat_link(&entry->m_read_lock_stat);
-    entry->m_write_lock_stat.m_control_flag=
-      &flag_events_locks_summary_by_event_name;
-    entry->m_write_lock_stat.m_parent= NULL;
-    reset_single_stat_link(&entry->m_write_lock_stat);
+    entry->m_read_lock_stat.reset();
+    entry->m_write_lock_stat.reset();
     entry->m_index= index;
+    entry->m_event_name_index= rwlock_class_start + index;
     PFS_atomic::add_u32(&rwlock_class_allocated_count, 1);
     return (index + 1);
   }
@@ -574,11 +587,8 @@ PFS_sync_key register_cond_class(const c
   {
     entry= &cond_class_array[index];
     init_instr_class(entry, name, name_length, flags);
-    entry->m_wait_stat.m_control_flag=
-      &flag_events_waits_summary_by_event_name;
-    entry->m_wait_stat.m_parent= NULL;
-    reset_single_stat_link(&entry->m_wait_stat);
     entry->m_index= index;
+    entry->m_event_name_index= cond_class_start + index;
     PFS_atomic::add_u32(&cond_class_allocated_count, 1);
     return (index + 1);
   }
@@ -721,11 +731,8 @@ PFS_file_key register_file_class(const c
   {
     entry= &file_class_array[index];
     init_instr_class(entry, name, name_length, flags);
-    entry->m_wait_stat.m_control_flag=
-      &flag_events_waits_summary_by_event_name;
-    entry->m_wait_stat.m_parent= NULL;
-    reset_single_stat_link(&entry->m_wait_stat);
     entry->m_index= index;
+    entry->m_event_name_index= file_class_start + index;
     PFS_atomic::add_u32(&file_class_allocated_count, 1);
     return (index + 1);
   }
@@ -749,6 +756,63 @@ PFS_file_class *sanitize_file_class(PFS_
   SANITIZE_ARRAY_BODY(file_class_array, file_class_max, unsafe);
 }
 
+PFS_instr_class *find_table_class(uint index)
+{
+  if (index == 1)
+    return & global_table_io_class;
+  return NULL;
+}
+
+PFS_instr_class *sanitize_table_class(PFS_instr_class *unsafe)
+{
+  if (likely(& global_table_io_class == unsafe))
+    return unsafe;
+  return NULL;
+}
+
+static void set_keys(PFS_table_share *pfs, const TABLE_SHARE *share)
+{
+  int len;
+  KEY *key_info= share->key_info;
+  PFS_table_key *pfs_key= pfs->m_keys;
+  PFS_table_key *pfs_key_last= pfs->m_keys + share->keys;
+  pfs->m_key_count= share->keys;
+
+  for ( ; pfs_key < pfs_key_last; pfs_key++, key_info++)
+  {
+    len= strlen(key_info->name);
+    memcpy(pfs_key->m_name, key_info->name, len);
+    pfs_key->m_name_length= len;
+  }
+
+  pfs_key_last= pfs->m_keys + MAX_KEY;
+  for ( ; pfs_key < pfs_key_last; pfs_key++)
+    pfs_key->m_name_length= 0;
+}
+
+static int compare_keys(PFS_table_share *pfs, const TABLE_SHARE *share)
+{
+  uint len;
+  KEY *key_info= share->key_info;
+  PFS_table_key *pfs_key= pfs->m_keys;
+  PFS_table_key *pfs_key_last= pfs->m_keys + share->keys;
+
+  if (pfs->m_key_count != share->keys)
+    return 1;
+
+  for ( ; pfs_key < pfs_key_last; pfs_key++, key_info++)
+  {
+    len= strlen(key_info->name);
+    if (len != pfs_key->m_name_length)
+      return 1;
+
+    if (memcmp(pfs_key->m_name, key_info->name, len) != 0)
+      return 1;
+  }
+
+  return 0;
+}
+
 /**
   Find or create a table share instrumentation.
   @param thread                       the executing instrumented thread
@@ -761,7 +825,6 @@ PFS_table_share* find_or_create_table_sh
                                             const TABLE_SHARE *share)
 {
   /* See comments in register_mutex_class */
-  int pass;
   PFS_table_share_key key;
 
   LF_PINS *pins= get_table_share_hash_pins(thread);
@@ -782,6 +845,7 @@ PFS_table_share* find_or_create_table_sh
 
   PFS_table_share **entry;
   uint retry_count= 0;
+  uint version= 0;
   const uint retry_max= 3;
   bool enabled= true;
   bool timed= true;
@@ -795,15 +859,24 @@ search:
     PFS_table_share *pfs;
     pfs= *entry;
     pfs->m_refcount++ ;
+    if (compare_keys(pfs, share) != 0)
+    {
+      set_keys(pfs, share);
+      /* FIXME: aggregate to table_share sink ? */
+      pfs->m_table_stat.reset();
+    }
     lf_hash_search_unpin(pins);
     return pfs;
   }
 
   if (retry_count == 0)
   {
-    /* No per object lokup yet */
-    enabled= global_table_class.m_enabled;
-    timed= global_table_class.m_timed;
+    version= setup_objects_version;
+    lookup_setup_object(thread,
+                        (temporary ? OBJECT_TYPE_TEMPORARY_TABLE : OBJECT_TYPE_TABLE),
+                        schema_name, schema_name_length,
+                        table_name, table_name_length,
+                        &enabled, &timed);
 
     /*
       Even when enabled is false, a record is added in the dictionary:
@@ -813,35 +886,32 @@ search:
     */
   }
 
-  /* table_name is not constant, just using it for noise on create */
-  uint i= randomized_index(table_name, table_share_max);
+  PFS_scan scan;
+  uint random= randomized_index(table_name, table_share_max);
 
-  /*
-    Pass 1: [random, table_share_max - 1]
-    Pass 2: [0, table_share_max - 1]
-  */
-  for (pass= 1; pass <= 2; i=0, pass++)
+  for (scan.init(random, table_share_max);
+       scan.has_pass();
+       scan.next_pass())
   {
-    PFS_table_share *pfs= table_share_array + i;
-    PFS_table_share *pfs_last= table_share_array + table_share_max;
+    PFS_table_share *pfs= table_share_array + scan.first();
+    PFS_table_share *pfs_last= table_share_array + scan.last();
     for ( ; pfs < pfs_last; pfs++)
     {
       if (pfs->m_lock.is_free())
       {
         if (pfs->m_lock.free_to_dirty())
         {
+          pfs->m_setup_objects_version= version;
           pfs->m_key= key;
           pfs->m_schema_name= &pfs->m_key.m_hash_key[1];
           pfs->m_schema_name_length= schema_name_length;
           pfs->m_table_name= &pfs->m_key.m_hash_key[schema_name_length + 2];
           pfs->m_table_name_length= table_name_length;
-          pfs->m_wait_stat.m_control_flag=
-            &flag_events_waits_summary_by_instance;
-          pfs->m_wait_stat.m_parent= NULL;
-          reset_single_stat_link(&pfs->m_wait_stat);
           pfs->m_enabled= enabled;
           pfs->m_timed= timed;
           pfs->m_refcount= 1;
+          pfs->m_table_stat.reset();
+          set_keys(pfs, share);
 
           int res;
           res= lf_hash_insert(&table_share_hash, pins, &pfs);
@@ -877,6 +947,12 @@ search:
   return NULL;
 }
 
+void release_table_share(PFS_table_share *pfs)
+{
+  DBUG_ASSERT(pfs->m_refcount > 0);
+  pfs->m_refcount--;
+}
+
 /**
   Purge an instrumented table share from the performance schema buffers.
   The table share is removed from the hash index, and freed.
@@ -939,51 +1015,6 @@ PFS_table_share *sanitize_table_share(PF
   SANITIZE_ARRAY_BODY(table_share_array, table_share_max, unsafe);
 }
 
-static void reset_mutex_class_waits(void)
-{
-  PFS_mutex_class *pfs= mutex_class_array;
-  PFS_mutex_class *pfs_last= mutex_class_array + mutex_class_max;
-
-  for ( ; pfs < pfs_last; pfs++)
-    reset_single_stat_link(&pfs->m_wait_stat);
-}
-
-static void reset_rwlock_class_waits(void)
-{
-  PFS_rwlock_class *pfs= rwlock_class_array;
-  PFS_rwlock_class *pfs_last= rwlock_class_array + rwlock_class_max;
-
-  for ( ; pfs < pfs_last; pfs++)
-    reset_single_stat_link(&pfs->m_wait_stat);
-}
-
-static void reset_cond_class_waits(void)
-{
-  PFS_cond_class *pfs= cond_class_array;
-  PFS_cond_class *pfs_last= cond_class_array + cond_class_max;
-
-  for ( ; pfs < pfs_last; pfs++)
-    reset_single_stat_link(&pfs->m_wait_stat);
-}
-
-static void reset_file_class_waits(void)
-{
-  PFS_file_class *pfs= file_class_array;
-  PFS_file_class *pfs_last= file_class_array + file_class_max;
-
-  for ( ; pfs < pfs_last; pfs++)
-    reset_single_stat_link(&pfs->m_wait_stat);
-}
-
-/** Reset the wait statistics for every instrument class. */
-void reset_instrument_class_waits(void)
-{
-  reset_mutex_class_waits();
-  reset_rwlock_class_waits();
-  reset_cond_class_waits();
-  reset_file_class_waits();
-}
-
 /** Reset the io statistics per file class. */
 void reset_file_class_io(void)
 {
@@ -991,7 +1022,7 @@ void reset_file_class_io(void)
   PFS_file_class *pfs_last= file_class_array + file_class_max;
 
   for ( ; pfs < pfs_last; pfs++)
-    reset_file_stat(&pfs->m_file_stat);
+    pfs->m_file_stat.m_io_stat.reset();
 }
 
 /** @} */

=== modified file 'storage/perfschema/pfs_instr_class.h'
--- a/storage/perfschema/pfs_instr_class.h	2010-07-23 17:08:41 +0000
+++ b/storage/perfschema/pfs_instr_class.h	2010-09-23 16:08:54 +0000
@@ -44,6 +44,8 @@
 #include "pfs_stat.h"
 #include "pfs_column_types.h"
 
+struct PFS_global_param;
+
 /**
   @addtogroup Performance_schema_buffers
   @{
@@ -60,6 +62,13 @@ typedef unsigned int PFS_file_key;
 
 struct PFS_thread;
 
+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 max_instrument_class;
+
 /** Information for all instrumentation. */
 struct PFS_instr_class
 {
@@ -73,18 +82,22 @@ struct PFS_instr_class
   bool m_enabled;
   /** True if this instrument is timed. */
   bool m_timed;
-  /** Wait statistics chain. */
-  PFS_single_stat_chain m_wait_stat;
+  /**
+    Instrument name index.
+    Self index in:
+    - EVENTS_WAITS_SUMMARY_*_BY_EVENT_NAME
+  */
+  uint m_event_name_index;
 };
 
 /** Instrumentation metadata for a MUTEX. */
 struct PFS_mutex_class : public PFS_instr_class
 {
   /**
-    Lock statistics chain.
+    Lock statistics.
     This statistic is not exposed in user visible tables yet.
   */
-  PFS_single_stat_chain m_lock_stat;
+  PFS_single_stat m_lock_stat;
   /** Self index in @c mutex_class_array. */
   uint m_index;
 };
@@ -93,15 +106,15 @@ struct PFS_mutex_class : public PFS_inst
 struct PFS_rwlock_class : public PFS_instr_class
 {
   /**
-    Read lock statistics chain.
+    Read lock statistics.
     This statistic is not exposed in user visible tables yet.
   */
-  PFS_single_stat_chain m_read_lock_stat;
+  PFS_single_stat m_read_lock_stat;
   /**
-    Write lock statistics chain.
+    Write lock statistics.
     This statistic is not exposed in user visible tables yet.
   */
-  PFS_single_stat_chain m_write_lock_stat;
+  PFS_single_stat m_write_lock_stat;
   /** Self index in @c rwlock_class_array. */
   uint m_index;
 };
@@ -143,6 +156,15 @@ struct PFS_table_share_key
   uint m_key_length;
 };
 
+/** Table index or 'key' */
+struct PFS_table_key
+{
+  /** Index name */
+  char m_name[NAME_LEN];
+  /** Length in bytes of @c m_name. */
+  uint m_name_length;
+};
+
 /** Instrumentation metadata for a table share. */
 struct PFS_table_share
 {
@@ -151,6 +173,8 @@ struct PFS_table_share
     return (enum_object_type) m_key.m_hash_key[0];
   }
 
+  /** Setup object refresh version. */
+  uint m_setup_objects_version;
   /** Internal lock. */
   pfs_lock m_lock;
   /** Search key. */
@@ -163,8 +187,6 @@ struct PFS_table_share
   const char *m_table_name;
   /** Length in bytes of @c m_table_name. */
   uint m_table_name_length;
-  /** Wait statistics chain. */
-  PFS_single_stat_chain m_wait_stat;
   /** True if this table instrument is enabled. */
   bool m_enabled;
   /** True if this table instrument is timed. */
@@ -172,14 +194,19 @@ struct PFS_table_share
   bool m_purge;
   /** Number of opened table handles. */
   uint m_refcount;
+  /** Table io statistics. */
+  PFS_table_stat m_table_stat;
+  /** Number of indexes. */
+  uint m_key_count;
+  /** Index names. */
+  PFS_table_key m_keys[MAX_KEY];
 };
 
 /**
-  Instrument controlling all tables.
-  This instrument is used as a default when there is no
-  entry present in SETUP_OBJECTS.
+  Instrument controlling all table io.
+  This instrument is used with table SETUP_OBJECTS.
 */
-extern PFS_instr_class global_table_class;
+extern PFS_instr_class global_table_io_class;
 
 /** Instrumentation metadata for a file. */
 struct PFS_file_class : public PFS_instr_class
@@ -190,6 +217,8 @@ struct PFS_file_class : public PFS_instr
   uint m_index;
 };
 
+void init_event_name_sizing(const PFS_global_param *param);
+
 int init_sync_class(uint mutex_class_sizing,
                     uint rwlock_class_sizing,
                     uint cond_class_sizing);
@@ -229,10 +258,13 @@ PFS_thread_class *find_thread_class(PSI_
 PFS_thread_class *sanitize_thread_class(PFS_thread_class *unsafe);
 PFS_file_class *find_file_class(PSI_file_key key);
 PFS_file_class *sanitize_file_class(PFS_file_class *unsafe);
+PFS_instr_class *find_table_class(uint index);
+PFS_instr_class *sanitize_table_class(PFS_instr_class *unsafe);
 
 PFS_table_share *find_or_create_table_share(PFS_thread *thread,
                                             bool temporary,
                                             const TABLE_SHARE *share);
+void release_table_share(PFS_table_share *pfs);
 void purge_table_share(PFS_thread *thread, PFS_table_share *pfs);
 void drop_table_share(PFS_thread *thread,
                       bool temporary,
@@ -255,7 +287,6 @@ extern ulong table_share_max;
 extern ulong table_share_lost;
 extern PFS_table_share *table_share_array;
 
-void reset_instrument_class_waits();
 void reset_file_class_io();
 
 /** @} */

=== modified file 'storage/perfschema/pfs_server.cc'
--- a/storage/perfschema/pfs_server.cc	2010-07-23 19:03:52 +0000
+++ b/storage/perfschema/pfs_server.cc	2010-09-23 16:08:54 +0000
@@ -29,6 +29,7 @@
 #include "pfs_events_waits.h"
 #include "pfs_timer.h"
 #include "pfs_setup_actor.h"
+#include "pfs_setup_object.h"
 #include "pfs_defaults.h"
 
 PFS_global_param pfs_param;
@@ -55,6 +56,7 @@ initialize_performance_schema(const PFS_
 
   init_timers();
   PFS_atomic::init();
+  init_event_name_sizing(param);
 
   if (pthread_key_create(&THR_PFS, destroy_pfs_thread))
     return NULL;
@@ -73,7 +75,9 @@ initialize_performance_schema(const PFS_
       init_file_hash() ||
       init_table_share_hash() ||
       init_setup_actor(param) ||
-      init_setup_actor_hash())
+      init_setup_actor_hash() ||
+      init_setup_object(param) ||
+      init_setup_object_hash())
   {
     /*
       The performance schema initialization failed.
@@ -119,6 +123,8 @@ static void cleanup_performance_schema(v
   cleanup_file_hash();
   cleanup_setup_actor();
   cleanup_setup_actor_hash();
+  cleanup_setup_object();
+  cleanup_setup_object_hash();
   PFS_atomic::cleanup();
 }
 

=== modified file 'storage/perfschema/pfs_server.h'
--- a/storage/perfschema/pfs_server.h	2010-09-01 22:59:33 +0000
+++ b/storage/perfschema/pfs_server.h	2010-09-23 16:08:54 +0000
@@ -69,6 +69,9 @@
 #ifndef PFS_MAX_SETUP_ACTOR
   #define PFS_MAX_SETUP_ACTOR 100
 #endif
+#ifndef PFS_MAX_SETUP_OBJECT
+  #define PFS_MAX_SETUP_OBJECT 100
+#endif
 
 /** Performance schema global sizing parameters. */
 struct PFS_global_param
@@ -98,6 +101,8 @@ struct PFS_global_param
   ulong m_events_waits_history_sizing;
   ulong m_events_waits_history_long_sizing;
   ulong m_setup_actor_sizing;
+  /** Maximum number of setup object records. */
+  ulong m_setup_object_sizing;
 };
 
 extern PFS_global_param pfs_param;

=== added file 'storage/perfschema/pfs_setup_object.cc'
--- a/storage/perfschema/pfs_setup_object.cc	1970-01-01 00:00:00 +0000
+++ b/storage/perfschema/pfs_setup_object.cc	2010-09-23 16:08:54 +0000
@@ -0,0 +1,328 @@
+/* Copyright (c) 2010, 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, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+/**
+  @file storage/perfschema/pfs_setup_object.cc
+  Performance schema setup object (implementation).
+*/
+
+#include "my_global.h"
+#include "my_sys.h"
+#include "my_base.h"
+#include "sql_string.h"
+#include "pfs.h"
+#include "pfs_stat.h"
+#include "pfs_instr.h"
+#include "pfs_setup_object.h"
+#include "pfs_global.h"
+
+/**
+  @addtogroup Performance_schema_buffers
+  @{
+*/
+
+uint setup_objects_version= 0;
+
+ulong setup_object_max;
+
+PFS_setup_object *setup_object_array= NULL;
+
+static LF_HASH setup_object_hash;
+static bool setup_object_hash_inited= false;
+
+/**
+  Initialize the setup object buffers.
+  @param param                        sizing parameters
+  @return 0 on success
+*/
+int init_setup_object(const PFS_global_param *param)
+{
+  setup_object_max= param->m_setup_object_sizing;
+
+  setup_object_array= NULL;
+
+  if (setup_object_max > 0)
+  {
+    setup_object_array= PFS_MALLOC_ARRAY(setup_object_max, PFS_setup_object,
+                                         MYF(MY_ZEROFILL));
+    if (unlikely(setup_object_array == NULL))
+      return 1;
+  }
+
+  return 0;
+}
+
+/** Cleanup all the setup object buffers. */
+void cleanup_setup_object(void)
+{
+  pfs_free(setup_object_array);
+  setup_object_array= NULL;
+  setup_object_max= 0;
+}
+
+static uchar *setup_object_hash_get_key(const uchar *entry, size_t *length,
+                                        my_bool)
+{
+  const PFS_setup_object * const *typed_entry;
+  const PFS_setup_object *setup_object;
+  const void *result;
+  typed_entry= reinterpret_cast<const PFS_setup_object* const *> (entry);
+  DBUG_ASSERT(typed_entry != NULL);
+  setup_object= *typed_entry;
+  DBUG_ASSERT(setup_object != NULL);
+  *length= setup_object->m_key.m_key_length;
+  result= setup_object->m_key.m_hash_key;
+  return const_cast<uchar*> (reinterpret_cast<const uchar*> (result));
+}
+
+/**
+  Initialize the setup objects hash.
+  @return 0 on success
+*/
+int init_setup_object_hash(void)
+{
+  if (! setup_object_hash_inited)
+  {
+    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_inited= true;
+  }
+  return 0;
+}
+
+/** Cleanup the setup objects hash. */
+void cleanup_setup_object_hash(void)
+{
+  if (setup_object_hash_inited)
+  {
+    lf_hash_destroy(&setup_object_hash);
+    setup_object_hash_inited= false;
+  }
+}
+
+static LF_PINS* get_setup_object_hash_pins(PFS_thread *thread)
+{
+  if (! setup_object_hash_inited)
+    return NULL;
+  if (unlikely(thread->m_setup_object_hash_pins == NULL))
+    thread->m_setup_object_hash_pins= lf_hash_get_pins(&setup_object_hash);
+  return thread->m_setup_object_hash_pins;
+}
+
+static void set_setup_object_key(PFS_setup_object_key *key,
+                                 enum_object_type object_type,
+                                 const char *schema, uint schema_length,
+                                 const char *object, uint object_length)
+{
+  DBUG_ASSERT(schema_length <= NAME_LEN);
+  DBUG_ASSERT(object_length <= NAME_LEN);
+
+  char *ptr= &key->m_hash_key[0];
+  ptr[0]= (char) object_type;
+  ptr++;
+  memcpy(ptr, schema, schema_length);
+  ptr+= schema_length;
+  ptr[0]= 0;
+  ptr++;
+  memcpy(ptr, object, object_length);
+  ptr+= object_length;
+  ptr[0]= 0;
+  ptr++;
+  key->m_key_length= ptr - &key->m_hash_key[0];
+}
+
+int insert_setup_object(enum_object_type object_type, const String *schema,
+                        const String *object, bool enabled, bool timed)
+{
+  if (setup_object_max == 0)
+    return HA_ERR_RECORD_FILE_FULL;
+
+  PFS_thread *thread= PFS_thread::get_current_thread();
+  if (unlikely(thread == NULL))
+    return HA_ERR_OUT_OF_MEM;
+
+  LF_PINS* pins= get_setup_object_hash_pins(thread);
+  if (unlikely(pins == NULL))
+    return HA_ERR_OUT_OF_MEM;
+
+  PFS_scan scan;
+  uint random= randomized_index(object, setup_object_max);
+
+  for (scan.init(random, setup_object_max);
+       scan.has_pass();
+       scan.next_pass())
+  {
+    PFS_setup_object *pfs= setup_object_array + scan.first();
+    PFS_setup_object *pfs_last= setup_object_array + scan.last();
+
+    for ( ; pfs < pfs_last; pfs++)
+    {
+      if (pfs->m_lock.is_free())
+      {
+        if (pfs->m_lock.free_to_dirty())
+        {
+          set_setup_object_key(&pfs->m_key, object_type,
+                               schema->ptr(), schema->length(),
+                               object->ptr(), object->length());
+          pfs->m_schema_name= &pfs->m_key.m_hash_key[1];
+          pfs->m_schema_name_length= schema->length();
+          pfs->m_object_name= pfs->m_schema_name + pfs->m_schema_name_length + 1;
+          pfs->m_object_name_length= object->length();
+          pfs->m_enabled= enabled;
+          pfs->m_timed= timed;
+
+          int res;
+          res= lf_hash_insert(&setup_object_hash, pins, &pfs);
+          if (likely(res == 0))
+          {
+            pfs->m_lock.dirty_to_allocated();
+            setup_objects_version++;
+            return 0;
+          }
+
+          pfs->m_lock.dirty_to_free();
+          if (res > 0)
+            return HA_ERR_FOUND_DUPP_KEY;
+          /* OOM in lf_hash_insert */
+          return HA_ERR_OUT_OF_MEM;
+        }
+      }
+    }
+  }
+
+  return HA_ERR_RECORD_FILE_FULL;
+}
+
+int delete_setup_object(enum_object_type object_type, const String *schema,
+                        const String *object)
+{
+  PFS_thread *thread= PFS_thread::get_current_thread();
+  if (unlikely(thread == NULL))
+    return HA_ERR_OUT_OF_MEM;
+
+  LF_PINS* pins= get_setup_object_hash_pins(thread);
+  if (unlikely(pins == NULL))
+    return HA_ERR_OUT_OF_MEM;
+
+  PFS_setup_object_key key;
+  set_setup_object_key(&key, object_type,
+                       schema->ptr(), schema->length(),
+                       object->ptr(), object->length());
+
+  PFS_setup_object **entry;
+  entry= reinterpret_cast<PFS_setup_object**>
+    (lf_hash_search(&setup_object_hash, pins, key.m_hash_key, key.m_key_length));
+
+  if (entry && (entry != MY_ERRPTR))
+  {
+    PFS_setup_object *pfs= *entry;
+    lf_hash_delete(&setup_object_hash, pins, key.m_hash_key, key.m_key_length);
+    pfs->m_lock.allocated_to_free();
+  }
+
+  setup_objects_version++;
+  return 0;
+}
+
+int reset_setup_object()
+{
+  PFS_thread *thread= PFS_thread::get_current_thread();
+  if (unlikely(thread == NULL))
+    return HA_ERR_OUT_OF_MEM;
+
+  LF_PINS* pins= get_setup_object_hash_pins(thread);
+  if (unlikely(pins == NULL))
+    return HA_ERR_OUT_OF_MEM;
+
+  PFS_setup_object *pfs= setup_object_array;
+  PFS_setup_object *pfs_last= setup_object_array + setup_object_max;
+
+  for ( ; pfs < pfs_last; pfs++)
+  {
+    if (pfs->m_lock.is_populated())
+    {
+      lf_hash_delete(&setup_object_hash, pins,
+                     pfs->m_key.m_hash_key, pfs->m_key.m_key_length);
+      pfs->m_lock.allocated_to_free();
+    }
+  }
+
+  setup_objects_version++;
+  return 0;
+}
+
+long setup_object_count()
+{
+  return setup_object_hash.count;
+}
+
+void lookup_setup_object(PFS_thread *thread,
+                         enum_object_type object_type,
+                         const char *schema_name, int schema_name_length,
+                         const char *object_name, int object_name_length,
+                         bool *enabled, bool *timed)
+{
+  PFS_setup_object_key key;
+  PFS_setup_object **entry;
+  PFS_setup_object *pfs;
+  int i;
+
+  LF_PINS* pins= get_setup_object_hash_pins(thread);
+  if (unlikely(pins == NULL))
+  {
+    *enabled= false;
+    *timed= false;
+    return;
+  }
+
+  for (i= 1; i<=3; i++)
+  {
+    switch(i)
+    {
+    case 1:
+      /* Lookup OBJECT_TYPE + OBJECT_SCHEMA + OBJECT_NAME in SETUP_OBJECTS */
+      set_setup_object_key(&key,
+                           object_type,
+                           schema_name, schema_name_length,
+                           object_name, object_name_length);
+      break;
+    case 2:
+      /* Lookup OBJECT_TYPE + OBJECT_SCHEMA + "%" in SETUP_OBJECTS */
+      set_setup_object_key(&key,
+                           object_type,
+                           schema_name, schema_name_length, "%", 1);
+      break;
+    case 3:
+      /* Lookup OBJECT_TYPE + NULL + NULL in SETUP_OBJECTS */
+      set_setup_object_key(&key, object_type, "%", 1, "%", 1);
+      break;
+    }
+    entry= reinterpret_cast<PFS_setup_object**>
+      (lf_hash_search(&setup_object_hash, pins, key.m_hash_key, key.m_key_length));
+
+    if (entry && (entry != MY_ERRPTR))
+    {
+      pfs= *entry;
+      *enabled= pfs->m_enabled;
+      *timed= pfs->m_timed;
+      return;
+    }
+  }
+  *enabled= false;
+  *timed= false;
+  return;
+}
+
+/** @} */

=== added file 'storage/perfschema/pfs_setup_object.h'
--- a/storage/perfschema/pfs_setup_object.h	1970-01-01 00:00:00 +0000
+++ b/storage/perfschema/pfs_setup_object.h	2010-09-23 16:08:54 +0000
@@ -0,0 +1,101 @@
+/* Copyright (c) 2010, 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, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#ifndef PFS_SETUP_OBJECT_H
+#define PFS_SETUP_OBJECT_H
+
+/**
+  @file storage/perfschema/pfs_setup_object.h
+  Performance schema setup object (declarations).
+*/
+
+#include "pfs_lock.h"
+#include "lf.h"
+
+class String;
+struct PFS_global_param;
+
+/**
+  @addtogroup Performance_schema_buffers
+  @{
+*/
+
+struct PFS_setup_object_key
+{
+  /**
+    Hash search key.
+    This has to be a string for LF_HASH,
+    the format is "<enum_object_type><schema_name><0x00><object_name><0x00>"
+  */
+  char m_hash_key[1 + NAME_LEN + 1 + NAME_LEN + 1];
+  uint m_key_length;
+};
+
+struct PFS_setup_object
+{
+  enum_object_type get_object_type()
+  {
+    return (enum_object_type) m_key.m_hash_key[0];
+  }
+
+  /** Internal lock. */
+  pfs_lock m_lock;
+  /** Hash key. */
+  PFS_setup_object_key m_key;
+  /** Schema name. Points inside m_key. */
+  const char *m_schema_name;
+  /** Length of @c m_schema_name. */
+  uint m_schema_name_length;
+  /** Object name. Points inside m_key. */
+  const char *m_object_name;
+  /** Length of @c m_object_name. */
+  uint m_object_name_length;
+  /** ENABLED flag. */
+  bool m_enabled;
+  /** TIMED flag. */
+  bool m_timed;
+};
+
+extern uint setup_objects_version;
+
+int init_setup_object(const PFS_global_param *param);
+void cleanup_setup_object(void);
+int init_setup_object_hash(void);
+void cleanup_setup_object_hash(void);
+
+int insert_setup_object(enum_object_type object_type, const String *schema,
+                        const String *object, bool enabled, bool timed);
+int delete_setup_object(enum_object_type object_type, const String *schema,
+                        const String *object);
+int reset_setup_object(void);
+long setup_object_count(void);
+
+void lookup_setup_object(PFS_thread *thread,
+                         enum_object_type object_type,
+                         const char *schema_name, int schema_name_length,
+                         const char *object_name, int object_name_length,
+                         bool *enabled, bool *timed);
+
+/* For iterators and show status. */
+
+extern ulong setup_object_max;
+
+/* Exposing the data directly, for iterators. */
+
+extern PFS_setup_object *setup_object_array;
+
+/** @} */
+#endif
+

=== modified file 'storage/perfschema/pfs_stat.h'
--- a/storage/perfschema/pfs_stat.h	2010-08-26 16:44:02 +0000
+++ b/storage/perfschema/pfs_stat.h	2010-09-23 16:08:54 +0000
@@ -16,6 +16,8 @@
 #ifndef PFS_STAT_H
 #define PFS_STAT_H
 
+#include "sql_const.h"
+
 /**
   @file storage/perfschema/pfs_stat.h
   Statistics (declarations).
@@ -26,16 +28,9 @@
   @{
 */
 
-/** Usage statistics chain, for a single value and its aggregates. */
-struct PFS_single_stat_chain
+/** Single statistic. */
+struct PFS_single_stat
 {
-  /**
-    Control flag.
-    Statistics are aggregated only if the control flag is true.
-  */
-  bool *m_control_flag;
-  /** Next link in the statistics chain. */
-  struct PFS_single_stat_chain *m_parent;
   /** Count of values. */
   ulonglong m_count;
   /** Sum of values. */
@@ -44,60 +39,48 @@ struct PFS_single_stat_chain
   ulonglong m_min;
   /** Maximum value. */
   ulonglong m_max;
-};
 
-/**
-  Reset a single statistic link.
-  Only the current link is reset, parents are not affected.
-  @param stat                         the statistics link to reset
-*/
-inline void reset_single_stat_link(PFS_single_stat_chain *stat)
-{
-  stat->m_count= 0;
-  stat->m_sum= 0;
-  stat->m_min= ULONGLONG_MAX;
-  stat->m_max= 0;
-}
+  PFS_single_stat()
+  {
+    m_count= 0;
+    m_sum= 0;
+    m_min= ULONGLONG_MAX;
+    m_max= 0;
+  }
 
-/**
-  Aggregate a value to a statistic chain.
-  @param stat                         the aggregated statistic chain
-  @param value                        the value to aggregate
-*/
-inline void aggregate_single_stat_chain(PFS_single_stat_chain *stat,
-                                        ulonglong value)
-{
-  do
+  inline void reset(void)
   {
-    if (*stat->m_control_flag)
-    {
-      stat->m_count++;
-      stat->m_sum+= value;
-      if (stat->m_min > value)
-        stat->m_min= value;
-      if (stat->m_max < value)
-        stat->m_max= value;
-    }
-    stat= stat->m_parent;
+    m_count= 0;
+    m_sum= 0;
+    m_min= ULONGLONG_MAX;
+    m_max= 0;
   }
-  while (stat);
-}
 
-/**
-  Increment the value counts in a statistic chain.
-  Used for instruments that are 'ENABLED' but not 'TIMED'.
-  @param stat                         the aggregated statistic chain
-*/
-inline void increment_single_stat_chain(PFS_single_stat_chain *stat)
-{
-  do
+  inline void aggregate(const PFS_single_stat *stat)
   {
-    if (*stat->m_control_flag)
-      stat->m_count++;
-    stat= stat->m_parent;
+    m_count+= stat->m_count;
+    m_sum+= stat->m_sum;
+    if (unlikely(m_min > stat->m_min))
+      m_min= stat->m_min;
+    if (unlikely(m_max < stat->m_max))
+      m_max= stat->m_max;
   }
-  while (stat);
-}
+
+  inline void aggregate_counted()
+  {
+    m_count++;
+  }
+
+  inline void aggregate_timed(ulonglong value)
+  {
+    m_count++;
+    m_sum+= value;
+    if (unlikely(m_min > value))
+      m_min= value;
+    if (unlikely(m_max < value))
+      m_max= value;
+  }
+};
 
 /** Statistics for COND usage. */
 struct PFS_cond_stat
@@ -108,11 +91,9 @@ struct PFS_cond_stat
   ulonglong m_broadcast_count;
 };
 
-/** Statistics for FILE usage. */
-struct PFS_file_stat
+/** Statistics for FILE IO usage. */
+struct PFS_file_io_stat
 {
-  /** Number of current open handles. */
-  ulong m_open_count;
   /** Count of READ operations. */
   ulonglong m_count_read;
   /** Count of WRITE operations. */
@@ -121,20 +102,125 @@ struct PFS_file_stat
   ulonglong m_read_bytes;
   /** Number of bytes written. */
   ulonglong m_write_bytes;
+
+  /** Reset file statistic. */
+  inline void reset(void)
+  {
+    m_count_read= 0;
+    m_count_write= 0;
+    m_read_bytes= 0;
+    m_write_bytes= 0;
+  }
+
+  inline void aggregate(const PFS_file_io_stat *stat)
+  {
+    m_count_read+= stat->m_count_read;
+    m_count_write+= stat->m_count_write;
+    m_read_bytes+= stat->m_read_bytes;
+    m_write_bytes+= stat->m_write_bytes;
+  }
+
+  inline void aggregate_read(ulonglong bytes)
+  {
+    m_count_read++;
+    m_read_bytes+= bytes;
+  }
+
+  inline void aggregate_write(ulonglong bytes)
+  {
+    m_count_write++;
+    m_write_bytes+= bytes;
+  }
 };
 
-/**
-  Reset file statistic.
-  @param stat                         the statistics to reset
-*/
-inline void reset_file_stat(PFS_file_stat *stat)
+/** Statistics for FILE usage. */
+struct PFS_file_stat
+{
+  /** Number of current open handles. */
+  ulong m_open_count;
+  /** File IO statistics. */
+  PFS_file_io_stat m_io_stat;
+};
+
+/** Single table io statistic. */
+struct PFS_table_io_stat
 {
-  stat->m_open_count= 0;
-  stat->m_count_read= 0;
-  stat->m_count_write= 0;
-  stat->m_read_bytes= 0;
-  stat->m_write_bytes= 0;
-}
+  /** FETCH statistics */
+  PFS_single_stat m_fetch;
+  /** INSERT statistics */
+  PFS_single_stat m_insert;
+  /** UPDATE statistics */
+  PFS_single_stat m_update;
+  /** DELETE statistics */
+  PFS_single_stat m_delete;
+
+  inline void reset(void)
+  {
+    m_fetch.reset();
+    m_insert.reset();
+    m_update.reset();
+    m_delete.reset();
+  }
+
+  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);
+  }
+
+  inline void sum(PFS_single_stat *result)
+  {
+    result->aggregate(& m_fetch);
+    result->aggregate(& m_insert);
+    result->aggregate(& m_update);
+    result->aggregate(& m_delete);
+  }
+};
+
+/** Statistics for TABLE usage. */
+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].
+  */
+  PFS_table_io_stat m_index_stat[MAX_KEY + 1];
+
+  /** Reset table statistic. */
+  inline void reset(void)
+  {
+    PFS_table_io_stat *stat= & m_index_stat[0];
+    PFS_table_io_stat *stat_last= & m_index_stat[MAX_KEY + 1];
+    for ( ; stat < stat_last ; stat++)
+      stat->reset();
+  }
+
+  inline void aggregate(const PFS_table_stat *stat)
+  {
+    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];
+    for ( ; to_stat < to_stat_last ; from_stat++, to_stat++)
+      to_stat->aggregate(from_stat);
+  }
+
+  inline void sum_io(PFS_single_stat *result)
+  {
+    PFS_table_io_stat *stat= & m_index_stat[0];
+    PFS_table_io_stat *stat_last= & m_index_stat[MAX_KEY + 1];
+    for ( ; stat < stat_last ; stat++)
+      stat->sum(result);
+  }
+
+  inline void sum(PFS_single_stat *result)
+  {
+    sum_io(result);
+    /* sum_lock(result); */
+  }
+};
 
 /** @} */
 #endif

=== modified file 'storage/perfschema/pfs_timer.cc'
--- a/storage/perfschema/pfs_timer.cc	2010-07-16 01:28:30 +0000
+++ b/storage/perfschema/pfs_timer.cc	2010-09-23 16:08:54 +0000
@@ -37,6 +37,17 @@ static ulong microsec_to_pico; /* In the
 static ulong millisec_to_pico; /* In theory, 1 000 000 000, fits in uint32 */
 static ulonglong tick_to_pico; /* 1e10 at 100 Hz, 1.666e10 at 60 Hz */
 
+/* Indexed by enum enum_timer_name */
+static struct time_normalizer to_pico_data[FIRST_TIMER_NAME + COUNT_TIMER_NAME]=
+{
+  { 0, 0}, /* unused */
+  { 0, 0}, /* cycle */
+  { 0, 0}, /* nanosec */
+  { 0, 0}, /* microsec */
+  { 0, 0}, /* millisec */
+  { 0, 0}  /* tick */
+};
+
 static inline ulong round_to_ulong(double value)
 {
   return (ulong) (value + 0.5);
@@ -88,13 +99,55 @@ void init_timers(void)
                                      (double)pfs_timer_info.ticks.frequency);
   else
     tick_to_pico= 0;
+
+  to_pico_data[TIMER_NAME_CYCLE].m_v0= cycle_v0;
+  to_pico_data[TIMER_NAME_CYCLE].m_factor= cycle_to_pico;
+
+  to_pico_data[TIMER_NAME_NANOSEC].m_v0= nanosec_v0;
+  to_pico_data[TIMER_NAME_NANOSEC].m_factor= nanosec_to_pico;
+
+  to_pico_data[TIMER_NAME_MICROSEC].m_v0= microsec_v0;
+  to_pico_data[TIMER_NAME_MICROSEC].m_factor= microsec_to_pico;
+
+  to_pico_data[TIMER_NAME_MILLISEC].m_v0= millisec_v0;
+  to_pico_data[TIMER_NAME_MILLISEC].m_factor= millisec_to_pico;
+
+  to_pico_data[TIMER_NAME_TICK].m_v0= tick_v0;
+  to_pico_data[TIMER_NAME_TICK].m_factor= tick_to_pico;
 }
 
-ulonglong get_timer_value(enum_timer_name timer_name)
+ulonglong get_timer_raw_value_and_function(enum_timer_name timer_name, timer_fct_t *fct)
+{
+  switch (timer_name)
+  {
+  case TIMER_NAME_CYCLE:
+    *fct= my_timer_cycles;
+    return my_timer_cycles();
+  case TIMER_NAME_NANOSEC:
+    *fct= my_timer_nanoseconds;
+    return my_timer_nanoseconds();
+  case TIMER_NAME_MICROSEC:
+    *fct= my_timer_microseconds;
+    return my_timer_microseconds();
+  case TIMER_NAME_MILLISEC:
+    *fct= my_timer_milliseconds;
+    return my_timer_milliseconds();
+  case TIMER_NAME_TICK:
+    *fct= my_timer_ticks;
+    return my_timer_ticks();
+  default:
+    *fct= NULL;
+    DBUG_ASSERT(false);
+  }
+  return 0;
+}
+
+ulonglong get_timer_pico_value(enum_timer_name timer_name)
 {
   ulonglong result;
 
-  switch (timer_name) {
+  switch (timer_name)
+  {
   case TIMER_NAME_CYCLE:
     result= (my_timer_cycles() - cycle_v0) * cycle_to_pico;
     break;
@@ -117,3 +170,38 @@ ulonglong get_timer_value(enum_timer_nam
   return result;
 }
 
+time_normalizer* time_normalizer::get(enum_timer_name timer_name)
+{
+  uint index= static_cast<uint> (timer_name);
+
+  DBUG_ASSERT(index >= FIRST_TIMER_NAME);
+  DBUG_ASSERT(index <= LAST_TIMER_NAME);
+
+  return & to_pico_data[index];
+}
+
+void time_normalizer::to_pico(ulonglong start, ulonglong end,
+                              ulonglong *pico_start, ulonglong *pico_end, ulonglong *pico_wait)
+{
+  if (start == 0)
+  {
+    *pico_start= 0;
+    *pico_end= 0;
+    *pico_wait= 0;
+  }
+  else
+  {
+    *pico_start= (start - m_v0) * m_factor;
+    if (end == 0)
+    {
+      *pico_end= 0;
+      *pico_wait= 0;
+    }
+    else
+    {
+      *pico_end= (end - m_v0) * m_factor;
+      *pico_wait= (end - start) * m_factor;
+    }
+  }
+}
+

=== modified file 'storage/perfschema/pfs_timer.h'
--- a/storage/perfschema/pfs_timer.h	2010-07-16 01:28:30 +0000
+++ b/storage/perfschema/pfs_timer.h	2010-09-23 16:08:54 +0000
@@ -23,12 +23,40 @@
 #include <my_rdtsc.h>
 #include "pfs_column_types.h"
 
+struct time_normalizer
+{
+  static time_normalizer* get(enum_timer_name timer_name);
+
+  ulonglong m_v0;
+  ulonglong m_factor;
+
+  inline ulonglong wait_to_pico(ulonglong wait)
+  {
+    return wait * m_factor;
+  }
+
+  inline ulonglong time_to_pico(ulonglong t)
+  {
+    return (t == 0 ? 0 : (t - m_v0) * m_factor);
+  }
+
+  void to_pico(ulonglong start, ulonglong end,
+               ulonglong *pico_start, ulonglong *pico_end, ulonglong *pico_wait);
+};
+
 extern enum_timer_name wait_timer;
 extern MY_TIMER_INFO pfs_timer_info;
 
 void init_timers();
 
-ulonglong get_timer_value(enum_timer_name timer_name);
+extern "C"
+{
+  typedef ulonglong (*timer_fct_t)(void);
+}
+
+ulonglong get_timer_pico_value(enum_timer_name timer_name);
+ulonglong get_timer_raw_value_and_function(enum_timer_name timer_name, timer_fct_t *fct);
+
 
 #endif
 

=== modified file 'storage/perfschema/table_all_instr.cc'
--- a/storage/perfschema/table_all_instr.cc	2010-07-16 01:28:30 +0000
+++ b/storage/perfschema/table_all_instr.cc	2010-09-23 16:08:54 +0000
@@ -151,115 +151,3 @@ int table_all_instr::rnd_pos(const void
   return HA_ERR_RECORD_DELETED;
 }
 
-table_all_instr_class::table_all_instr_class
-(const PFS_engine_table_share *share)
-  : PFS_engine_table(share, &m_pos),
-    m_pos(), m_next_pos()
-{}
-
-void table_all_instr_class::reset_position(void)
-{
-  m_pos.reset();
-  m_next_pos.reset();
-}
-
-int table_all_instr_class::rnd_next(void)
-{
-  PFS_mutex_class *mutex_class;
-  PFS_rwlock_class *rwlock_class;
-  PFS_cond_class *cond_class;
-  PFS_file_class *file_class;
-
-  for (m_pos.set_at(&m_next_pos);
-       m_pos.has_more_view();
-       m_pos.next_view())
-  {
-    switch (m_pos.m_index_1) {
-    case pos_all_instr_class::VIEW_MUTEX:
-      mutex_class= find_mutex_class(m_pos.m_index_2);
-      if (mutex_class)
-      {
-        make_instr_row(mutex_class);
-        m_next_pos.set_after(&m_pos);
-        return 0;
-      }
-      break;
-    case pos_all_instr_class::VIEW_RWLOCK:
-      rwlock_class= find_rwlock_class(m_pos.m_index_2);
-      if (rwlock_class)
-      {
-        make_instr_row(rwlock_class);
-        m_next_pos.set_after(&m_pos);
-        return 0;
-      }
-      break;
-    case pos_all_instr_class::VIEW_COND:
-      cond_class= find_cond_class(m_pos.m_index_2);
-      if (cond_class)
-      {
-        make_instr_row(cond_class);
-        m_next_pos.set_after(&m_pos);
-        return 0;
-      }
-      break;
-    case pos_all_instr_class::VIEW_FILE:
-      file_class= find_file_class(m_pos.m_index_2);
-      if (file_class)
-      {
-        make_instr_row(file_class);
-        m_next_pos.set_after(&m_pos);
-        return 0;
-      }
-      break;
-    }
-  }
-
-  return HA_ERR_END_OF_FILE;
-}
-
-int table_all_instr_class::rnd_pos(const void *pos)
-{
-  PFS_mutex_class *mutex_class;
-  PFS_rwlock_class *rwlock_class;
-  PFS_cond_class *cond_class;
-  PFS_file_class *file_class;
-
-  set_position(pos);
-  switch (m_pos.m_index_1) {
-  case pos_all_instr_class::VIEW_MUTEX:
-    mutex_class= find_mutex_class(m_pos.m_index_2);
-    if (mutex_class)
-    {
-      make_instr_row(mutex_class);
-      return 0;
-    }
-    break;
-  case pos_all_instr_class::VIEW_RWLOCK:
-    rwlock_class= find_rwlock_class(m_pos.m_index_2);
-    if (rwlock_class)
-    {
-      make_instr_row(rwlock_class);
-      return 0;
-    }
-    break;
-  case pos_all_instr_class::VIEW_COND:
-    cond_class= find_cond_class(m_pos.m_index_2);
-    if (cond_class)
-    {
-      make_instr_row(cond_class);
-      return 0;
-    }
-    break;
-  case pos_all_instr_class::VIEW_FILE:
-    file_class= find_file_class(m_pos.m_index_2);
-    if (file_class)
-    {
-      make_instr_row(file_class);
-      return 0;
-    }
-    break;
-  }
-
-  return HA_ERR_RECORD_DELETED;
-}
-

=== modified file 'storage/perfschema/table_all_instr.h'
--- a/storage/perfschema/table_all_instr.h	2010-07-23 17:08:41 +0000
+++ b/storage/perfschema/table_all_instr.h	2010-09-23 16:08:54 +0000
@@ -31,66 +31,6 @@
   @{
 */
 
-/** Position of a cursor on table_all_instr_class. */
-struct pos_all_instr_class : public PFS_double_index,
-                             public PFS_instrument_view_constants
-{
-  pos_all_instr_class()
-    : PFS_double_index(FIRST_VIEW, 1)
-  {}
-
-  inline void reset(void)
-  {
-    m_index_1= FIRST_VIEW;
-    m_index_2= 1;
-  }
-
-  inline bool has_more_view(void)
-  { return (m_index_1 <= LAST_VIEW); }
-
-  inline void next_view(void)
-  {
-    m_index_1++;
-    /* Instrument keys start at 1, not 0. */
-    m_index_2= 1;
-  }
-};
-
-/**
-  Abstract table, a union of all instrumentations class metadata.
-  This table is a union of:
-  - a view on all mutex classes,
-  - a view on all rwlock classes,
-  - a view on all cond classes,
-  - a view on all file classes
-*/
-class table_all_instr_class : public PFS_engine_table
-{
-public:
-  virtual int rnd_next();
-  virtual int rnd_pos(const void *pos);
-  virtual void reset_position(void);
-
-protected:
-  table_all_instr_class(const PFS_engine_table_share *share);
-
-public:
-  ~table_all_instr_class()
-  {}
-
-protected:
-  /**
-    Build a row.
-    @param klass                      the instrument class
-  */
-  virtual void make_instr_row(PFS_instr_class *klass)= 0;
-
-  /** Current position. */
-  pos_all_instr_class m_pos;
-  /** Next position. */
-  pos_all_instr_class m_next_pos;
-};
-
 /** Position of a cursor on table_all_instr. */
 struct pos_all_instr : public PFS_double_index,
                        public PFS_instrument_view_constants

=== modified file 'storage/perfschema/table_events_waits.cc'
--- a/storage/perfschema/table_events_waits.cc	2010-08-26 22:46:51 +0000
+++ b/storage/perfschema/table_events_waits.cc	2010-09-23 16:08:54 +0000
@@ -24,6 +24,7 @@
 #include "pfs_instr_class.h"
 #include "pfs_instr.h"
 #include "pfs_events_waits.h"
+#include "pfs_timer.h"
 
 THR_LOCK table_events_waits_current::m_table_lock;
 
@@ -226,10 +227,14 @@ void table_events_waits_common::make_row
 
   m_row.m_thread_internal_id= safe_thread->m_thread_internal_id;
   m_row.m_event_id= wait->m_event_id;
+#ifdef HAVE_NESTED_EVENTS
   m_row.m_nesting_event_id= wait->m_nesting_event_id;
-  m_row.m_timer_state= wait->m_timer_state;
-  m_row.m_timer_start= wait->m_timer_start;
-  m_row.m_timer_end= wait->m_timer_end;
+#endif
+
+  time_normalizer *normalizer= time_normalizer::get(wait_timer);
+  normalizer->to_pico(wait->m_timer_start, wait->m_timer_end,
+                      & m_row.m_timer_start, & m_row.m_timer_end, & m_row.m_timer_wait);
+
   m_row.m_object_instance_addr= (intptr) wait->m_object_instance_addr;
 
   /*
@@ -269,7 +274,7 @@ void table_events_waits_common::make_row
     memcpy(m_row.m_object_name, wait->m_object_name,
            wait->m_object_name_length);
     m_row.m_object_name_length= wait->m_object_name_length;
-    safe_class= &global_table_class;
+    safe_class= sanitize_table_class(wait->m_class);
     break;
   case WAIT_CLASS_FILE:
     m_row.m_object_type= "FILE";
@@ -423,21 +428,20 @@ int table_events_waits_common::read_row_
         set_field_varchar_utf8(f, m_row.m_source, m_row.m_source_length);
         break;
       case 4: /* TIMER_START */
-        if ((m_row.m_timer_state == TIMER_STATE_STARTED) ||
-            (m_row.m_timer_state == TIMER_STATE_TIMED))
+        if (m_row.m_timer_start != 0)
           set_field_ulonglong(f, m_row.m_timer_start);
         else
           f->set_null();
         break;
       case 5: /* TIMER_END */
-        if (m_row.m_timer_state == TIMER_STATE_TIMED)
+        if (m_row.m_timer_end != 0)
           set_field_ulonglong(f, m_row.m_timer_end);
         else
           f->set_null();
         break;
       case 6: /* TIMER_WAIT */
-        if (m_row.m_timer_state == TIMER_STATE_TIMED)
-          set_field_ulonglong(f, m_row.m_timer_end - m_row.m_timer_start);
+        if (m_row.m_timer_wait != 0)
+          set_field_ulonglong(f, m_row.m_timer_wait);
         else
           f->set_null();
         break;
@@ -475,7 +479,11 @@ int table_events_waits_common::read_row_
         set_field_ulonglong(f, m_row.m_object_instance_addr);
         break;
       case 12: /* NESTING_EVENT_ID */
+#ifdef HAVE_NESTED_EVENTS
         set_field_ulonglong(f, m_row.m_nesting_event_id);
+#else
+        f->set_null();
+#endif
         break;
       case 13: /* OPERATION */
         operation= &operation_names_map[(int) m_row.m_operation - 1];
@@ -547,9 +555,9 @@ int table_events_waits_current::rnd_next
     if (m_pos.m_index_2 >= 1)
       continue;
 #else
-    uint safe_locker_count= pfs_thread->m_wait_locker_count;
+    uint safe_events_waits_count= pfs_thread->m_events_waits_count;
 
-    if (safe_locker_count == 0)
+    if (safe_events_waits_count == 0)
     {
       /* Display the last top level wait, when completed */
       if (m_pos.m_index_2 >= 1)
@@ -558,12 +566,12 @@ int table_events_waits_current::rnd_next
     else
     {
       /* Display all pending waits, when in progress */
-      if (m_pos.m_index_2 >= safe_locker_count)
+      if (m_pos.m_index_2 >= safe_events_waits_count)
         continue;
     }
 #endif
 
-    wait= &pfs_thread->m_wait_locker_stack[m_pos.m_index_2].m_waits_current;
+    wait= &pfs_thread->m_events_waits_stack[m_pos.m_index_2];
 
     if (wait->m_wait_class == NO_WAIT_CLASS)
     {
@@ -599,9 +607,9 @@ int table_events_waits_current::rnd_pos(
   if (m_pos.m_index_2 >= 1)
     return HA_ERR_RECORD_DELETED;
 #else
-  uint safe_locker_count= pfs_thread->m_wait_locker_count;
+  uint safe_events_waits_count= pfs_thread->m_events_waits_count;
 
-  if (safe_locker_count == 0)
+  if (safe_events_waits_count == 0)
   {
     /* Display the last top level wait, when completed */
     if (m_pos.m_index_2 >= 1)
@@ -610,14 +618,14 @@ int table_events_waits_current::rnd_pos(
   else
   {
     /* Display all pending waits, when in progress */
-    if (m_pos.m_index_2 >= safe_locker_count)
+    if (m_pos.m_index_2 >= safe_events_waits_count)
       return HA_ERR_RECORD_DELETED;
   }
 #endif
 
-  DBUG_ASSERT(m_pos.m_index_2 < LOCKER_STACK_SIZE);
+  DBUG_ASSERT(m_pos.m_index_2 < WAIT_STACK_SIZE);
 
-  wait= &pfs_thread->m_wait_locker_stack[m_pos.m_index_2].m_waits_current;
+  wait= &pfs_thread->m_events_waits_stack[m_pos.m_index_2];
 
   if (wait->m_wait_class == NO_WAIT_CLASS)
     return HA_ERR_RECORD_DELETED;

=== modified file 'storage/perfschema/table_events_waits.h'
--- a/storage/perfschema/table_events_waits.h	2010-07-30 09:02:32 +0000
+++ b/storage/perfschema/table_events_waits.h	2010-09-23 16:08:54 +0000
@@ -45,14 +45,12 @@ struct row_events_waits
   const char *m_name;
   /** Length in bytes of @c m_name. */
   uint m_name_length;
-  /** Timer state. */
-  enum timer_state m_timer_state;
   /** Column TIMER_START. */
   ulonglong m_timer_start;
-  /** True if TIMER_END is null. */
-  bool m_timer_end_null;
   /** Column TIMER_END. */
   ulonglong m_timer_end;
+  /** Column TIMER_WAIT. */
+  ulonglong m_timer_wait;
   /** Column OBJECT_TYPE. */
   const char *m_object_type;
   /** Length in bytes of @c m_object_type. */

=== modified file 'storage/perfschema/table_events_waits_summary.cc'
--- a/storage/perfschema/table_events_waits_summary.cc	2010-09-01 22:59:33 +0000
+++ b/storage/perfschema/table_events_waits_summary.cc	2010-09-23 16:08:54 +0000
@@ -26,319 +26,6 @@
 #include "table_events_waits_summary.h"
 #include "pfs_global.h"
 
-THR_LOCK table_events_waits_summary_by_thread_by_event_name::m_table_lock;
-
-static const TABLE_FIELD_TYPE ews_by_thread_by_event_name_field_types[]=
-{
-  {
-    { C_STRING_WITH_LEN("THREAD_ID") },
-    { C_STRING_WITH_LEN("int(11)") },
-    { NULL, 0}
-  },
-  {
-    { C_STRING_WITH_LEN("EVENT_NAME") },
-    { C_STRING_WITH_LEN("varchar(128)") },
-    { NULL, 0}
-  },
-  {
-    { C_STRING_WITH_LEN("COUNT_STAR") },
-    { C_STRING_WITH_LEN("bigint(20)") },
-    { NULL, 0}
-  },
-  {
-    { C_STRING_WITH_LEN("SUM_TIMER_WAIT") },
-    { C_STRING_WITH_LEN("bigint(20)") },
-    { NULL, 0}
-  },
-  {
-    { C_STRING_WITH_LEN("MIN_TIMER_WAIT") },
-    { C_STRING_WITH_LEN("bigint(20)") },
-    { NULL, 0}
-  },
-  {
-    { C_STRING_WITH_LEN("AVG_TIMER_WAIT") },
-    { C_STRING_WITH_LEN("bigint(20)") },
-    { NULL, 0}
-  },
-  {
-    { C_STRING_WITH_LEN("MAX_TIMER_WAIT") },
-    { C_STRING_WITH_LEN("bigint(20)") },
-    { NULL, 0}
-  }
-};
-
-TABLE_FIELD_DEF
-table_events_waits_summary_by_thread_by_event_name::m_field_def=
-{ 7, ews_by_thread_by_event_name_field_types };
-
-PFS_engine_table_share
-table_events_waits_summary_by_thread_by_event_name::m_share=
-{
-  { C_STRING_WITH_LEN("EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME") },
-  &pfs_truncatable_acl,
-  &table_events_waits_summary_by_thread_by_event_name::create,
-  NULL, /* write_row */
-  &table_events_waits_summary_by_thread_by_event_name::delete_all_rows,
-  NULL, /* get_row_count */
-  1000, /* records */
-  sizeof(pos_events_waits_summary_by_thread_by_event_name),
-  &m_table_lock,
-  &m_field_def,
-  false /* checked */
-};
-
-PFS_engine_table*
-table_events_waits_summary_by_thread_by_event_name::create(void)
-{
-  return new table_events_waits_summary_by_thread_by_event_name();
-}
-
-int
-table_events_waits_summary_by_thread_by_event_name::delete_all_rows(void)
-{
-  reset_per_thread_wait_stat();
-  return 0;
-}
-
-table_events_waits_summary_by_thread_by_event_name
-::table_events_waits_summary_by_thread_by_event_name()
-  : PFS_engine_table(&m_share, &m_pos),
-    m_row_exists(false), m_pos(), m_next_pos()
-{}
-
-void table_events_waits_summary_by_thread_by_event_name::reset_position(void)
-{
-  m_pos.reset();
-  m_next_pos.reset();
-}
-
-int table_events_waits_summary_by_thread_by_event_name::rnd_next(void)
-{
-  PFS_thread *thread;
-  PFS_mutex_class *mutex_class;
-  PFS_rwlock_class *rwlock_class;
-  PFS_cond_class *cond_class;
-  PFS_file_class *file_class;
-
-  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())
-    {
-      for ( ; m_pos.has_more_view(); m_pos.next_view())
-      {
-        switch (m_pos.m_index_2) {
-        case pos_events_waits_summary_by_thread_by_event_name::VIEW_MUTEX:
-          mutex_class= find_mutex_class(m_pos.m_index_3);
-          if (mutex_class)
-          {
-            make_mutex_row(thread, mutex_class);
-            m_next_pos.set_after(&m_pos);
-            return 0;
-          }
-          break;
-        case pos_events_waits_summary_by_thread_by_event_name::VIEW_RWLOCK:
-          rwlock_class= find_rwlock_class(m_pos.m_index_3);
-          if (rwlock_class)
-          {
-            make_rwlock_row(thread, rwlock_class);
-            m_next_pos.set_after(&m_pos);
-            return 0;
-          }
-          break;
-        case pos_events_waits_summary_by_thread_by_event_name::VIEW_COND:
-          cond_class= find_cond_class(m_pos.m_index_3);
-          if (cond_class)
-          {
-            make_cond_row(thread, cond_class);
-            m_next_pos.set_after(&m_pos);
-            return 0;
-          }
-          break;
-        case pos_events_waits_summary_by_thread_by_event_name::VIEW_FILE:
-          file_class= find_file_class(m_pos.m_index_3);
-          if (file_class)
-          {
-            make_file_row(thread, file_class);
-            m_next_pos.set_after(&m_pos);
-            return 0;
-          }
-          break;
-        }
-      }
-    }
-  }
-
-  return HA_ERR_END_OF_FILE;
-}
-
-int
-table_events_waits_summary_by_thread_by_event_name::rnd_pos(const void *pos)
-{
-  PFS_thread *thread;
-  PFS_mutex_class *mutex_class;
-  PFS_rwlock_class *rwlock_class;
-  PFS_cond_class *cond_class;
-  PFS_file_class *file_class;
-
-  set_position(pos);
-  DBUG_ASSERT(m_pos.m_index_1 < thread_max);
-
-  thread= &thread_array[m_pos.m_index_1];
-  if (! thread->m_lock.is_populated())
-    return HA_ERR_RECORD_DELETED;
-
-  switch (m_pos.m_index_2) {
-  case pos_events_waits_summary_by_thread_by_event_name::VIEW_MUTEX:
-    mutex_class= find_mutex_class(m_pos.m_index_3);
-    if (mutex_class)
-    {
-      make_mutex_row(thread, mutex_class);
-      return 0;
-    }
-    break;
-  case pos_events_waits_summary_by_thread_by_event_name::VIEW_RWLOCK:
-    rwlock_class= find_rwlock_class(m_pos.m_index_3);
-    if (rwlock_class)
-    {
-      make_rwlock_row(thread, rwlock_class);
-      return 0;
-    }
-    break;
-  case pos_events_waits_summary_by_thread_by_event_name::VIEW_COND:
-    cond_class= find_cond_class(m_pos.m_index_3);
-    if (cond_class)
-    {
-      make_cond_row(thread, cond_class);
-      return 0;
-    }
-    break;
-  case pos_events_waits_summary_by_thread_by_event_name::VIEW_FILE:
-    file_class= find_file_class(m_pos.m_index_3);
-    if (file_class)
-    {
-      make_file_row(thread, file_class);
-      return 0;
-    }
-    break;
-  }
-  return HA_ERR_RECORD_DELETED;
-}
-
-void table_events_waits_summary_by_thread_by_event_name
-::make_instr_row(PFS_thread *thread, PFS_instr_class *klass,
-                 PFS_single_stat_chain *stat)
-{
-  pfs_lock lock;
-
-  m_row_exists= false;
-
-  /* Protect this reader against a thread termination */
-  thread->m_lock.begin_optimistic_lock(&lock);
-
-  m_row.m_thread_internal_id= thread->m_thread_internal_id;
-  m_row.m_name= klass->m_name;
-  m_row.m_name_length= klass->m_name_length;
-
-  m_row.m_count= stat->m_count;
-  m_row.m_sum= stat->m_sum;
-  m_row.m_min= stat->m_min;
-  m_row.m_max= stat->m_max;
-
-  if (m_row.m_count)
-    m_row.m_avg= m_row.m_sum / m_row.m_count;
-  else
-  {
-    m_row.m_min= 0;
-    m_row.m_avg= 0;
-  }
-
-  if (thread->m_lock.end_optimistic_lock(&lock))
-    m_row_exists= true;
-}
-
-void table_events_waits_summary_by_thread_by_event_name
-::make_mutex_row(PFS_thread *thread, PFS_mutex_class *klass)
-{
-  PFS_single_stat_chain *stat;
-  stat= find_per_thread_mutex_class_wait_stat(thread, klass);
-  make_instr_row(thread, klass, stat);
-}
-
-void table_events_waits_summary_by_thread_by_event_name
-::make_rwlock_row(PFS_thread *thread, PFS_rwlock_class *klass)
-{
-  PFS_single_stat_chain *stat;
-  stat= find_per_thread_rwlock_class_wait_stat(thread, klass);
-  make_instr_row(thread, klass, stat);
-}
-
-void table_events_waits_summary_by_thread_by_event_name
-::make_cond_row(PFS_thread *thread, PFS_cond_class *klass)
-{
-  PFS_single_stat_chain *stat;
-  stat= find_per_thread_cond_class_wait_stat(thread, klass);
-  make_instr_row(thread, klass, stat);
-}
-
-void table_events_waits_summary_by_thread_by_event_name
-::make_file_row(PFS_thread *thread, PFS_file_class *klass)
-{
-  PFS_single_stat_chain *stat;
-  stat= find_per_thread_file_class_wait_stat(thread, klass);
-  make_instr_row(thread, klass, stat);
-}
-
-int table_events_waits_summary_by_thread_by_event_name
-::read_row_values(TABLE *table, unsigned char *, Field **fields,
-                  bool read_all)
-{
-  Field *f;
-
-  if (unlikely(! m_row_exists))
-    return HA_ERR_RECORD_DELETED;
-
-  /* Set the null bits */
-  DBUG_ASSERT(table->s->null_bytes == 0);
-
-  for (; (f= *fields) ; fields++)
-  {
-    if (read_all || bitmap_is_set(table->read_set, f->field_index))
-    {
-      switch(f->field_index)
-      {
-      case 0: /* THREAD_ID */
-        set_field_ulong(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: /* COUNT */
-        set_field_ulonglong(f, m_row.m_count);
-        break;
-      case 3: /* SUM */
-        set_field_ulonglong(f, m_row.m_sum);
-        break;
-      case 4: /* MIN */
-        set_field_ulonglong(f, m_row.m_min);
-        break;
-      case 5: /* AVG */
-        set_field_ulonglong(f, m_row.m_avg);
-        break;
-      case 6: /* MAX */
-        set_field_ulonglong(f, m_row.m_max);
-        break;
-      default:
-        DBUG_ASSERT(false);
-      }
-    }
-  }
-
-  return 0;
-}
-
 THR_LOCK table_events_waits_summary_by_instance::m_table_lock;
 
 static const TABLE_FIELD_TYPE ews_by_instance_field_types[]=
@@ -434,18 +121,8 @@ void table_events_waits_summary_by_insta
   m_row.m_name_length= klass->m_name_length;
   m_row.m_object_instance_addr= (intptr) object_instance_begin;
 
-  m_row.m_count= pfs->m_wait_stat.m_count;
-  m_row.m_sum= pfs->m_wait_stat.m_sum;
-  m_row.m_min= pfs->m_wait_stat.m_min;
-  m_row.m_max= pfs->m_wait_stat.m_max;
-
-  if (m_row.m_count)
-    m_row.m_avg= m_row.m_sum / m_row.m_count;
-  else
-  {
-    m_row.m_min= 0;
-    m_row.m_avg= 0;
-  }
+  time_normalizer *normalizer= time_normalizer::get(wait_timer);
+  m_row.m_stat.set(normalizer, & pfs->m_wait_stat);
 
   if (pfs->m_lock.end_optimistic_lock(&lock))
     m_row_exists= true;
@@ -536,19 +213,19 @@ int table_events_waits_summary_by_instan
         set_field_ulonglong(f, m_row.m_object_instance_addr);
         break;
       case 2: /* COUNT */
-        set_field_ulonglong(f, m_row.m_count);
+        set_field_ulonglong(f, m_row.m_stat.m_count);
         break;
       case 3: /* SUM */
-        set_field_ulonglong(f, m_row.m_sum);
+        set_field_ulonglong(f, m_row.m_stat.m_sum);
         break;
       case 4: /* MIN */
-        set_field_ulonglong(f, m_row.m_min);
+        set_field_ulonglong(f, m_row.m_stat.m_min);
         break;
       case 5: /* AVG */
-        set_field_ulonglong(f, m_row.m_avg);
+        set_field_ulonglong(f, m_row.m_stat.m_avg);
         break;
       case 6: /* MAX */
-        set_field_ulonglong(f, m_row.m_max);
+        set_field_ulonglong(f, m_row.m_stat.m_max);
         break;
       default:
         DBUG_ASSERT(false);

=== modified file 'storage/perfschema/table_events_waits_summary.h'
--- a/storage/perfschema/table_events_waits_summary.h	2010-09-01 22:59:33 +0000
+++ b/storage/perfschema/table_events_waits_summary.h	2010-09-23 16:08:54 +0000
@@ -33,118 +33,6 @@
   @{
 */
 
-/**
-  A row of table
-  PERFORMANCE_SCHEMA.EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME.
-*/
-struct row_events_waits_summary_by_thread_by_event_name
-{
-  /** Column THREAD_ID. */
-  ulong m_thread_internal_id;
-  /** Column EVENT_NAME. */
-  const char *m_name;
-  /** Length in bytes of @c m_name. */
-  uint m_name_length;
-  /** Column COUNT_STAR. */
-  ulonglong m_count;
-  /** Column SUM_TIMER_WAIT. */
-  ulonglong m_sum;
-  /** Column MIN_TIMER_WAIT. */
-  ulonglong m_min;
-  /** Column AVG_TIMER_WAIT. */
-  ulonglong m_avg;
-  /** Column MAX_TIMER_WAIT. */
-  ulonglong m_max;
-};
-
-/**
-  Position of a cursor on
-  PERFORMANCE_SCHEMA.EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME.
-*/
-struct pos_events_waits_summary_by_thread_by_event_name
-: public PFS_triple_index, public PFS_instrument_view_constants
-{
-  pos_events_waits_summary_by_thread_by_event_name()
-    : PFS_triple_index(0, FIRST_VIEW, 1)
-  {}
-
-  inline void reset(void)
-  {
-    m_index_1= 0;
-    m_index_2= FIRST_VIEW;
-    m_index_3= 1;
-  }
-
-  inline bool has_more_thread(void)
-  { return (m_index_1 < thread_max); }
-
-  inline bool has_more_view(void)
-  { return (m_index_2 <= LAST_VIEW); }
-
-  inline void next_thread(void)
-  {
-    m_index_1++;
-    m_index_2= FIRST_VIEW;
-    m_index_3= 1;
-  }
-
-  inline void next_view(void)
-  {
-    m_index_2++;
-    m_index_3= 1;
-  }
-};
-
-/** Table PERFORMANCE_SCHEMA.EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME. */
-class table_events_waits_summary_by_thread_by_event_name
-  : public PFS_engine_table
-{
-public:
-  /** Table share */
-  static PFS_engine_table_share m_share;
-  static PFS_engine_table* create();
-  static int delete_all_rows();
-
-  virtual int rnd_next();
-  virtual int rnd_pos(const void *pos);
-  virtual void reset_position(void);
-
-protected:
-  virtual int read_row_values(TABLE *table,
-                              unsigned char *buf,
-                              Field **fields,
-                              bool read_all);
-
-  table_events_waits_summary_by_thread_by_event_name();
-
-public:
-  ~table_events_waits_summary_by_thread_by_event_name()
-  {}
-
-protected:
-  void make_instr_row(PFS_thread *thread, PFS_instr_class *klass,
-                      PFS_single_stat_chain *stat);
-  void make_mutex_row(PFS_thread *thread, PFS_mutex_class *klass);
-  void make_rwlock_row(PFS_thread *thread, PFS_rwlock_class *klass);
-  void make_cond_row(PFS_thread *thread, PFS_cond_class *klass);
-  void make_file_row(PFS_thread *thread, PFS_file_class *klass);
-
-private:
-  /** Table share lock. */
-  static THR_LOCK m_table_lock;
-  /** Fields definition. */
-  static TABLE_FIELD_DEF m_field_def;
-
-  /** Current row. */
-  row_events_waits_summary_by_thread_by_event_name m_row;
-  /** True if the current row exists. */
-  bool m_row_exists;
-  /** Current position. */
-  pos_events_waits_summary_by_thread_by_event_name m_pos;
-  /** Next position. */
-  pos_events_waits_summary_by_thread_by_event_name m_next_pos;
-};
-
 /** A row of PERFORMANCE_SCHEMA.EVENTS_WAITS_SUMMARY_BY_INSTANCE. */
 struct row_events_waits_summary_by_instance
 {
@@ -154,16 +42,8 @@ struct row_events_waits_summary_by_insta
   uint m_name_length;
   /** Column OBJECT_INSTANCE_BEGIN. */
   intptr m_object_instance_addr;
-  /** Column COUNT_STAR. */
-  ulonglong m_count;
-  /** Column SUM_TIMER_WAIT. */
-  ulonglong m_sum;
-  /** Column MIN_TIMER_WAIT. */
-  ulonglong m_min;
-  /** Column AVG_TIMER_WAIT. */
-  ulonglong m_avg;
-  /** Column MAX_TIMER_WAIT. */
-  ulonglong m_max;
+  /** Columns COUNT_STAR, SUM/MIN/AVG/MAX TIMER_WAIT. */
+  PFS_stat_row m_stat;
 };
 
 /** Table PERFORMANCE_SCHEMA.EVENTS_WAITS_SUMMARY_BY_INSTANCE. */

=== added file 'storage/perfschema/table_ews_by_thread_by_event_name.cc'
--- a/storage/perfschema/table_ews_by_thread_by_event_name.cc	1970-01-01 00:00:00 +0000
+++ b/storage/perfschema/table_ews_by_thread_by_event_name.cc	2010-09-23 16:08:54 +0000
@@ -0,0 +1,374 @@
+/* Copyright (c) 2010, 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, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+/**
+  @file storage/perfschema/table_ews_by_thread_by_event_name.cc
+  Table EVENTS_WAITS_SUMMARY_BY_HOST_BY_EVENT_NAME (implementation).
+*/
+
+#include "my_global.h"
+#include "my_pthread.h"
+#include "pfs_instr_class.h"
+#include "pfs_column_types.h"
+#include "pfs_column_values.h"
+#include "table_ews_by_thread_by_event_name.h"
+#include "pfs_global.h"
+
+THR_LOCK table_ews_by_thread_by_event_name::m_table_lock;
+
+static const TABLE_FIELD_TYPE field_types[]=
+{
+  {
+    { C_STRING_WITH_LEN("THREAD_ID") },
+    { C_STRING_WITH_LEN("int(11)") },
+    { NULL, 0}
+  },
+  {
+    { C_STRING_WITH_LEN("EVENT_NAME") },
+    { C_STRING_WITH_LEN("varchar(128)") },
+    { NULL, 0}
+  },
+  {
+    { C_STRING_WITH_LEN("COUNT_STAR") },
+    { C_STRING_WITH_LEN("bigint(20)") },
+    { NULL, 0}
+  },
+  {
+    { C_STRING_WITH_LEN("SUM_TIMER_WAIT") },
+    { C_STRING_WITH_LEN("bigint(20)") },
+    { NULL, 0}
+  },
+  {
+    { C_STRING_WITH_LEN("MIN_TIMER_WAIT") },
+    { C_STRING_WITH_LEN("bigint(20)") },
+    { NULL, 0}
+  },
+  {
+    { C_STRING_WITH_LEN("AVG_TIMER_WAIT") },
+    { C_STRING_WITH_LEN("bigint(20)") },
+    { NULL, 0}
+  },
+  {
+    { C_STRING_WITH_LEN("MAX_TIMER_WAIT") },
+    { C_STRING_WITH_LEN("bigint(20)") },
+    { NULL, 0}
+  }
+};
+
+TABLE_FIELD_DEF
+table_ews_by_thread_by_event_name::m_field_def=
+{ 7, field_types };
+
+PFS_engine_table_share
+table_ews_by_thread_by_event_name::m_share=
+{
+  { C_STRING_WITH_LEN("EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME") },
+  &pfs_truncatable_acl,
+  table_ews_by_thread_by_event_name::create,
+  NULL, /* write_row */
+  table_ews_by_thread_by_event_name::delete_all_rows,
+  NULL, /* get_row_count */
+  1000, /* records */
+  sizeof(pos_ews_by_thread_by_event_name),
+  &m_table_lock,
+  &m_field_def,
+  false /* checked */
+};
+
+PFS_engine_table*
+table_ews_by_thread_by_event_name::create(void)
+{
+  return new table_ews_by_thread_by_event_name();
+}
+
+int
+table_ews_by_thread_by_event_name::delete_all_rows(void)
+{
+  reset_per_thread_wait_stat();
+  return 0;
+}
+
+table_ews_by_thread_by_event_name::table_ews_by_thread_by_event_name()
+  : PFS_engine_table(&m_share, &m_pos),
+    m_row_exists(false), m_pos(), m_next_pos()
+{}
+
+void table_ews_by_thread_by_event_name::reset_position(void)
+{
+  m_pos.reset();
+  m_next_pos.reset();
+}
+
+int table_ews_by_thread_by_event_name::rnd_next(void)
+{
+  PFS_thread *thread;
+  PFS_mutex_class *mutex_class;
+  PFS_rwlock_class *rwlock_class;
+  PFS_cond_class *cond_class;
+  PFS_file_class *file_class;
+  PFS_instr_class *table_class;
+
+  for (m_pos.set_at(&m_next_pos);
+       m_pos.has_more_view();
+       m_pos.next_view())
+  {
+    switch (m_pos.m_index_1)
+    {
+    case pos_ews_by_thread_by_event_name::VIEW_MUTEX:
+      do
+      {
+        mutex_class= find_mutex_class(m_pos.m_index_2);
+        if (mutex_class)
+        {
+          for ( ; m_pos.has_more_thread(); m_pos.next_thread())
+          {
+            thread= &thread_array[m_pos.m_index_3];
+            if (thread->m_lock.is_populated())
+            {
+              make_row(thread, mutex_class);
+              m_next_pos.set_after(&m_pos);
+              return 0;
+            }
+          }
+          m_pos.next_instrument();
+        }
+      } while (mutex_class != NULL);
+      break;
+    case pos_ews_by_thread_by_event_name::VIEW_RWLOCK:
+      do
+      {
+        rwlock_class= find_rwlock_class(m_pos.m_index_2);
+        if (rwlock_class)
+        {
+          for ( ; m_pos.has_more_thread(); m_pos.next_thread())
+          {
+            thread= &thread_array[m_pos.m_index_3];
+            if (thread->m_lock.is_populated())
+            {
+              make_row(thread, rwlock_class);
+              m_next_pos.set_after(&m_pos);
+              return 0;
+            }
+          }
+          m_pos.next_instrument();
+        }
+      } while (rwlock_class != NULL);
+      break;
+    case pos_ews_by_thread_by_event_name::VIEW_COND:
+      do
+      {
+        cond_class= find_cond_class(m_pos.m_index_2);
+        if (cond_class)
+        {
+          for ( ; m_pos.has_more_thread(); m_pos.next_thread())
+          {
+            thread= &thread_array[m_pos.m_index_3];
+            if (thread->m_lock.is_populated())
+            {
+              make_row(thread, cond_class);
+              m_next_pos.set_after(&m_pos);
+              return 0;
+            }
+          }
+          m_pos.next_instrument();
+        }
+      } while (cond_class != NULL);
+      break;
+    case pos_ews_by_thread_by_event_name::VIEW_FILE:
+      do
+      {
+        file_class= find_file_class(m_pos.m_index_2);
+        if (file_class)
+        {
+          for ( ; m_pos.has_more_thread(); m_pos.next_thread())
+          {
+            thread= &thread_array[m_pos.m_index_3];
+            if (thread->m_lock.is_populated())
+            {
+              make_row(thread, file_class);
+              m_next_pos.set_after(&m_pos);
+              return 0;
+            }
+          }
+          m_pos.next_instrument();
+        }
+      } while (file_class != NULL);
+      break;
+    case pos_ews_by_thread_by_event_name::VIEW_TABLE:
+      do
+      {
+        table_class= find_table_class(m_pos.m_index_2);
+        if (table_class)
+        {
+          for ( ; m_pos.has_more_thread(); m_pos.next_thread())
+          {
+            thread= &thread_array[m_pos.m_index_3];
+            if (thread->m_lock.is_populated())
+            {
+              make_row(thread, table_class);
+              m_next_pos.set_after(&m_pos);
+              return 0;
+            }
+          }
+          m_pos.next_instrument();
+        }
+      } while (table_class != NULL);
+      break;
+    default:
+      break;
+    }
+  }
+
+  return HA_ERR_END_OF_FILE;
+}
+
+int
+table_ews_by_thread_by_event_name::rnd_pos(const void *pos)
+{
+  PFS_thread *thread;
+  PFS_mutex_class *mutex_class;
+  PFS_rwlock_class *rwlock_class;
+  PFS_cond_class *cond_class;
+  PFS_file_class *file_class;
+  PFS_instr_class *table_class;
+
+  set_position(pos);
+  DBUG_ASSERT(m_pos.m_index_3 < thread_max);
+
+  thread= &thread_array[m_pos.m_index_3];
+  if (! thread->m_lock.is_populated())
+    return HA_ERR_RECORD_DELETED;
+
+  switch (m_pos.m_index_1)
+  {
+  case pos_ews_by_thread_by_event_name::VIEW_MUTEX:
+    mutex_class= find_mutex_class(m_pos.m_index_2);
+    if (mutex_class)
+    {
+      make_row(thread, mutex_class);
+      return 0;
+    }
+    break;
+  case pos_ews_by_thread_by_event_name::VIEW_RWLOCK:
+    rwlock_class= find_rwlock_class(m_pos.m_index_2);
+    if (rwlock_class)
+    {
+      make_row(thread, rwlock_class);
+      return 0;
+    }
+    break;
+  case pos_ews_by_thread_by_event_name::VIEW_COND:
+    cond_class= find_cond_class(m_pos.m_index_2);
+    if (cond_class)
+    {
+      make_row(thread, cond_class);
+      return 0;
+    }
+    break;
+  case pos_ews_by_thread_by_event_name::VIEW_FILE:
+    file_class= find_file_class(m_pos.m_index_2);
+    if (file_class)
+    {
+      make_row(thread, file_class);
+      return 0;
+    }
+    break;
+  case pos_ews_by_thread_by_event_name::VIEW_TABLE:
+    table_class= find_table_class(m_pos.m_index_2);
+    if (table_class)
+    {
+      make_row(thread, table_class);
+      return 0;
+    }
+    break;
+  }
+
+  return HA_ERR_RECORD_DELETED;
+}
+
+void table_ews_by_thread_by_event_name
+::make_row(PFS_thread *thread, PFS_instr_class *klass)
+{
+  pfs_lock lock;
+  PFS_single_stat *event_name_array;
+  PFS_single_stat *stat;
+  uint index= klass->m_event_name_index;
+  event_name_array= thread->m_instr_class_wait_stats;
+
+  m_row_exists= false;
+
+  /* Protect this reader against a thread termination */
+  thread->m_lock.begin_optimistic_lock(&lock);
+
+  m_row.m_thread_internal_id= thread->m_thread_internal_id;
+  m_row.m_name= klass->m_name;
+  m_row.m_name_length= klass->m_name_length;
+
+  stat= & event_name_array[index];
+  time_normalizer *normalizer= time_normalizer::get(wait_timer);
+  m_row.m_stat.set(normalizer, stat);
+
+  if (thread->m_lock.end_optimistic_lock(&lock))
+    m_row_exists= true;
+}
+
+int table_ews_by_thread_by_event_name
+::read_row_values(TABLE *table, unsigned char *, Field **fields,
+                  bool read_all)
+{
+  Field *f;
+
+  if (unlikely(! m_row_exists))
+    return HA_ERR_RECORD_DELETED;
+
+  /* Set the null bits */
+  DBUG_ASSERT(table->s->null_bytes == 0);
+
+  for (; (f= *fields) ; fields++)
+  {
+    if (read_all || bitmap_is_set(table->read_set, f->field_index))
+    {
+      switch(f->field_index)
+      {
+      case 0: /* THREAD_ID */
+        set_field_ulong(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: /* COUNT */
+        set_field_ulonglong(f, m_row.m_stat.m_count);
+        break;
+      case 3: /* SUM */
+        set_field_ulonglong(f, m_row.m_stat.m_sum);
+        break;
+      case 4: /* MIN */
+        set_field_ulonglong(f, m_row.m_stat.m_min);
+        break;
+      case 5: /* AVG */
+        set_field_ulonglong(f, m_row.m_stat.m_avg);
+        break;
+      case 6: /* MAX */
+        set_field_ulonglong(f, m_row.m_stat.m_max);
+        break;
+      default:
+        DBUG_ASSERT(false);
+      }
+    }
+  }
+
+  return 0;
+}
+

=== added file 'storage/perfschema/table_ews_by_thread_by_event_name.h'
--- a/storage/perfschema/table_ews_by_thread_by_event_name.h	1970-01-01 00:00:00 +0000
+++ b/storage/perfschema/table_ews_by_thread_by_event_name.h	2010-09-23 16:08:54 +0000
@@ -0,0 +1,142 @@
+/* Copyright (c) 2010, 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, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#ifndef TABLE_EWS_BY_THREAD_BY_EVENT_NAME_H
+#define TABLE_EWS_BY_THREAD_BY_EVENT_NAME_H
+
+/**
+  @file storage/perfschema/table_ews_by_thread_by_event_name.h
+  Table EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "pfs_instr_class.h"
+#include "pfs_instr.h"
+#include "table_helper.h"
+
+/**
+  @addtogroup Performance_schema_tables
+  @{
+*/
+
+/**
+  A row of table
+  PERFORMANCE_SCHEMA.EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME.
+*/
+struct row_ews_by_thread_by_event_name
+{
+  /** Column THREAD_ID. */
+  ulong m_thread_internal_id;
+  /** Column EVENT_NAME. */
+  const char *m_name;
+  /** Length in bytes of @c m_name. */
+  uint m_name_length;
+  /** Columns COUNT_STAR, SUM/MIN/AVG/MAX TIMER_WAIT. */
+  PFS_stat_row m_stat;
+};
+
+/**
+  Position of a cursor on
+  PERFORMANCE_SCHEMA.EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME.
+  Index 1 on instrument view
+  Index 2 on instrument class (1 based)
+  Index 3 on thread (0 based)
+*/
+struct pos_ews_by_thread_by_event_name
+: public PFS_triple_index, public PFS_instrument_view_constants
+{
+  pos_ews_by_thread_by_event_name()
+    : PFS_triple_index(FIRST_VIEW, 1, 0)
+  {}
+
+  inline void reset(void)
+  {
+    m_index_1= FIRST_VIEW;
+    m_index_2= 1;
+    m_index_3= 0;
+  }
+
+  inline bool has_more_view(void)
+  { return (m_index_1 <= LAST_VIEW); }
+
+  inline bool has_more_thread(void)
+  { return (m_index_3 < thread_max); }
+
+  inline void next_view(void)
+  {
+    m_index_1++;
+    m_index_2= 1;
+    m_index_3= 0;
+  }
+
+  inline void next_instrument(void)
+  {
+    m_index_2++;
+    m_index_3= 0;
+  }
+
+  inline void next_thread(void)
+  {
+    m_index_3++;
+  }
+};
+
+/** Table PERFORMANCE_SCHEMA.EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME. */
+class table_ews_by_thread_by_event_name : public PFS_engine_table
+{
+public:
+  /** Table share */
+  static PFS_engine_table_share m_share;
+  static PFS_engine_table* create();
+  static int delete_all_rows();
+
+  virtual int rnd_next();
+  virtual int rnd_pos(const void *pos);
+  virtual void reset_position(void);
+
+protected:
+  virtual int read_row_values(TABLE *table,
+                              unsigned char *buf,
+                              Field **fields,
+                              bool read_all);
+
+  table_ews_by_thread_by_event_name();
+
+public:
+  ~table_ews_by_thread_by_event_name()
+  {}
+
+protected:
+  void make_row(PFS_thread *thread, PFS_instr_class *klass);
+
+private:
+  /** Table share lock. */
+  static THR_LOCK m_table_lock;
+  /** Fields definition. */
+  static TABLE_FIELD_DEF m_field_def;
+
+  /** Current row. */
+  row_ews_by_thread_by_event_name m_row;
+  /** True is the current row exists. */
+  bool m_row_exists;
+  /** Current position. */
+  pos_ews_by_thread_by_event_name m_pos;
+  /** Next position. */
+  pos_ews_by_thread_by_event_name m_next_pos;
+};
+
+/** @} */
+#endif

=== modified file 'storage/perfschema/table_ews_global_by_event_name.cc'
--- a/storage/perfschema/table_ews_global_by_event_name.cc	2010-09-01 22:59:33 +0000
+++ b/storage/perfschema/table_ews_global_by_event_name.cc	2010-09-23 16:08:54 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 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
@@ -10,8 +10,8 @@
   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
 /**
   @file storage/perfschema/table_ews_global_by_event_name.cc
@@ -25,6 +25,8 @@
 #include "pfs_column_values.h"
 #include "table_ews_global_by_event_name.h"
 #include "pfs_global.h"
+#include "pfs_instr.h"
+#include "pfs_timer.h"
 
 THR_LOCK table_ews_global_by_event_name::m_table_lock;
 
@@ -71,51 +73,338 @@ table_ews_global_by_event_name::m_share=
 {
   { C_STRING_WITH_LEN("EVENTS_WAITS_SUMMARY_GLOBAL_BY_EVENT_NAME") },
   &pfs_truncatable_acl,
-  &table_ews_global_by_event_name::create,
+  table_ews_global_by_event_name::create,
   NULL, /* write_row */
-  &table_ews_global_by_event_name::delete_all_rows,
+  table_ews_global_by_event_name::delete_all_rows,
   NULL, /* get_row_count */
   1000, /* records */
-  sizeof(pos_all_instr_class),
+  sizeof(pos_ews_global_by_event_name),
   &m_table_lock,
   &m_field_def,
   false /* checked */
 };
 
-PFS_engine_table* table_ews_global_by_event_name::create(void)
+PFS_engine_table*
+table_ews_global_by_event_name::create(void)
 {
   return new table_ews_global_by_event_name();
 }
 
-int table_ews_global_by_event_name::delete_all_rows(void)
+int
+table_ews_global_by_event_name::delete_all_rows(void)
 {
-  reset_instrument_class_waits();
+  reset_events_waits_by_instance();
+  /* FIXME: table io */
+  reset_global_wait_stat();
   return 0;
 }
 
-table_ews_global_by_event_name
-::table_ews_global_by_event_name()
-  : table_all_instr_class(&m_share)
+table_ews_global_by_event_name::table_ews_global_by_event_name()
+  : PFS_engine_table(&m_share, &m_pos),
+    m_row_exists(false), m_pos(), m_next_pos()
 {}
 
+void table_ews_global_by_event_name::reset_position(void)
+{
+  m_pos.reset();
+  m_next_pos.reset();
+}
+
+int table_ews_global_by_event_name::rnd_next(void)
+{
+  PFS_mutex_class *mutex_class;
+  PFS_rwlock_class *rwlock_class;
+  PFS_cond_class *cond_class;
+  PFS_file_class *file_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())
+  {
+    switch (m_pos.m_index_1)
+    {
+    case pos_ews_global_by_event_name::VIEW_MUTEX:
+      mutex_class= find_mutex_class(m_pos.m_index_2);
+      if (mutex_class)
+      {
+        make_mutex_row(mutex_class);
+        m_next_pos.set_after(&m_pos);
+        return 0;
+      }
+      break;
+    case pos_ews_global_by_event_name::VIEW_RWLOCK:
+      rwlock_class= find_rwlock_class(m_pos.m_index_2);
+      if (rwlock_class)
+      {
+        make_rwlock_row(rwlock_class);
+        m_next_pos.set_after(&m_pos);
+        return 0;
+      }
+      break;
+    case pos_ews_global_by_event_name::VIEW_COND:
+      cond_class= find_cond_class(m_pos.m_index_2);
+      if (cond_class)
+      {
+        make_cond_row(cond_class);
+        m_next_pos.set_after(&m_pos);
+        return 0;
+      }
+      break;
+    case pos_ews_global_by_event_name::VIEW_FILE:
+      file_class= find_file_class(m_pos.m_index_2);
+      if (file_class)
+      {
+        make_file_row(file_class);
+        m_next_pos.set_after(&m_pos);
+        return 0;
+      }
+      break;
+    case pos_ews_global_by_event_name::VIEW_TABLE:
+      if (m_pos.m_index_2 == 1)
+      {
+        make_table_io_row(&global_table_io_class);
+        m_next_pos.set_after(&m_pos);
+        return 0;
+      }
+      break;
+    default:
+      break;
+    }
+  }
+
+  return HA_ERR_END_OF_FILE;
+}
+
+int
+table_ews_global_by_event_name::rnd_pos(const void *pos)
+{
+  PFS_mutex_class *mutex_class;
+  PFS_rwlock_class *rwlock_class;
+  PFS_cond_class *cond_class;
+  PFS_file_class *file_class;
+
+  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:
+    mutex_class= find_mutex_class(m_pos.m_index_2);
+    if (mutex_class)
+    {
+      make_mutex_row(mutex_class);
+      return 0;
+    }
+    break;
+  case pos_ews_global_by_event_name::VIEW_RWLOCK:
+    rwlock_class= find_rwlock_class(m_pos.m_index_2);
+    if (rwlock_class)
+    {
+      make_rwlock_row(rwlock_class);
+      return 0;
+    }
+    break;
+  case pos_ews_global_by_event_name::VIEW_COND:
+    cond_class= find_cond_class(m_pos.m_index_2);
+    if (cond_class)
+    {
+      make_cond_row(cond_class);
+      return 0;
+    }
+    break;
+  case pos_ews_global_by_event_name::VIEW_FILE:
+    file_class= find_file_class(m_pos.m_index_2);
+    if (file_class)
+    {
+      make_file_row(file_class);
+      return 0;
+    }
+    break;
+  case pos_ews_global_by_event_name::VIEW_TABLE:
+    DBUG_ASSERT(m_pos.m_index_2 == 1);
+    make_table_io_row(&global_table_io_class);
+    break;
+  }
+
+  return HA_ERR_RECORD_DELETED;
+}
+
+
+void table_ews_global_by_event_name
+::make_mutex_row(PFS_mutex_class *klass)
+{
+  m_row.m_name= klass->m_name;
+  m_row.m_name_length= klass->m_name_length;
+  uint index= klass->m_event_name_index;
+  PFS_single_stat cumulated_stat= global_instr_class_waits_array[index];
+
+  /* FIXME: improve singletons */
+  /* For all the mutex instances ... */
+  PFS_mutex *pfs= mutex_array;
+  PFS_mutex *pfs_last= mutex_array + mutex_max;
+  for ( ; pfs < pfs_last; pfs++)
+  {
+    if ((pfs->m_class == klass) && pfs->m_lock.is_populated())
+    {
+      /*
+        If the instance belongs to this class,
+        aggregate the instance statistics.
+      */
+      cumulated_stat.aggregate(& pfs->m_wait_stat);
+    }
+  }
+
+  time_normalizer *normalizer= time_normalizer::get(wait_timer);
+  m_row.m_stat.set(normalizer, &cumulated_stat);
+  m_row_exists= true;
+}
+
+void table_ews_global_by_event_name
+::make_rwlock_row(PFS_rwlock_class *klass)
+{
+  m_row.m_name= klass->m_name;
+  m_row.m_name_length= klass->m_name_length;
+  uint index= klass->m_event_name_index;
+  PFS_single_stat cumulated_stat= global_instr_class_waits_array[index];
+
+  /* FIXME: improve singletons */
+  /* For all the rwlock instances ... */
+  PFS_rwlock *pfs= rwlock_array;
+  PFS_rwlock *pfs_last= rwlock_array + rwlock_max;
+  for ( ; pfs < pfs_last; pfs++)
+  {
+    if ((pfs->m_class == klass) && pfs->m_lock.is_populated())
+    {
+      /*
+        If the instance belongs to this class,
+        aggregate the instance statistics.
+      */
+      cumulated_stat.aggregate(& pfs->m_wait_stat);
+    }
+  }
+
+  time_normalizer *normalizer= time_normalizer::get(wait_timer);
+  m_row.m_stat.set(normalizer, &cumulated_stat);
+  m_row_exists= true;
+}
+
+void table_ews_global_by_event_name
+::make_cond_row(PFS_cond_class *klass)
+{
+  m_row.m_name= klass->m_name;
+  m_row.m_name_length= klass->m_name_length;
+  uint index= klass->m_event_name_index;
+  PFS_single_stat cumulated_stat= global_instr_class_waits_array[index];
+
+  /* FIXME: improve singletons */
+  /* For all the cond instances ... */
+  PFS_cond *pfs= cond_array;
+  PFS_cond *pfs_last= cond_array + cond_max;
+  for ( ; pfs < pfs_last; pfs++)
+  {
+    if ((pfs->m_class == klass) && pfs->m_lock.is_populated())
+    {
+      /*
+        If the instance belongs to this class,
+        aggregate the instance statistics.
+      */
+      cumulated_stat.aggregate(& pfs->m_wait_stat);
+    }
+  }
+
+  time_normalizer *normalizer= time_normalizer::get(wait_timer);
+  m_row.m_stat.set(normalizer, &cumulated_stat);
+  m_row_exists= true;
+}
+
+void table_ews_global_by_event_name
+::make_file_row(PFS_file_class *klass)
+{
+  m_row.m_name= klass->m_name;
+  m_row.m_name_length= klass->m_name_length;
+  uint index= klass->m_event_name_index;
+  PFS_single_stat cumulated_stat= global_instr_class_waits_array[index];
+
+  /* FIXME: improve singletons */
+  /* For all the file instances ... */
+  PFS_file *pfs= file_array;
+  PFS_file *pfs_last= file_array + file_max;
+  for ( ; pfs < pfs_last; pfs++)
+  {
+    if ((pfs->m_class == klass) && pfs->m_lock.is_populated())
+    {
+      /*
+        If the instance belongs to this class,
+        aggregate the instance statistics.
+      */
+      cumulated_stat.aggregate(& pfs->m_wait_stat);
+    }
+  }
+
+  /* FIXME: */
+  /* For all the file handles ... */
+
+  time_normalizer *normalizer= time_normalizer::get(wait_timer);
+  m_row.m_stat.set(normalizer, &cumulated_stat);
+  m_row_exists= true;
+}
+
 void table_ews_global_by_event_name
-::make_instr_row(PFS_instr_class *klass)
+::make_table_io_row(PFS_instr_class *klass)
 {
   m_row.m_name= klass->m_name;
   m_row.m_name_length= klass->m_name_length;
+  uint index= klass->m_event_name_index;
+  PFS_single_stat cumulated_stat= global_instr_class_waits_array[index];
+  PFS_table_io_stat cumulated_io_stat;
+
+  /* For all the table shares ... */
+  PFS_table_share *share= table_share_array;
+  PFS_table_share *share_last= table_share_array + table_share_max;
+  for ( ; share < share_last; share++)
+  {
+    if (share->m_lock.is_populated())
+    {
+      /* Aggregate index stats */
+      for (index= 0; index <= share->m_key_count; index++)
+        cumulated_io_stat.aggregate(& share->m_table_stat.m_index_stat[index]);
+
+      /** Aggregate global stats */
+      cumulated_io_stat.aggregate(& share->m_table_stat.m_index_stat[MAX_KEY]);
+    }
+  }
 
-  m_row.m_count= klass->m_wait_stat.m_count;
-  m_row.m_sum= klass->m_wait_stat.m_sum;
-  m_row.m_min= klass->m_wait_stat.m_min;
-  m_row.m_max= klass->m_wait_stat.m_max;
-
-  if (m_row.m_count)
-    m_row.m_avg= m_row.m_sum / m_row.m_count;
-  else
+  /* For all the table handles ... */
+  PFS_table *table= table_array;
+  PFS_table *table_last= table_array + table_max;
+  for ( ; table < table_last; table++)
   {
-    m_row.m_min= 0;
-    m_row.m_avg= 0;
+    if (table->m_lock.is_populated())
+    {
+      PFS_table_share *safe_share= sanitize_table_share(table->m_share);
+
+      if (likely(safe_share != NULL))
+      {
+        /* Aggregate index stats */
+        for (index= 0; index <= safe_share->m_key_count; index++)
+          cumulated_io_stat.aggregate(& table->m_table_stat.m_index_stat[index]);
+
+        /** Aggregate global stats */
+        cumulated_io_stat.aggregate(& table->m_table_stat.m_index_stat[MAX_KEY]);
+      }
+    }
   }
+
+  cumulated_io_stat.sum(& cumulated_stat);
+
+  time_normalizer *normalizer= time_normalizer::get(wait_timer);
+  m_row.m_stat.set(normalizer, &cumulated_stat);
+  m_row_exists= true;
 }
 
 int table_ews_global_by_event_name
@@ -124,14 +413,12 @@ int table_ews_global_by_event_name
 {
   Field *f;
 
+  if (unlikely(! m_row_exists))
+    return HA_ERR_RECORD_DELETED;
+
   /* Set the null bits */
   DBUG_ASSERT(table->s->null_bytes == 0);
 
-  /*
-    The row always exist,
-    the instrument classes are static and never disappear.
-  */
-
   for (; (f= *fields) ; fields++)
   {
     if (read_all || bitmap_is_set(table->read_set, f->field_index))
@@ -142,19 +429,19 @@ int table_ews_global_by_event_name
         set_field_varchar_utf8(f, m_row.m_name, m_row.m_name_length);
         break;
       case 1: /* COUNT */
-        set_field_ulonglong(f, m_row.m_count);
+        set_field_ulonglong(f, m_row.m_stat.m_count);
         break;
       case 2: /* SUM */
-        set_field_ulonglong(f, m_row.m_sum);
+        set_field_ulonglong(f, m_row.m_stat.m_sum);
         break;
       case 3: /* MIN */
-        set_field_ulonglong(f, m_row.m_min);
+        set_field_ulonglong(f, m_row.m_stat.m_min);
         break;
       case 4: /* AVG */
-        set_field_ulonglong(f, m_row.m_avg);
+        set_field_ulonglong(f, m_row.m_stat.m_avg);
         break;
       case 5: /* MAX */
-        set_field_ulonglong(f, m_row.m_max);
+        set_field_ulonglong(f, m_row.m_stat.m_max);
         break;
       default:
         DBUG_ASSERT(false);

=== modified file 'storage/perfschema/table_ews_global_by_event_name.h'
--- a/storage/perfschema/table_ews_global_by_event_name.h	2010-08-12 14:08:52 +0000
+++ b/storage/perfschema/table_ews_global_by_event_name.h	2010-09-23 16:08:54 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 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
@@ -10,11 +10,11 @@
   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
-#ifndef TABLE_EVENTS_WAITS_SUMMARY_GLOBAL_BY_EVENT_NAME_H
-#define TABLE_EVENTS_WAITS_SUMMARY_GLOBAL_BY_EVENT_NAME_H
+#ifndef TABLE_EWS_GLOBAL_BY_EVENT_NAME_H
+#define TABLE_EWS_GLOBAL_BY_EVENT_NAME_H
 
 /**
   @file storage/perfschema/table_ews_global_by_event_name.h
@@ -25,34 +25,63 @@
 #include "pfs_engine_table.h"
 #include "pfs_instr_class.h"
 #include "pfs_instr.h"
-#include "table_all_instr.h"
+#include "table_helper.h"
 
 /**
   @addtogroup Performance_schema_tables
   @{
 */
 
-/** A row of PERFORMANCE_SCHEMA.EVENTS_WAITS_SUMMARY_GLOBAL_BY_EVENT_NAME. */
+/**
+  A row of table
+  PERFORMANCE_SCHEMA.EVENTS_WAITS_SUMMARY_GLOBAL_BY_EVENT_NAME.
+*/
 struct row_ews_global_by_event_name
 {
   /** Column EVENT_NAME. */
   const char *m_name;
   /** Length in bytes of @c m_name. */
   uint m_name_length;
-  /** Column COUNT_STAR. */
-  ulonglong m_count;
-  /** Column SUM_TIMER_WAIT. */
-  ulonglong m_sum;
-  /** Column MIN_TIMER_WAIT. */
-  ulonglong m_min;
-  /** Column AVG_TIMER_WAIT. */
-  ulonglong m_avg;
-  /** Column MAX_TIMER_WAIT. */
-  ulonglong m_max;
+  /** Columns COUNT_STAR, SUM/MIN/AVG/MAX TIMER_WAIT. */
+  PFS_stat_row m_stat;
+};
+
+/**
+  Position of a cursor on
+  PERFORMANCE_SCHEMA.EVENTS_WAITS_SUMMARY_GLOBAL_BY_EVENT_NAME.
+  Index 1 on instrument view
+  Index 2 on instrument class (1 based)
+*/
+struct pos_ews_global_by_event_name
+: public PFS_double_index, public PFS_instrument_view_constants
+{
+  pos_ews_global_by_event_name()
+    : PFS_double_index(FIRST_VIEW, 1)
+  {}
+
+  inline void reset(void)
+  {
+    m_index_1= FIRST_VIEW;
+    m_index_2= 1;
+  }
+
+  inline bool has_more_view(void)
+  { return (m_index_1 <= LAST_VIEW); }
+
+  inline void next_view(void)
+  {
+    m_index_1++;
+    m_index_2= 1;
+  }
+
+  inline void next_instrument(void)
+  {
+    m_index_2++;
+  }
 };
 
 /** Table PERFORMANCE_SCHEMA.EVENTS_WAITS_SUMMARY_GLOBAL_BY_EVENT_NAME. */
-class table_ews_global_by_event_name : public table_all_instr_class
+class table_ews_global_by_event_name : public PFS_engine_table
 {
 public:
   /** Table share */
@@ -60,9 +89,11 @@ public:
   static PFS_engine_table* create();
   static int delete_all_rows();
 
-protected:
-  virtual void make_instr_row(PFS_instr_class *klass);
+  virtual int rnd_next();
+  virtual int rnd_pos(const void *pos);
+  virtual void reset_position(void);
 
+protected:
   virtual int read_row_values(TABLE *table,
                               unsigned char *buf,
                               Field **fields,
@@ -74,6 +105,13 @@ public:
   ~table_ews_global_by_event_name()
   {}
 
+protected:
+  void make_mutex_row(PFS_mutex_class *klass);
+  void make_rwlock_row(PFS_rwlock_class *klass);
+  void make_cond_row(PFS_cond_class *klass);
+  void make_file_row(PFS_file_class *klass);
+  void make_table_io_row(PFS_instr_class *klass);
+
 private:
   /** Table share lock. */
   static THR_LOCK m_table_lock;
@@ -82,6 +120,12 @@ private:
 
   /** Current row. */
   row_ews_global_by_event_name m_row;
+  /** True is the current row exists. */
+  bool m_row_exists;
+  /** Current position. */
+  pos_ews_global_by_event_name m_pos;
+  /** Next position. */
+  pos_ews_global_by_event_name m_next_pos;
 };
 
 /** @} */

=== modified file 'storage/perfschema/table_file_summary.cc'
--- a/storage/perfschema/table_file_summary.cc	2010-07-23 19:03:52 +0000
+++ b/storage/perfschema/table_file_summary.cc	2010-09-23 16:08:54 +0000
@@ -84,6 +84,7 @@ PFS_engine_table* table_file_summary_by_
 
 int table_file_summary_by_event_name::delete_all_rows(void)
 {
+  reset_file_instance_io();
   reset_file_class_io();
   return 0;
 }
@@ -140,7 +141,22 @@ void table_file_summary_by_event_name::m
 {
   m_row.m_name= &klass->m_name[0];
   m_row.m_name_length= klass->m_name_length;
-  m_row.m_file_stat= klass->m_file_stat;
+  m_row.m_file_io_stat= klass->m_file_stat.m_io_stat;
+
+  /* For all file instances ... */
+  PFS_file *pfs= file_array;
+  PFS_file *pfs_last= file_array + file_max;
+  for ( ; pfs < pfs_last; pfs++)
+  {
+    if ((pfs->m_class == klass) && pfs->m_lock.is_populated())
+    {
+      /*
+        If the instance belongs to this class,
+        aggregate the instance statistics.
+      */
+      m_row.m_file_io_stat.aggregate(& pfs->m_file_stat.m_io_stat);
+    }
+  }
 }
 
 int table_file_summary_by_event_name::read_row_values(TABLE *table,
@@ -165,16 +181,16 @@ int table_file_summary_by_event_name::re
         set_field_varchar_utf8(f, m_row.m_name, m_row.m_name_length);
         break;
       case 1: /* COUNT_READ */
-        set_field_ulonglong(f, m_row.m_file_stat.m_count_read);
+        set_field_ulonglong(f, m_row.m_file_io_stat.m_count_read);
         break;
       case 2: /* COUNT_WRITE */
-        set_field_ulonglong(f, m_row.m_file_stat.m_count_write);
+        set_field_ulonglong(f, m_row.m_file_io_stat.m_count_write);
         break;
       case 3: /* READ_BYTES */
-        set_field_ulonglong(f, m_row.m_file_stat.m_read_bytes);
+        set_field_ulonglong(f, m_row.m_file_io_stat.m_read_bytes);
         break;
       case 4: /* WRITE_BYTES */
-        set_field_ulonglong(f, m_row.m_file_stat.m_write_bytes);
+        set_field_ulonglong(f, m_row.m_file_io_stat.m_write_bytes);
         break;
       default:
         DBUG_ASSERT(false);
@@ -320,7 +336,7 @@ void table_file_summary_by_instance::mak
   m_row.m_filename_length= pfs->m_filename_length;
   m_row.m_name= safe_class->m_name;
   m_row.m_name_length= safe_class->m_name_length;
-  m_row.m_file_stat= pfs->m_file_stat;
+  m_row.m_file_io_stat= pfs->m_file_stat.m_io_stat;
 
   if (pfs->m_lock.end_optimistic_lock(&lock))
     m_row_exists= true;
@@ -352,16 +368,16 @@ int table_file_summary_by_instance::read
         set_field_varchar_utf8(f, m_row.m_name, m_row.m_name_length);
         break;
       case 2: /* COUNT_READ */
-        set_field_ulonglong(f, m_row.m_file_stat.m_count_read);
+        set_field_ulonglong(f, m_row.m_file_io_stat.m_count_read);
         break;
       case 3: /* COUNT_WRITE */
-        set_field_ulonglong(f, m_row.m_file_stat.m_count_write);
+        set_field_ulonglong(f, m_row.m_file_io_stat.m_count_write);
         break;
       case 4: /* READ_BYTES */
-        set_field_ulonglong(f, m_row.m_file_stat.m_read_bytes);
+        set_field_ulonglong(f, m_row.m_file_io_stat.m_read_bytes);
         break;
       case 5: /* WRITE_BYTES */
-        set_field_ulonglong(f, m_row.m_file_stat.m_write_bytes);
+        set_field_ulonglong(f, m_row.m_file_io_stat.m_write_bytes);
         break;
       default:
         DBUG_ASSERT(false);

=== modified file 'storage/perfschema/table_file_summary.h'
--- a/storage/perfschema/table_file_summary.h	2010-07-23 19:03:52 +0000
+++ b/storage/perfschema/table_file_summary.h	2010-09-23 16:08:54 +0000
@@ -42,7 +42,7 @@ struct row_file_summary_by_event_name
     Columns COUNT_READ, COUNT_WRITE,
     SUM_NUMBER_OF_BYTES_READ, SUM_NUMBER_OF_BYTES_WRITE.
   */
-  PFS_file_stat m_file_stat;
+  PFS_file_io_stat m_file_io_stat;
 };
 
 /** Table PERFORMANCE_SCHEMA.FILE_SUMMARY_BY_EVENT_NAME. */
@@ -101,7 +101,7 @@ struct row_file_summary_by_instance
     Columns COUNT_READ, COUNT_WRITE,
     SUM_NUMBER_OF_BYTES_READ, SUM_NUMBER_OF_BYTES_WRITE.
   */
-  PFS_file_stat m_file_stat;
+  PFS_file_io_stat m_file_io_stat;
 };
 
 /** Table PERFORMANCE_SCHEMA.FILE_UMMARY_BY_INSTANCE. */

=== modified file 'storage/perfschema/table_helper.h'
--- a/storage/perfschema/table_helper.h	2010-07-02 17:25:26 +0000
+++ b/storage/perfschema/table_helper.h	2010-09-23 16:08:54 +0000
@@ -10,12 +10,16 @@
   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
 #ifndef PFS_TABLE_HELPER_H
 #define PFS_TABLE_HELPER_H
 
+#include "pfs_column_types.h"
+#include "pfs_stat.h"
+#include "pfs_timer.h"
+
 /**
   @file storage/perfschema/table_helper.h
   Performance schema table helpers (declarations).
@@ -49,6 +53,80 @@ struct PFS_object_view_constants
   static const uint VIEW_FUNCTION= 4;
 };
 
+struct PFS_stat_row
+{
+  /** Column COUNT_STAR. */
+  ulonglong m_count;
+  /** Column SUM_TIMER_WAIT. */
+  ulonglong m_sum;
+  /** Column MIN_TIMER_WAIT. */
+  ulonglong m_min;
+  /** Column AVG_TIMER_WAIT. */
+  ulonglong m_avg;
+  /** Column MAX_TIMER_WAIT. */
+  ulonglong m_max;
+
+  inline void set(time_normalizer *normalizer, const PFS_single_stat *stat)
+  {
+    m_count= stat->m_count;
+
+    if (m_count)
+    {
+      m_sum= normalizer->wait_to_pico(stat->m_sum);
+      m_min= normalizer->wait_to_pico(stat->m_min);
+      m_max= normalizer->wait_to_pico(stat->m_max);
+      m_avg= normalizer->wait_to_pico(stat->m_sum / stat->m_count);
+    }
+    else
+    {
+      m_sum= 0;
+      m_min= 0;
+      m_avg= 0;
+      m_max= 0;
+    }
+  }
+};
+
+struct PFS_table_io_stat_row
+{
+  PFS_stat_row m_all;
+  PFS_stat_row m_all_read;
+  PFS_stat_row m_all_write;
+  PFS_stat_row m_fetch;
+  PFS_stat_row m_insert;
+  PFS_stat_row m_update;
+  PFS_stat_row m_delete;
+
+  inline void set(time_normalizer *normalizer, const PFS_table_io_stat *stat)
+  {
+    PFS_single_stat all_read;
+    PFS_single_stat all_write;
+    PFS_single_stat all;
+
+    m_fetch.set(normalizer, & stat->m_fetch);
+
+    all_read.aggregate(& stat->m_fetch);
+
+    m_insert.set(normalizer, & stat->m_insert);
+    m_update.set(normalizer, & stat->m_update);
+    m_delete.set(normalizer, & stat->m_delete);
+
+    all_write.aggregate(& stat->m_insert);
+    all_write.aggregate(& stat->m_update);
+    all_write.aggregate(& stat->m_delete);
+
+    all.aggregate(& all_read);
+    all.aggregate(& all_write);
+
+    m_all_read.set(normalizer, & all_read);
+    m_all_write.set(normalizer, & all_write);
+    m_all.set(normalizer, & all);
+  }
+};
+
+int object_type_to_enum(String *in, enum_object_type *out);
+void set_field_object_type(Field *f, enum_object_type object_type);
+
 /** @} */
 
 #endif

=== added file 'storage/perfschema/table_os_global_by_type.cc'
--- a/storage/perfschema/table_os_global_by_type.cc	1970-01-01 00:00:00 +0000
+++ b/storage/perfschema/table_os_global_by_type.cc	2010-09-23 16:08:54 +0000
@@ -0,0 +1,269 @@
+/* Copyright (c) 2010, 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, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+/**
+  @file storage/perfschema/table_os_global_by_type.cc
+  Table OBJECTS_SUMMARY_GLOBAL_BY_TYPE (implementation).
+*/
+
+#include "my_global.h"
+#include "my_pthread.h"
+#include "pfs_instr_class.h"
+#include "pfs_column_types.h"
+#include "pfs_column_values.h"
+#include "table_os_global_by_type.h"
+#include "pfs_global.h"
+
+THR_LOCK table_os_global_by_type::m_table_lock;
+
+static const TABLE_FIELD_TYPE field_types[]=
+{
+  {
+    { C_STRING_WITH_LEN("OBJECT_TYPE") },
+    { C_STRING_WITH_LEN("varchar(64)") },
+    { NULL, 0}
+  },
+  {
+    { C_STRING_WITH_LEN("OBJECT_SCHEMA") },
+    { C_STRING_WITH_LEN("varchar(64)") },
+    { NULL, 0}
+  },
+  {
+    { C_STRING_WITH_LEN("OBJECT_NAME") },
+    { C_STRING_WITH_LEN("varchar(64)") },
+    { NULL, 0}
+  },
+  {
+    { C_STRING_WITH_LEN("COUNT_STAR") },
+    { C_STRING_WITH_LEN("bigint(20)") },
+    { NULL, 0}
+  },
+  {
+    { C_STRING_WITH_LEN("SUM_TIMER_WAIT") },
+    { C_STRING_WITH_LEN("bigint(20)") },
+    { NULL, 0}
+  },
+  {
+    { C_STRING_WITH_LEN("MIN_TIMER_WAIT") },
+    { C_STRING_WITH_LEN("bigint(20)") },
+    { NULL, 0}
+  },
+  {
+    { C_STRING_WITH_LEN("AVG_TIMER_WAIT") },
+    { C_STRING_WITH_LEN("bigint(20)") },
+    { NULL, 0}
+  },
+  {
+    { C_STRING_WITH_LEN("MAX_TIMER_WAIT") },
+    { C_STRING_WITH_LEN("bigint(20)") },
+    { NULL, 0}
+  }
+};
+
+TABLE_FIELD_DEF
+table_os_global_by_type::m_field_def=
+{ 8, field_types };
+
+PFS_engine_table_share
+table_os_global_by_type::m_share=
+{
+  { C_STRING_WITH_LEN("OBJECTS_SUMMARY_GLOBAL_BY_TYPE") },
+  &pfs_truncatable_acl,
+  table_os_global_by_type::create,
+  NULL, /* write_row */
+  table_os_global_by_type::delete_all_rows,
+  NULL, /* get_row_count */
+  1000, /* records */
+  sizeof(pos_os_global_by_type),
+  &m_table_lock,
+  &m_field_def,
+  false /* checked */
+};
+
+PFS_engine_table*
+table_os_global_by_type::create(void)
+{
+  return new table_os_global_by_type();
+}
+
+int
+table_os_global_by_type::delete_all_rows(void)
+{
+  reset_per_thread_wait_stat();
+  return 0;
+}
+
+table_os_global_by_type::table_os_global_by_type()
+  : PFS_engine_table(&m_share, &m_pos),
+    m_row_exists(false), m_pos(), m_next_pos()
+{}
+
+void table_os_global_by_type::reset_position(void)
+{
+  m_pos.reset();
+  m_next_pos.reset();
+}
+
+int table_os_global_by_type::rnd_next(void)
+{
+  PFS_table_share *table_share;
+
+  for (m_pos.set_at(&m_next_pos);
+       m_pos.has_more_view();
+       m_pos.next_view())
+  {
+    switch (m_pos.m_index_1) {
+    case pos_os_global_by_type::VIEW_TABLE:
+      for ( ; m_pos.m_index_2 < table_share_max; m_pos.m_index_2++)
+      {
+        table_share= &table_share_array[m_pos.m_index_2];
+        if (table_share->m_lock.is_populated())
+        {
+          make_row(table_share);
+          m_next_pos.set_after(&m_pos);
+          return 0;
+        }
+      }
+      break;
+    default:
+      break;
+    }
+  }
+
+  return HA_ERR_END_OF_FILE;
+}
+
+int
+table_os_global_by_type::rnd_pos(const void *pos)
+{
+  PFS_table_share *table_share;
+
+  set_position(pos);
+
+  switch (m_pos.m_index_1) {
+  case pos_os_global_by_type::VIEW_TABLE:
+    DBUG_ASSERT(m_pos.m_index_2 < table_share_max);
+    table_share= &table_share_array[m_pos.m_index_2];
+    if (table_share->m_lock.is_populated())
+    {
+      make_row(table_share);
+      return 0;
+    }
+    break;
+  default:
+    break;
+  }
+
+  return HA_ERR_RECORD_DELETED;
+}
+
+void table_os_global_by_type::make_row(PFS_table_share *share)
+{
+  pfs_lock lock;
+  PFS_single_stat cumulated_stat;
+
+  m_row_exists= false;
+
+  share->m_lock.begin_optimistic_lock(&lock);
+
+  m_row.m_object_type= share->get_object_type();
+  memcpy(m_row.m_schema_name, share->m_schema_name, share->m_schema_name_length);
+  m_row.m_schema_name_length= share->m_schema_name_length;
+  memcpy(m_row.m_object_name, share->m_table_name, share->m_table_name_length);
+  m_row.m_object_name_length= share->m_table_name_length;
+  share->m_table_stat.sum(& cumulated_stat);
+
+  if (! share->m_lock.end_optimistic_lock(&lock))
+    return;
+
+  m_row_exists= true;
+
+  if (share->m_refcount > 0)
+  {
+    /* For all the table handles still opened ... */
+    PFS_table *table= table_array;
+    PFS_table *table_last= table_array + table_max;
+    for ( ; table < table_last ; table++)
+    {
+      if ((table->m_share == share) && (table->m_lock.is_populated()))
+      {
+        /*
+          If the opened table handle is for this table share,
+          aggregate the table handle statistics.
+        */
+        table->m_table_stat.sum(& cumulated_stat);
+      }
+    }
+  }
+
+  time_normalizer *normalizer= time_normalizer::get(wait_timer);
+  m_row.m_stat.set(normalizer, &cumulated_stat);
+}
+
+int table_os_global_by_type::read_row_values(TABLE *table,
+                                             unsigned char *buf,
+                                             Field **fields,
+                                             bool read_all)
+{
+  Field *f;
+
+  if (unlikely(! m_row_exists))
+    return HA_ERR_RECORD_DELETED;
+
+  /* Set the null bits */
+  DBUG_ASSERT(table->s->null_bytes == 1);
+  buf[0]= 0;
+
+  for (; (f= *fields) ; fields++)
+  {
+    if (read_all || bitmap_is_set(table->read_set, f->field_index))
+    {
+      switch(f->field_index)
+      {
+      case 0: /* OBJECT_TYPE */
+        set_field_object_type(f, m_row.m_object_type);
+        break;
+      case 1: /* SCHEMA_NAME */
+        set_field_varchar_utf8(f, m_row.m_schema_name,
+                               m_row.m_schema_name_length);
+        break;
+      case 2: /* OBJECT_NAME */
+        set_field_varchar_utf8(f, m_row.m_object_name,
+                               m_row.m_object_name_length);
+        break;
+      case 3: /* COUNT */
+        set_field_ulonglong(f, m_row.m_stat.m_count);
+        break;
+      case 4: /* SUM */
+        set_field_ulonglong(f, m_row.m_stat.m_sum);
+        break;
+      case 5: /* MIN */
+        set_field_ulonglong(f, m_row.m_stat.m_min);
+        break;
+      case 6: /* AVG */
+        set_field_ulonglong(f, m_row.m_stat.m_avg);
+        break;
+      case 7: /* MAX */
+        set_field_ulonglong(f, m_row.m_stat.m_max);
+        break;
+      default:
+        DBUG_ASSERT(false);
+      }
+    }
+  }
+
+  return 0;
+}
+

=== added file 'storage/perfschema/table_os_global_by_type.h'
--- a/storage/perfschema/table_os_global_by_type.h	1970-01-01 00:00:00 +0000
+++ b/storage/perfschema/table_os_global_by_type.h	2010-09-23 16:08:54 +0000
@@ -0,0 +1,130 @@
+/* Copyright (c) 2010, 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, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#ifndef TABLE_OBJECTS_SUMMARY_GLOBAL_BY_TYPE_H
+#define TABLE_OBJECTS_SUMMARY_GLOBAL_BY_TYPE_H
+
+/**
+  @file storage/perfschema/table_os_global_by_type.h
+  Table OBJECTS_SUMMARY_GLOBAL_BY_TYPE (declarations).
+*/
+
+#include "pfs_column_types.h"
+#include "pfs_engine_table.h"
+#include "pfs_instr_class.h"
+#include "pfs_instr.h"
+#include "table_helper.h"
+
+/**
+  @addtogroup Performance_schema_tables
+  @{
+*/
+
+/**
+  A row of table
+  PERFORMANCE_SCHEMA.OBJECTS_SUMMARY_GLOBAL_BY_TYPE.
+*/
+struct row_os_global_by_type
+{
+  /** Column OBJECT_TYPE. */
+  enum_object_type m_object_type;
+  /** Column SCHEMA_NAME. */
+  char m_schema_name[NAME_LEN];
+  /** Length in bytes of @c m_schema_name. */
+  uint m_schema_name_length;
+  /** Column OBJECT_NAME. */
+  char m_object_name[NAME_LEN];
+  /** Length in bytes of @c m_object_name. */
+  uint m_object_name_length;
+  /** Columns COUNT_STAR, SUM/MIN/AVG/MAX TIMER_WAIT. */
+  PFS_stat_row m_stat;
+};
+
+/**
+  Position of a cursor on
+  PERFORMANCE_SCHEMA.OBJECTS_SUMMARY_GLOBAL_BY_TYPE.
+  Index 1 on object type
+  Index 2 on object instance (0 based)
+*/
+struct pos_os_global_by_type : public PFS_double_index,
+                               public PFS_object_view_constants
+{
+  pos_os_global_by_type()
+    : PFS_double_index(FIRST_VIEW, 0)
+  {}
+
+  inline void reset(void)
+  {
+    m_index_1= FIRST_VIEW;
+    m_index_2= 0;
+  }
+
+  inline bool has_more_view(void)
+  { return (m_index_1 <= LAST_VIEW); }
+
+  inline void next_view(void)
+  {
+    m_index_1++;
+    m_index_2= 0;
+  }
+};
+
+/** Table PERFORMANCE_SCHEMA.OBJECTS_SUMMARY_GLOBAL_BY_TYPE. */
+class table_os_global_by_type : public PFS_engine_table
+{
+public:
+  /** Table share */
+  static PFS_engine_table_share m_share;
+  static PFS_engine_table* create();
+  static int delete_all_rows();
+
+  virtual int rnd_next();
+  virtual int rnd_pos(const void *pos);
+  virtual void reset_position(void);
+
+protected:
+  virtual int read_row_values(TABLE *table,
+                              unsigned char *buf,
+                              Field **fields,
+                              bool read_all);
+
+  table_os_global_by_type();
+
+public:
+  ~table_os_global_by_type()
+  {}
+
+protected:
+  void make_row(PFS_table_share *table_share);
+
+private:
+  /** Table share lock. */
+  static THR_LOCK m_table_lock;
+  /** Fields definition. */
+  static TABLE_FIELD_DEF m_field_def;
+
+  /** Current row. */
+  row_os_global_by_type m_row;
+  /** True is the current row exists. */
+  bool m_row_exists;
+  /** Current position. */
+  pos_os_global_by_type m_pos;
+  /** Next position. */
+  pos_os_global_by_type m_next_pos;
+};
+
+
+/** @} */
+#endif

=== modified file 'storage/perfschema/table_setup_consumers.cc'
--- a/storage/perfschema/table_setup_consumers.cc	2010-07-23 19:03:52 +0000
+++ b/storage/perfschema/table_setup_consumers.cc	2010-09-23 16:08:54 +0000
@@ -24,7 +24,7 @@
 #include "pfs_instr.h"
 #include "pfs_events_waits.h"
 
-#define COUNT_SETUP_CONSUMERS 8
+#define COUNT_SETUP_CONSUMERS 5
 static row_setup_consumers all_setup_consumers_data[COUNT_SETUP_CONSUMERS]=
 {
   {
@@ -40,24 +40,12 @@ static row_setup_consumers all_setup_con
     &flag_events_waits_history_long
   },
   {
-    { C_STRING_WITH_LEN("events_waits_summary_by_thread_by_event_name") },
-    &flag_events_waits_summary_by_thread_by_event_name
+    { C_STRING_WITH_LEN("global_instrumentation") },
+    &flag_global_instrumentation
   },
   {
-    { C_STRING_WITH_LEN("events_waits_summary_by_event_name") },
-    &flag_events_waits_summary_by_event_name
-  },
-  {
-    { C_STRING_WITH_LEN("events_waits_summary_by_instance") },
-    &flag_events_waits_summary_by_instance
-  },
-  {
-    { C_STRING_WITH_LEN("file_summary_by_event_name") },
-    &flag_file_summary_by_event_name
-  },
-  {
-    { C_STRING_WITH_LEN("file_summary_by_instance") },
-    &flag_file_summary_by_instance
+    { C_STRING_WITH_LEN("thread_instrumentation") },
+    &flag_thread_instrumentation
   }
 };
 

=== modified file 'storage/perfschema/table_setup_instruments.cc'
--- a/storage/perfschema/table_setup_instruments.cc	2010-07-30 09:02:32 +0000
+++ b/storage/perfschema/table_setup_instruments.cc	2010-09-23 16:08:54 +0000
@@ -89,6 +89,7 @@ int table_setup_instruments::rnd_next(vo
   PFS_rwlock_class *rwlock_class;
   PFS_cond_class *cond_class;
   PFS_file_class *file_class;
+  PFS_instr_class *table_class;
 
   for (m_pos.set_at(&m_next_pos);
        m_pos.has_more_view();
@@ -135,9 +136,10 @@ int table_setup_instruments::rnd_next(vo
       }
       break;
     case pos_setup_instruments::VIEW_TABLE:
-      if (m_pos.m_index_2 == 1)
+      table_class= find_table_class(m_pos.m_index_2);
+      if (table_class)
       {
-        make_row(&global_table_class);
+        make_row(table_class);
         m_next_pos.set_after(&m_pos);
         return 0;
       }
@@ -154,6 +156,7 @@ int table_setup_instruments::rnd_pos(con
   PFS_rwlock_class *rwlock_class;
   PFS_cond_class *cond_class;
   PFS_file_class *file_class;
+  PFS_instr_class *table_class;
 
   set_position(pos);
 
@@ -194,9 +197,10 @@ int table_setup_instruments::rnd_pos(con
     }
     break;
   case pos_setup_instruments::VIEW_TABLE:
-    if (m_pos.m_index_2 == 1)
+    table_class= find_table_class(m_pos.m_index_2);
+    if (table_class)
     {
-      make_row(&global_table_class);
+      make_row(table_class);
       return 0;
     }
     break;

=== added file 'storage/perfschema/table_setup_objects.cc'
--- a/storage/perfschema/table_setup_objects.cc	1970-01-01 00:00:00 +0000
+++ b/storage/perfschema/table_setup_objects.cc	2010-09-23 16:08:54 +0000
@@ -0,0 +1,362 @@
+/* Copyright (c) 2008, 2010, 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/table_setup_objects.cc
+  Table SETUP_OBJECTS (implementation).
+*/
+
+#include "my_global.h"
+#include "my_pthread.h"
+#include "pfs_instr.h"
+#include "pfs_column_types.h"
+#include "pfs_column_values.h"
+#include "pfs_setup_object.h"
+#include "table_setup_objects.h"
+#include "table_helper.h"
+#include "pfs_global.h"
+
+THR_LOCK table_setup_objects::m_table_lock;
+
+static const TABLE_FIELD_TYPE field_types[]=
+{
+  {
+    { C_STRING_WITH_LEN("OBJECT_TYPE") },
+    { C_STRING_WITH_LEN("enum(\'TABLE\')") },
+    { NULL, 0}
+  },
+  {
+    { C_STRING_WITH_LEN("OBJECT_SCHEMA") },
+    { C_STRING_WITH_LEN("varchar(64)") },
+    { NULL, 0}
+  },
+  {
+    { C_STRING_WITH_LEN("OBJECT_NAME") },
+    { C_STRING_WITH_LEN("varchar(64)") },
+    { NULL, 0}
+  },
+#if 0
+  {
+    { C_STRING_WITH_LEN("ENABLED") },
+    { C_STRING_WITH_LEN("enum(\'YES\',\'NO\')") },
+    { NULL, 0}
+  },
+#endif
+  {
+    { C_STRING_WITH_LEN("TIMED") },
+    { C_STRING_WITH_LEN("enum(\'YES\',\'NO\')") },
+    { NULL, 0}
+  }
+};
+
+TABLE_FIELD_DEF
+table_setup_objects::m_field_def=
+{ 4, field_types };
+
+PFS_engine_table_share
+table_setup_objects::m_share=
+{
+  { C_STRING_WITH_LEN("SETUP_OBJECTS") },
+  &pfs_editable_acl,
+  table_setup_objects::create,
+  table_setup_objects::write_row,
+  table_setup_objects::delete_all_rows,
+  table_setup_objects::get_row_count,
+  1000, /* records */
+  sizeof(PFS_simple_index),
+  &m_table_lock,
+  &m_field_def,
+  false /* checked */
+};
+
+PFS_engine_table* table_setup_objects::create(void)
+{
+  return new table_setup_objects();
+}
+
+int table_setup_objects::write_row(TABLE *table, unsigned char *buf,
+                                   Field **fields)
+{
+  Field *f;
+  enum_object_type object_type= OBJECT_TYPE_TABLE;
+  String object_schema_data("%", 1, &my_charset_utf8_bin);
+  String object_name_data("%", 1, &my_charset_utf8_bin);
+  String *object_schema= &object_schema_data;
+  String *object_name= &object_name_data;
+  enum_yes_no yes_no;
+  bool enabled= true;
+  bool timed= true;
+
+  for (; (f= *fields) ; fields++)
+  {
+    if (bitmap_is_set(table->write_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;
+#if 0
+      case 3: /* ENABLED */
+        yes_no= (enum_yes_no) get_field_enum(f);
+        enabled= (yes_no == ENUM_YES) ? true : false;
+        break;
+#endif
+      case 3: /* TIMED */
+        yes_no= (enum_yes_no) get_field_enum(f);
+        timed= (yes_no == ENUM_YES) ? true : false;
+        break;
+      default:
+        DBUG_ASSERT(false);
+      }
+    }
+  }
+
+  /* Reject illegal enum values in OBJECT_TYPE */
+  if (object_type != OBJECT_TYPE_TABLE)
+    return HA_ERR_NO_REFERENCED_ROW;
+
+  return insert_setup_object(object_type, object_schema, object_name,
+                             enabled, timed);
+}
+
+int table_setup_objects::delete_all_rows(void)
+{
+  return reset_setup_object();
+}
+
+ha_rows table_setup_objects::get_row_count(void)
+{
+  return setup_object_count();
+}
+
+table_setup_objects::table_setup_objects()
+  : PFS_engine_table(&m_share, &m_pos),
+  m_row_exists(false), m_pos(0), m_next_pos(0)
+{}
+
+void table_setup_objects::reset_position(void)
+{
+  m_pos.m_index= 0;
+  m_next_pos.m_index= 0;
+}
+
+int table_setup_objects::rnd_next(void)
+{
+  PFS_setup_object *pfs;
+
+  for (m_pos.set_at(&m_next_pos);
+       m_pos.m_index < setup_object_max;
+       m_pos.next())
+  {
+    pfs= &setup_object_array[m_pos.m_index];
+    if (pfs->m_lock.is_populated())
+    {
+      make_row(pfs);
+      m_next_pos.set_after(&m_pos);
+      return 0;
+    }
+  }
+
+  return HA_ERR_END_OF_FILE;
+}
+
+int table_setup_objects::rnd_pos(const void *pos)
+{
+  PFS_setup_object *pfs;
+
+  set_position(pos);
+
+  DBUG_ASSERT(m_pos.m_index < setup_object_max);
+  pfs= &setup_object_array[m_pos.m_index];
+  if (pfs->m_lock.is_populated())
+  {
+    make_row(pfs);
+    return 0;
+  }
+
+  return HA_ERR_RECORD_DELETED;
+}
+
+void table_setup_objects::make_row(PFS_setup_object *pfs)
+{
+  pfs_lock lock;
+
+  m_row_exists= false;
+
+  pfs->m_lock.begin_optimistic_lock(&lock);
+
+  m_row.m_object_type= pfs->get_object_type();
+  memcpy(m_row.m_schema_name, pfs->m_schema_name, pfs->m_schema_name_length);
+  m_row.m_schema_name_length= pfs->m_schema_name_length;
+  memcpy(m_row.m_object_name, pfs->m_object_name, pfs->m_object_name_length);
+  m_row.m_object_name_length= pfs->m_object_name_length;
+#if 0
+  m_row.m_enabled_ptr= &pfs->m_enabled;
+#else
+  /*
+    The ENABLED column does not exist,
+    so disabled records are be displayed.
+  */
+  if (! pfs->m_enabled)
+    return;
+#endif
+
+  m_row.m_timed_ptr= &pfs->m_timed;
+
+  if (pfs->m_lock.end_optimistic_lock(&lock))
+    m_row_exists= true;
+}
+
+int table_setup_objects::read_row_values(TABLE *table,
+                                         unsigned char *buf,
+                                         Field **fields,
+                                         bool read_all)
+{
+  Field *f;
+
+  if (unlikely(! m_row_exists))
+    return HA_ERR_RECORD_DELETED;
+
+  /* Set the null bits */
+  DBUG_ASSERT(table->s->null_bytes == 1);
+  buf[0]= 0;
+
+  for (; (f= *fields) ; fields++)
+  {
+    if (read_all || bitmap_is_set(table->read_set, f->field_index))
+    {
+      switch(f->field_index)
+      {
+      case 0: /* OBJECT_TYPE */
+        set_field_enum(f, m_row.m_object_type);
+        break;
+      case 1: /* OBJECT_SCHEMA */
+        if (m_row.m_schema_name_length)
+          set_field_varchar_utf8(f, m_row.m_schema_name,
+                                 m_row.m_schema_name_length);
+        else
+          f->set_null();
+        break;
+      case 2: /* OBJECT_NAME */
+        if (m_row.m_object_name_length)
+          set_field_varchar_utf8(f, m_row.m_object_name,
+                                 m_row.m_object_name_length);
+        else
+          f->set_null();
+        break;
+#if 0
+      case 3: /* ENABLED */
+        set_field_enum(f, (*m_row.m_enabled_ptr) ? ENUM_YES : ENUM_NO);
+        break;
+#endif
+      case 3: /* TIMED */
+        set_field_enum(f, (*m_row.m_timed_ptr) ? ENUM_YES : ENUM_NO);
+        break;
+      default:
+        DBUG_ASSERT(false);
+      }
+    }
+  }
+
+  return 0;
+}
+
+int table_setup_objects::update_row_values(TABLE *table,
+                                           const unsigned char *,
+                                           unsigned char *,
+                                           Field **fields)
+{
+  Field *f;
+  enum_yes_no value;
+
+  for (; (f= *fields) ; fields++)
+  {
+    if (bitmap_is_set(table->write_set, f->field_index))
+    {
+      switch(f->field_index)
+      {
+      case 0: /* OBJECT_TYPE */
+      case 1: /* OBJECT_SCHEMA */
+      case 2: /* OBJECT_NAME */
+        my_error(ER_WRONG_PERFSCHEMA_USAGE, MYF(0));
+        return HA_ERR_WRONG_COMMAND;
+#if 0
+      case 3: /* ENABLED */
+        value= (enum_yes_no) get_field_enum(f);
+        *m_row.m_enabled_ptr= (value == ENUM_YES) ? true : false;
+        break;
+#endif
+      case 3: /* TIMED */
+        value= (enum_yes_no) get_field_enum(f);
+        *m_row.m_timed_ptr= (value == ENUM_YES) ? true : false;
+        break;
+      default:
+        DBUG_ASSERT(false);
+      }
+    }
+  }
+
+  setup_objects_version++;
+  return 0;
+}
+
+int table_setup_objects::delete_row_values(TABLE *table,
+                                           const unsigned char *buf,
+                                           Field **fields)
+{
+  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;
+
+  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);
+      }
+    }
+  }
+
+  DBUG_ASSERT(object_schema != NULL);
+  DBUG_ASSERT(object_name != NULL);
+
+  return delete_setup_object(object_type, object_schema, object_name);
+}
+

=== added file 'storage/perfschema/table_setup_objects.h'
--- a/storage/perfschema/table_setup_objects.h	1970-01-01 00:00:00 +0000
+++ b/storage/perfschema/table_setup_objects.h	2010-09-23 16:08:54 +0000
@@ -0,0 +1,111 @@
+/* Copyright (c) 2008, 2010, 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_SETUP_OBJECTS_H
+#define TABLE_SETUP_OBJECTS_H
+
+/**
+  @file storage/perfschema/table_setup_objects.h
+  Table SETUP_OBJECTS (declarations).
+*/
+
+#include "pfs_engine_table.h"
+#include "table_helper.h"
+
+struct PFS_setup_object;
+
+/**
+  @addtogroup Performance_schema_tables
+  @{
+*/
+
+/** A row of PERFORMANCE_SCHEMA.SETUP_OBJECTS. */
+struct row_setup_objects
+{
+  /** Column OBJECT_TYPE. */
+  enum_object_type m_object_type;
+  /** Column SCHEMA_NAME. */
+  char m_schema_name[NAME_LEN];
+  /** Length in bytes of @c m_schema_name. */
+  uint m_schema_name_length;
+  /** Column OBJECT_NAME. */
+  char m_object_name[NAME_LEN];
+  /** Length in bytes of @c m_object_name. */
+  uint m_object_name_length;
+#if 0
+  /** Column ENABLED. */
+  bool *m_enabled_ptr;
+#endif
+  /** Column TIMED. */
+  bool *m_timed_ptr;
+};
+
+/** Table PERFORMANCE_SCHEMA.SETUP_OBJECTS. */
+class table_setup_objects : public PFS_engine_table
+{
+public:
+  /** Table share. */
+  static PFS_engine_table_share m_share;
+  /** Table builder. */
+  static PFS_engine_table* create();
+  static int write_row(TABLE *table, unsigned char *buf, Field **fields);
+  static int delete_all_rows();
+  static ha_rows get_row_count();
+
+  virtual int rnd_next();
+  virtual int rnd_pos(const void *pos);
+  virtual void reset_position(void);
+
+protected:
+  virtual int read_row_values(TABLE *table,
+                              unsigned char *buf,
+                              Field **fields,
+                              bool read_all);
+
+  virtual int update_row_values(TABLE *table,
+                                const unsigned char *old_buf,
+                                unsigned char *new_buf,
+                                Field **fields);
+
+  virtual int delete_row_values(TABLE *table,
+                                const unsigned char *buf,
+                                Field **fields);
+
+  table_setup_objects();
+
+public:
+  ~table_setup_objects()
+  {}
+
+private:
+  void make_row(PFS_setup_object *pfs);
+
+  /** Table share lock. */
+  static THR_LOCK m_table_lock;
+  /** Fields definition. */
+  static TABLE_FIELD_DEF m_field_def;
+
+  /** Current row. */
+  row_setup_objects m_row;
+  /** True is the current row exists. */
+  bool m_row_exists;
+  /** Current position. */
+  PFS_simple_index m_pos;
+  /** Next position. */
+  PFS_simple_index m_next_pos;
+};
+
+/** @} */
+#endif

=== modified file 'storage/perfschema/unittest/pfs-t.cc'
--- a/storage/perfschema/unittest/pfs-t.cc	2010-07-23 19:03:52 +0000
+++ b/storage/perfschema/unittest/pfs-t.cc	2010-09-23 16:08:54 +0000
@@ -25,6 +25,8 @@
 #include <memory.h>
 
 #include "stub_print_error.h"
+#include "stub_pfs_defaults.h"
+#include "stub_server_misc.h"
 
 /* test helpers, to simulate the setup */
 
@@ -95,6 +97,7 @@ void test_bootstrap()
   param.m_events_waits_history_sizing= 0;
   param.m_events_waits_history_long_sizing= 0;
   param.m_setup_actor_sizing= 0;
+  param.m_setup_object_sizing= 0;
 
   boot= initialize_performance_schema(& param);
   ok(boot != NULL, "boot");
@@ -138,11 +141,16 @@ PSI * load_perfschema()
   param.m_events_waits_history_sizing= 10;
   param.m_events_waits_history_long_sizing= 10;
   param.m_setup_actor_sizing= 0;
+  param.m_setup_object_sizing= 0;
 
   /* test_bootstrap() covered this, assuming it just works */
   boot= initialize_performance_schema(& param);
   psi= boot->get_interface(PSI_VERSION_1);
 
+  /* Reset every consumer to a known state */
+  flag_global_instrumentation= true;
+  flag_thread_instrumentation= true;
+
   return (PSI*) psi;
 }
 
@@ -554,8 +562,8 @@ void test_init_disabled()
   file_class_A= find_file_class(file_key_A);
   ok(file_class_A != NULL, "file class A");
 
-  /* Pretend thread T-1 is running, and disabled */
-  /* ------------------------------------------- */
+  /* Pretend thread T-1 is running, and disabled, with thread_instrumentation */
+  /* ------------------------------------------------------------------------ */
 
   psi->set_thread(thread_1);
   setup_thread(thread_1, false);
@@ -564,61 +572,61 @@ void test_init_disabled()
 
   mutex_class_A->m_enabled= false;
   mutex_A1= psi->init_mutex(mutex_key_A, NULL);
-  ok(mutex_A1 == NULL, "not instrumented");
+  ok(mutex_A1 == NULL, "mutex_A1 not instrumented");
 
-  /* enabled M-A + disabled T-1: no instrumentation */
+  /* enabled M-A + disabled T-1: instrumentation (for later) */
 
   mutex_class_A->m_enabled= true;
   mutex_A1= psi->init_mutex(mutex_key_A, NULL);
-  ok(mutex_A1 == NULL, "not instrumented");
+  ok(mutex_A1 != NULL, "mutex_A1 instrumented");
 
   /* broken key + disabled T-1: no instrumentation */
 
   mutex_class_A->m_enabled= true;
   mutex_A1= psi->init_mutex(0, NULL);
-  ok(mutex_A1 == NULL, "not instrumented");
+  ok(mutex_A1 == NULL, "mutex key 0 not instrumented");
   mutex_A1= psi->init_mutex(99, NULL);
-  ok(mutex_A1 == NULL, "not instrumented");
+  ok(mutex_A1 == NULL, "broken mutex key not instrumented");
 
   /* disabled RW-A + disabled T-1: no instrumentation */
 
   rwlock_class_A->m_enabled= false;
   rwlock_A1= psi->init_rwlock(rwlock_key_A, NULL);
-  ok(rwlock_A1 == NULL, "not instrumented");
+  ok(rwlock_A1 == NULL, "rwlock_A1 not instrumented");
 
-  /* enabled RW-A + disabled T-1: no instrumentation */
+  /* enabled RW-A + disabled T-1: instrumentation (for later) */
 
   rwlock_class_A->m_enabled= true;
   rwlock_A1= psi->init_rwlock(rwlock_key_A, NULL);
-  ok(rwlock_A1 == NULL, "not instrumented");
+  ok(rwlock_A1 != NULL, "rwlock_A1 instrumented");
 
   /* broken key + disabled T-1: no instrumentation */
 
   rwlock_class_A->m_enabled= true;
   rwlock_A1= psi->init_rwlock(0, NULL);
-  ok(rwlock_A1 == NULL, "not instrumented");
+  ok(rwlock_A1 == NULL, "rwlock key 0 not instrumented");
   rwlock_A1= psi->init_rwlock(99, NULL);
-  ok(rwlock_A1 == NULL, "not instrumented");
+  ok(rwlock_A1 == NULL, "broken rwlock key not instrumented");
 
   /* disabled C-A + disabled T-1: no instrumentation */
 
   cond_class_A->m_enabled= false;
   cond_A1= psi->init_cond(cond_key_A, NULL);
-  ok(cond_A1 == NULL, "not instrumented");
+  ok(cond_A1 == NULL, "cond_A1 not instrumented");
 
-  /* enabled C-A + disabled T-1: no instrumentation */
+  /* enabled C-A + disabled T-1: instrumentation (for later) */
 
   cond_class_A->m_enabled= true;
   cond_A1= psi->init_cond(cond_key_A, NULL);
-  ok(cond_A1 == NULL, "not instrumented");
+  ok(cond_A1 != NULL, "cond_A1 instrumented");
 
   /* broken key + disabled T-1: no instrumentation */
 
   cond_class_A->m_enabled= true;
   cond_A1= psi->init_cond(0, NULL);
-  ok(cond_A1 == NULL, "not instrumented");
+  ok(cond_A1 == NULL, "cond key 0 not instrumented");
   cond_A1= psi->init_cond(99, NULL);
-  ok(cond_A1 == NULL, "not instrumented");
+  ok(cond_A1 == NULL, "broken cond key not instrumented");
 
   /* disabled F-A + disabled T-1: no instrumentation */
 
@@ -740,17 +748,17 @@ void test_init_disabled()
   file_class_A->m_enabled= true;
   psi->create_file(file_key_A, "foo-instrumented", (File) 12);
   file_A1= lookup_file_by_name("foo-instrumented");
-  ok(file_A1 != NULL, "instrumented");
+  ok(file_A1 != NULL, "file_A1 instrumented");
 
   /* broken key + enabled T-1: no instrumentation */
 
   file_class_A->m_enabled= true;
   psi->create_file(0, "foo", (File) 12);
   file_A1= lookup_file_by_name("foo");
-  ok(file_A1 == NULL, "not instrumented");
+  ok(file_A1 == NULL, "file key 0 not instrumented");
   psi->create_file(99, "foo", (File) 12);
   file_A1= lookup_file_by_name("foo");
-  ok(file_A1 == NULL, "not instrumented");
+  ok(file_A1 == NULL, "broken file key not instrumented");
 
   /* Pretend the running thread is not instrumented */
   /* ---------------------------------------------- */
@@ -761,61 +769,61 @@ void test_init_disabled()
 
   mutex_class_A->m_enabled= false;
   mutex_A1= psi->init_mutex(mutex_key_A, NULL);
-  ok(mutex_A1 == NULL, "not instrumented");
+  ok(mutex_A1 == NULL, "mutex_A1 not instrumented");
 
-  /* enabled M-A + unknown thread: no instrumentation */
+  /* enabled M-A + unknown thread: instrumentation (for later) */
 
   mutex_class_A->m_enabled= true;
   mutex_A1= psi->init_mutex(mutex_key_A, NULL);
-  ok(mutex_A1 == NULL, "not instrumented");
+  ok(mutex_A1 != NULL, "mutex_A1 instrumented");
 
   /* broken key + unknown thread: no instrumentation */
 
   mutex_class_A->m_enabled= true;
   mutex_A1= psi->init_mutex(0, NULL);
-  ok(mutex_A1 == NULL, "not instrumented");
+  ok(mutex_A1 == NULL, "mutex key 0 not instrumented");
   mutex_A1= psi->init_mutex(99, NULL);
-  ok(mutex_A1 == NULL, "not instrumented");
+  ok(mutex_A1 == NULL, "broken mutex key not instrumented");
 
   /* disabled RW-A + unknown thread: no instrumentation */
 
   rwlock_class_A->m_enabled= false;
   rwlock_A1= psi->init_rwlock(rwlock_key_A, NULL);
-  ok(rwlock_A1 == NULL, "not instrumented");
+  ok(rwlock_A1 == NULL, "rwlock_A1 not instrumented");
 
-  /* enabled RW-A + unknown thread: no instrumentation */
+  /* enabled RW-A + unknown thread: instrumentation (for later) */
 
   rwlock_class_A->m_enabled= true;
   rwlock_A1= psi->init_rwlock(rwlock_key_A, NULL);
-  ok(rwlock_A1 == NULL, "not instrumented");
+  ok(rwlock_A1 != NULL, "rwlock_A1 instrumented");
 
   /* broken key + unknown thread: no instrumentation */
 
   rwlock_class_A->m_enabled= true;
   rwlock_A1= psi->init_rwlock(0, NULL);
-  ok(rwlock_A1 == NULL, "not instrumented");
+  ok(rwlock_A1 == NULL, "rwlock key 0 not instrumented");
   rwlock_A1= psi->init_rwlock(99, NULL);
-  ok(rwlock_A1 == NULL, "not instrumented");
+  ok(rwlock_A1 == NULL, "broken rwlock key not instrumented");
 
   /* disabled C-A + unknown thread: no instrumentation */
 
   cond_class_A->m_enabled= false;
   cond_A1= psi->init_cond(cond_key_A, NULL);
-  ok(cond_A1 == NULL, "not instrumented");
+  ok(cond_A1 == NULL, "cond_A1 not instrumented");
 
-  /* enabled C-A + unknown thread: no instrumentation */
+  /* enabled C-A + unknown thread: instrumentation (for later) */
 
   cond_class_A->m_enabled= true;
   cond_A1= psi->init_cond(cond_key_A, NULL);
-  ok(cond_A1 == NULL, "not instrumented");
+  ok(cond_A1 != NULL, "cond_A1 instrumented");
 
   /* broken key + unknown thread: no instrumentation */
 
   cond_class_A->m_enabled= true;
   cond_A1= psi->init_cond(0, NULL);
-  ok(cond_A1 == NULL, "not instrumented");
+  ok(cond_A1 == NULL, "cond key 0 not instrumented");
   cond_A1= psi->init_cond(99, NULL);
-  ok(cond_A1 == NULL, "not instrumented");
+  ok(cond_A1 == NULL, "broken cond key not instrumented");
 
   /* disabled F-A + unknown thread: no instrumentation */
 
@@ -960,46 +968,84 @@ void test_locker_disabled()
   cond_class_A->m_enabled= true;
   file_class_A->m_enabled= true;
 
+
   mutex_locker= psi->get_thread_mutex_locker(&mutex_state, mutex_A1, PSI_MUTEX_LOCK);
-  ok(mutex_locker == NULL, "no locker");
+  ok(mutex_locker == NULL, "no locker (T-1 disabled)");
   rwlock_locker= psi->get_thread_rwlock_locker(&rwlock_state, rwlock_A1, PSI_RWLOCK_READLOCK);
-  ok(rwlock_locker == NULL, "no locker");
+  ok(rwlock_locker == NULL, "no locker (T-1 disabled)");
   cond_locker= psi->get_thread_cond_locker(&cond_state, cond_A1, mutex_A1, PSI_COND_WAIT);
-  ok(cond_locker == NULL, "no locker");
+  ok(cond_locker == NULL, "no locker (T-1 disabled)");
   file_locker= psi->get_thread_file_name_locker(&file_state, file_key_A, PSI_FILE_OPEN, "xxx", NULL);
-  ok(file_locker == NULL, "no locker");
+  ok(file_locker == NULL, "no locker (T-1 disabled)");
   file_locker= psi->get_thread_file_stream_locker(&file_state, file_A1, PSI_FILE_READ);
-  ok(file_locker == NULL, "no locker");
+  ok(file_locker == NULL, "no locker (T-1 disabled)");
   file_locker= psi->get_thread_file_descriptor_locker(&file_state, (File) 12, PSI_FILE_READ);
-  ok(file_locker == NULL, "no locker");
+  ok(file_locker == NULL, "no locker (T-1 disabled)");
 
-  /* Pretend the consumer is disabled */
-  /* -------------------------------- */
+  /* Pretend the global consumer is disabled */
+  /* --------------------------------------- */
 
   setup_thread(thread_1, true);
-  flag_events_waits_current= false;
+  flag_global_instrumentation= false;
   mutex_class_A->m_enabled= true;
   rwlock_class_A->m_enabled= true;
   cond_class_A->m_enabled= true;
   file_class_A->m_enabled= true;
 
   mutex_locker= psi->get_thread_mutex_locker(&mutex_state, mutex_A1, PSI_MUTEX_LOCK);
-  ok(mutex_locker == NULL, "no locker");
+  ok(mutex_locker == NULL, "no locker (global disabled)");
   rwlock_locker= psi->get_thread_rwlock_locker(&rwlock_state, rwlock_A1, PSI_RWLOCK_READLOCK);
-  ok(rwlock_locker == NULL, "no locker");
+  ok(rwlock_locker == NULL, "no locker (global disabled)");
   cond_locker= psi->get_thread_cond_locker(&cond_state, cond_A1, mutex_A1, PSI_COND_WAIT);
-  ok(cond_locker == NULL, "no locker");
+  ok(cond_locker == NULL, "no locker (global disabled)");
   file_locker= psi->get_thread_file_name_locker(&file_state, file_key_A, PSI_FILE_OPEN, "xxx", NULL);
-  ok(file_locker == NULL, "no locker");
+  ok(file_locker == NULL, "no locker (global disabled)");
   file_locker= psi->get_thread_file_stream_locker(&file_state, file_A1, PSI_FILE_READ);
-  ok(file_locker == NULL, "no locker");
+  ok(file_locker == NULL, "no locker (global disabled)");
   file_locker= psi->get_thread_file_descriptor_locker(&file_state, (File) 12, PSI_FILE_READ);
-  ok(file_locker == NULL, "no locker");
+  ok(file_locker == NULL, "no locker (global disabled)");
+
+  /* Pretent the mode is global, counted only */
+  /* ---------------------------------------- */
+
+  setup_thread(thread_1, true);
+  flag_global_instrumentation= true;
+  flag_thread_instrumentation= false;
+  mutex_class_A->m_enabled= true;
+  mutex_class_A->m_timed= false;
+  rwlock_class_A->m_enabled= true;
+  rwlock_class_A->m_timed= false;
+  cond_class_A->m_enabled= true;
+  cond_class_A->m_timed= false;
+  file_class_A->m_enabled= true;
+  file_class_A->m_timed= false;
+
+  mutex_locker= psi->get_thread_mutex_locker(&mutex_state, mutex_A1, PSI_MUTEX_LOCK);
+  ok(mutex_locker == NULL, "no locker (global counted)");
+  rwlock_locker= psi->get_thread_rwlock_locker(&rwlock_state, rwlock_A1, PSI_RWLOCK_READLOCK);
+  ok(rwlock_locker == NULL, "no locker (global counted)");
+  cond_locker= psi->get_thread_cond_locker(&cond_state, cond_A1, mutex_A1, PSI_COND_WAIT);
+  ok(cond_locker == NULL, "no locker (global counted)");
+  file_locker= psi->get_thread_file_name_locker(&file_state, file_key_A, PSI_FILE_OPEN, "xxx", NULL);
+  ok(file_locker != NULL, "locker (global counted)");
+  psi->start_file_wait(file_locker, 10, __FILE__, __LINE__);
+  psi->end_file_wait(file_locker, 10);
+  file_locker= psi->get_thread_file_stream_locker(&file_state, file_A1, PSI_FILE_READ);
+  ok(file_locker != NULL, "locker (global counted)");
+  psi->start_file_wait(file_locker, 10, __FILE__, __LINE__);
+  psi->end_file_wait(file_locker, 10);
+  file_locker= psi->get_thread_file_descriptor_locker(&file_state, (File) 12, PSI_FILE_READ);
+  ok(file_locker != NULL, "locker (global counted)");
+  psi->start_file_wait(file_locker, 10, __FILE__, __LINE__);
+  psi->end_file_wait(file_locker, 10);
+
+  /* TODO */
 
   /* Pretend the instrument is disabled */
   /* ---------------------------------- */
 
   setup_thread(thread_1, true);
+  flag_global_instrumentation= true;
   flag_events_waits_current= true;
   mutex_class_A->m_enabled= false;
   rwlock_class_A->m_enabled= false;
@@ -1019,15 +1065,21 @@ void test_locker_disabled()
   file_locker= psi->get_thread_file_descriptor_locker(&file_state, (File) 12, PSI_FILE_READ);
   ok(file_locker == NULL, "no locker");
 
-  /* Pretend everything is enabled */
-  /* ----------------------------- */
+  /* Pretend everything is enabled and timed */
+  /* --------------------------------------- */
 
   setup_thread(thread_1, true);
+  flag_global_instrumentation= true;
+  flag_thread_instrumentation= true;
   flag_events_waits_current= true;
   mutex_class_A->m_enabled= true;
+  mutex_class_A->m_timed= true;
   rwlock_class_A->m_enabled= true;
+  rwlock_class_A->m_timed= true;
   cond_class_A->m_enabled= true;
+  cond_class_A->m_timed= true;
   file_class_A->m_enabled= true;
+  file_class_A->m_timed= true;
 
   mutex_locker= psi->get_thread_mutex_locker(&mutex_state, mutex_A1, PSI_MUTEX_LOCK);
   ok(mutex_locker != NULL, "locker");
@@ -1204,6 +1256,118 @@ void test_enabled()
 #endif
 }
 
+void test_event_name_index()
+{
+  PSI *psi;
+  PSI_bootstrap *boot;
+  PFS_global_param param;
+
+  diag("test_event_name_index");
+
+  param.m_enabled= true;
+
+  /* Per mutex info waits should be at [0..9] */
+  param.m_mutex_class_sizing= 10;
+  /* Per rwlock info waits should be at [10..29] */
+  param.m_rwlock_class_sizing= 20;
+  /* Per cond info waits should be at [30..69] */
+  param.m_cond_class_sizing= 40;
+  /* Per file info waits should be at [70..149] */
+  param.m_file_class_sizing= 80;
+  /* Per table info waits should be at [150] */
+  param.m_table_share_sizing= 160;
+
+  param.m_thread_class_sizing= 0;
+
+  param.m_mutex_sizing= 0;
+  param.m_rwlock_sizing= 0;
+  param.m_cond_sizing= 0;
+  param.m_thread_sizing= 0;
+  param.m_table_sizing= 0;
+  param.m_file_sizing= 0;
+  param.m_file_handle_sizing= 0;
+  param.m_events_waits_history_sizing= 0;
+  param.m_events_waits_history_long_sizing= 0;
+  param.m_setup_actor_sizing= 0;
+  param.m_setup_object_sizing= 0;
+
+  boot= initialize_performance_schema(& param);
+  ok(boot != NULL, "bootstrap");
+  psi= (PSI*) boot->get_interface(PSI_VERSION_1);
+  ok(psi != NULL, "psi");
+
+  PFS_mutex_class *mutex_class;
+  PSI_mutex_key dummy_mutex_key_1;
+  PSI_mutex_key dummy_mutex_key_2;
+  PSI_mutex_info dummy_mutexes[]=
+  {
+    { & dummy_mutex_key_1, "M-1", 0},
+    { & dummy_mutex_key_2, "M-2", 0}
+  };
+
+  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");
+  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");
+
+  PFS_rwlock_class *rwlock_class;
+  PSI_rwlock_key dummy_rwlock_key_1;
+  PSI_rwlock_key dummy_rwlock_key_2;
+  PSI_rwlock_info dummy_rwlocks[]=
+  {
+    { & dummy_rwlock_key_1, "RW-1", 0},
+    { & dummy_rwlock_key_2, "RW-2", 0}
+  };
+
+  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");
+  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");
+
+  PFS_cond_class *cond_class;
+  PSI_cond_key dummy_cond_key_1;
+  PSI_cond_key dummy_cond_key_2;
+  PSI_cond_info dummy_conds[]=
+  {
+    { & dummy_cond_key_1, "C-1", 0},
+    { & dummy_cond_key_2, "C-2", 0}
+  };
+
+  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");
+  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");
+
+  PFS_file_class *file_class;
+  PSI_file_key dummy_file_key_1;
+  PSI_file_key dummy_file_key_2;
+  PSI_file_info dummy_files[]=
+  {
+    { & dummy_file_key_1, "F-1", 0},
+    { & dummy_file_key_2, "F-2", 0}
+  };
+
+  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");
+  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(global_table_io_class.m_event_name_index == 150, "index 150");
+  ok(max_instrument_class= 151, "151 event names");
+}
+
 void do_all_tests()
 {
   test_bootstrap();
@@ -1211,11 +1375,12 @@ void do_all_tests()
   test_init_disabled();
   test_locker_disabled();
   test_file_instrumentation_leak();
+  test_event_name_index();
 }
 
 int main(int, char **)
 {
-  plan(153);
+  plan(180);
   MY_INIT("pfs-t");
   do_all_tests();
   return 0;

=== modified file 'storage/perfschema/unittest/pfs_instr-oom-t.cc'
--- a/storage/perfschema/unittest/pfs_instr-oom-t.cc	2010-07-23 19:03:52 +0000
+++ b/storage/perfschema/unittest/pfs_instr-oom-t.cc	2010-09-23 16:08:54 +0000
@@ -18,9 +18,11 @@
 #include <pfs_instr.h>
 #include <pfs_stat.h>
 #include <pfs_global.h>
+#include <pfs_instr_class.h>
 #include <tap.h>
 
 #include "stub_pfs_global.h"
+#include "stub_server_misc.h"
 
 void test_oom()
 {
@@ -46,7 +48,9 @@ void test_oom()
   param.m_events_waits_history_sizing= 0;
   param.m_events_waits_history_long_sizing= 0;
   param.m_setup_actor_sizing= 0;
+  param.m_setup_object_sizing= 0;
 
+  init_event_name_sizing(& param);
   rc= init_instruments(& param);
   ok(rc == 1, "oom (mutex)");
 
@@ -67,7 +71,9 @@ void test_oom()
   param.m_events_waits_history_sizing= 0;
   param.m_events_waits_history_long_sizing= 0;
   param.m_setup_actor_sizing= 0;
+  param.m_setup_object_sizing= 0;
 
+  init_event_name_sizing(& param);
   rc= init_instruments(& param);
   ok(rc == 1, "oom (rwlock)");
 
@@ -88,7 +94,9 @@ void test_oom()
   param.m_events_waits_history_sizing= 0;
   param.m_events_waits_history_long_sizing= 0;
   param.m_setup_actor_sizing= 0;
+  param.m_setup_object_sizing= 0;
 
+  init_event_name_sizing(& param);
   rc= init_instruments(& param);
   ok(rc == 1, "oom (cond)");
 
@@ -109,7 +117,9 @@ void test_oom()
   param.m_events_waits_history_sizing= 0;
   param.m_events_waits_history_long_sizing= 0;
   param.m_setup_actor_sizing= 0;
+  param.m_setup_object_sizing= 0;
 
+  init_event_name_sizing(& param);
   rc= init_instruments(& param);
   ok(rc == 1, "oom (file)");
 
@@ -130,7 +140,9 @@ void test_oom()
   param.m_events_waits_history_sizing= 0;
   param.m_events_waits_history_long_sizing= 0;
   param.m_setup_actor_sizing= 0;
+  param.m_setup_object_sizing= 0;
 
+  init_event_name_sizing(& param);
   rc= init_instruments(& param);
   ok(rc == 1, "oom (table)");
 
@@ -151,7 +163,9 @@ void test_oom()
   param.m_events_waits_history_sizing= 0;
   param.m_events_waits_history_long_sizing= 0;
   param.m_setup_actor_sizing= 0;
+  param.m_setup_object_sizing= 0;
 
+  init_event_name_sizing(& param);
   rc= init_instruments(& param);
   ok(rc == 1, "oom (thread)");
 
@@ -174,8 +188,10 @@ void test_oom()
   param.m_events_waits_history_sizing= 10;
   param.m_events_waits_history_long_sizing= 0;
   param.m_setup_actor_sizing= 0;
+  param.m_setup_object_sizing= 0;
 
   stub_alloc_fails_after_count= 2;
+  init_event_name_sizing(& param);
   rc= init_instruments(& param);
   ok(rc == 1, "oom (thread history sizing)");
 
@@ -196,8 +212,10 @@ void test_oom()
   param.m_events_waits_history_sizing= 0;
   param.m_events_waits_history_long_sizing= 0;
   param.m_setup_actor_sizing= 0;
+  param.m_setup_object_sizing= 0;
 
   stub_alloc_fails_after_count= 2;
+  init_event_name_sizing(& param);
   rc= init_instruments(& param);
   ok(rc == 1, "oom (per thread wait)");
 

=== modified file 'storage/perfschema/unittest/pfs_instr-t.cc'
--- a/storage/perfschema/unittest/pfs_instr-t.cc	2010-07-30 09:02:32 +0000
+++ b/storage/perfschema/unittest/pfs_instr-t.cc	2010-09-23 16:08:54 +0000
@@ -18,10 +18,13 @@
 #include <pfs_instr.h>
 #include <pfs_stat.h>
 #include <pfs_global.h>
+#include <pfs_instr_class.h>
 #include <tap.h>
 
 #include <memory.h>
 
+#include "stub_server_misc.h"
+
 void test_no_instruments()
 {
   int rc;
@@ -44,7 +47,9 @@ void test_no_instruments()
   param.m_events_waits_history_sizing= 0;
   param.m_events_waits_history_long_sizing= 0;
   param.m_setup_actor_sizing= 0;
+  param.m_setup_object_sizing= 0;
 
+  init_event_name_sizing(& param);
   rc= init_instruments(& param);
   ok(rc == 0, "zero init");
 
@@ -85,7 +90,9 @@ void test_no_instances()
   param.m_events_waits_history_sizing= 0;
   param.m_events_waits_history_long_sizing= 0;
   param.m_setup_actor_sizing= 0;
+  param.m_setup_object_sizing= 0;
 
+  init_event_name_sizing(& param);
   rc= init_instruments(& param);
   ok(rc == 0, "no instances init");
 
@@ -199,10 +206,17 @@ void test_with_instances()
   param.m_events_waits_history_sizing= 10;
   param.m_events_waits_history_long_sizing= 10000;
   param.m_setup_actor_sizing= 0;
+  param.m_setup_object_sizing= 0;
 
+  init_event_name_sizing(& param);
   rc= init_instruments(& param);
   ok(rc == 0, "instances init");
 
+  dummy_mutex_class.m_event_name_index= 0;
+  dummy_rwlock_class.m_event_name_index= 1;
+  dummy_cond_class.m_event_name_index= 2;
+  dummy_file_class.m_event_name_index= 3;
+
   mutex_1= create_mutex(& dummy_mutex_class, NULL);
   ok(mutex_1 != NULL, "mutex");
   ok(mutex_lost == 0, "not lost");
@@ -317,100 +331,16 @@ void test_with_instances()
   cleanup_instruments();
 }
 
-void test_per_thread_wait()
-{
-  int rc;
-  PFS_mutex_class dummy_mutex_class;
-  PFS_rwlock_class dummy_rwlock_class;
-  PFS_cond_class dummy_cond_class;
-  PFS_thread_class dummy_thread_class;
-  PFS_file_class dummy_file_class;
-  PFS_thread *thread;
-  PFS_single_stat_chain *base;
-  PFS_single_stat_chain *stat;
-  PFS_global_param param;
-
-
-  /* Per mutex info waits should be at [0..9] */
-  mutex_class_max= 10;
-  /* Per rwlock info waits should be at [10..29] */
-  rwlock_class_max= 20;
-  /* Per cond info waits should be at [30..69] */
-  cond_class_max= 40;
-  /* Per file info waits should be at [70..149] */
-  file_class_max= 80;
-  /* Per table info waits should be at [150..309] */
-  table_share_max= 160;
-
-  param.m_enabled= true;
-  param.m_mutex_class_sizing= mutex_class_max;
-  param.m_rwlock_class_sizing= rwlock_class_max;
-  param.m_cond_class_sizing= cond_class_max;
-  param.m_thread_class_sizing= 2;
-  param.m_table_share_sizing= table_share_max;
-  param.m_file_class_sizing= file_class_max;
-  param.m_mutex_sizing= 0;
-  param.m_rwlock_sizing= 0;
-  param.m_cond_sizing= 0;
-  param.m_thread_sizing= 2;
-  param.m_table_sizing= 0;
-  param.m_file_sizing= 0;
-  param.m_file_handle_sizing= 0;
-  param.m_events_waits_history_sizing= 10;
-  param.m_events_waits_history_long_sizing= 10000;
-  param.m_setup_actor_sizing= 0;
-
-  rc= init_instruments(& param);
-  ok(rc == 0, "instances init");
-
-  thread= create_thread(& dummy_thread_class, NULL, 0);
-  ok(thread != NULL, "thread");
-  ok(thread_lost == 0, "not lost");
-
-  base= & thread->m_instr_class_wait_stats[0];
-
-  dummy_mutex_class.m_index= 0;
-  stat= find_per_thread_mutex_class_wait_stat(thread, & dummy_mutex_class);
-  ok(base + 0 == stat, "fist mutex info slot at 0");
-  dummy_mutex_class.m_index= mutex_class_max - 1;
-  stat= find_per_thread_mutex_class_wait_stat(thread, & dummy_mutex_class);
-  ok(base + 9 == stat, "last mutex info slot at 9");
-
-  dummy_rwlock_class.m_index= 0;
-  stat= find_per_thread_rwlock_class_wait_stat(thread, & dummy_rwlock_class);
-  ok(base + 10 == stat, "fist rwlock info slot at 10");
-  dummy_rwlock_class.m_index= rwlock_class_max - 1;
-  stat= find_per_thread_rwlock_class_wait_stat(thread, & dummy_rwlock_class);
-  ok(base + 29 == stat, "last rwlock info slot at 29");
-
-  dummy_cond_class.m_index= 0;
-  stat= find_per_thread_cond_class_wait_stat(thread, & dummy_cond_class);
-  ok(base + 30 == stat, "fist cond info slot at 30");
-  dummy_cond_class.m_index= cond_class_max - 1;
-  stat= find_per_thread_cond_class_wait_stat(thread, & dummy_cond_class);
-  ok(base + 69 == stat, "last cond info slot at 69");
-
-  dummy_file_class.m_index= 0;
-  stat= find_per_thread_file_class_wait_stat(thread, & dummy_file_class);
-  ok(base + 70 == stat, "fist file info slot at 70");
-  dummy_file_class.m_index= file_class_max - 1;
-  stat= find_per_thread_file_class_wait_stat(thread, & dummy_file_class);
-  ok(base + 149 == stat, "last file info slot at 149");
-
-  cleanup_instruments();
-}
-
 void do_all_tests()
 {
   test_no_instruments();
   test_no_instances();
   test_with_instances();
-  test_per_thread_wait();
 }
 
 int main(int, char **)
 {
-  plan(102);
+  plan(91);
   MY_INIT("pfs_instr-t");
   do_all_tests();
   return 0;

=== modified file 'storage/perfschema/unittest/pfs_instr_class-oom-t.cc'
--- a/storage/perfschema/unittest/pfs_instr_class-oom-t.cc	2010-07-16 01:28:30 +0000
+++ b/storage/perfschema/unittest/pfs_instr_class-oom-t.cc	2010-09-23 16:08:54 +0000
@@ -20,6 +20,7 @@
 #include <tap.h>
 
 #include "stub_pfs_global.h"
+#include "stub_server_misc.h"
 
 void test_oom()
 {

=== modified file 'storage/perfschema/unittest/pfs_instr_class-t.cc'
--- a/storage/perfschema/unittest/pfs_instr_class-t.cc	2010-07-23 17:08:41 +0000
+++ b/storage/perfschema/unittest/pfs_instr_class-t.cc	2010-09-23 16:08:54 +0000
@@ -21,6 +21,8 @@
 #include <pfs_global.h>
 #include <tap.h>
 
+#include "stub_server_misc.h"
+
 void test_no_registration()
 {
   int rc;
@@ -82,11 +84,11 @@ void test_no_registration()
   fake_thread.m_table_share_hash_pins= NULL;
 
 #ifdef LATER
-  table= find_or_create_table_share(& fake_thread, "foo_db", 6, "foo_table", 9);
+  table= find_or_create_table_share(& fake_thread, false, "foo_db", 6, "foo_table", 9);
   ok(table == NULL, "not created");
-  table= find_or_create_table_share(& fake_thread, "bar_db", 6, "bar_table", 9);
+  table= find_or_create_table_share(& fake_thread, false, "bar_db", 6, "bar_table", 9);
   ok(table == NULL, "not created");
-  table= find_or_create_table_share(& fake_thread, "foo_db", 6, "foo_table", 9);
+  table= find_or_create_table_share(& fake_thread, false, "foo_db", 6, "foo_table", 9);
   ok(table == NULL, "not created");
 #endif
 
@@ -356,7 +358,7 @@ void test_table_registration()
   fake_thread.m_table_share_hash_pins= NULL;
 
   table_share_lost= 0;
-  table_share= find_or_create_table_share(& fake_thread, "db1", 3, "t1", 2);
+  table_share= find_or_create_table_share(& fake_thread, false, "db1", 3, "t1", 2);
   ok(table_share == NULL, "not created");
   ok(table_share_lost == 1, "lost the table");
 
@@ -364,37 +366,37 @@ void test_table_registration()
   init_table_share(5);
   init_table_share_hash();
 
-  table_share= find_or_create_table_share(& fake_thread, "db1", 3, "t1", 2);
+  table_share= find_or_create_table_share(& fake_thread, false, "db1", 3, "t1", 2);
   ok(table_share != NULL, "created db1.t1");
   ok(table_share_lost == 0, "not lost");
 
-  table_share_2= find_or_create_table_share(& fake_thread, "db1", 3, "t1", 2);
+  table_share_2= find_or_create_table_share(& fake_thread, false, "db1", 3, "t1", 2);
   ok(table_share_2 != NULL, "found db1.t1");
   ok(table_share_lost == 0, "not lost");
   ok(table_share == table_share_2, "same table");
 
-  table_share_2= find_or_create_table_share(& fake_thread, "db1", 3, "t2", 2);
+  table_share_2= find_or_create_table_share(& fake_thread, false, "db1", 3, "t2", 2);
   ok(table_share_2 != NULL, "created db1.t2");
   ok(table_share_lost == 0, "not lost");
 
-  table_share_2= find_or_create_table_share(& fake_thread, "db2", 3, "t1", 2);
+  table_share_2= find_or_create_table_share(& fake_thread, false, "db2", 3, "t1", 2);
   ok(table_share_2 != NULL, "created db2.t1");
   ok(table_share_lost == 0, "not lost");
 
-  table_share_2= find_or_create_table_share(& fake_thread, "db2", 3, "t2", 2);
+  table_share_2= find_or_create_table_share(& fake_thread, false, "db2", 3, "t2", 2);
   ok(table_share_2 != NULL, "created db2.t2");
   ok(table_share_lost == 0, "not lost");
 
-  table_share_2= find_or_create_table_share(& fake_thread, "db3", 3, "t3", 2);
+  table_share_2= find_or_create_table_share(& fake_thread, false, "db3", 3, "t3", 2);
   ok(table_share_2 != NULL, "created db3.t3");
   ok(table_share_lost == 0, "not lost");
 
-  table_share_2= find_or_create_table_share(& fake_thread, "db4", 3, "t4", 2);
+  table_share_2= find_or_create_table_share(& fake_thread, false, "db4", 3, "t4", 2);
   ok(table_share_2 == NULL, "lost db4.t4");
   ok(table_share_lost == 1, "lost");
 
   table_share_lost= 0;
-  table_share_2= find_or_create_table_share(& fake_thread, "db1", 3, "t2", 2);
+  table_share_2= find_or_create_table_share(& fake_thread, false, "db1", 3, "t2", 2);
   ok(table_share_2 != NULL, "found db1.t2");
   ok(table_share_lost == 0, "not lost");
   ok(strncmp(table_share_2->m_schema_name, "db1", 3) == 0 , "schema db1");
@@ -407,16 +409,22 @@ void test_table_registration()
 #endif
 }
 
-void set_wait_stat(PFS_single_stat_chain *stat)
+void set_wait_stat(PFS_instr_class *klass)
 {
+  PFS_single_stat *stat;
+  stat= & global_instr_class_waits_array[klass->m_event_name_index];
+
   stat->m_count= 12;
   stat->m_min= 5;
   stat->m_max= 120;
   stat->m_sum= 999;
 }
 
-bool is_empty_stat(PFS_single_stat_chain *stat)
+bool is_empty_stat(PFS_instr_class *klass)
 {
+  PFS_single_stat *stat;
+  stat= & global_instr_class_waits_array[klass->m_event_name_index];
+
   if (stat->m_count != 0)
     return false;
   if (stat->m_min != (ulonglong) -1)
@@ -509,46 +517,48 @@ void test_instruments_reset()
   file_3= find_file_class(3);
   ok(file_3 != NULL, "file key 3");
 
-  set_wait_stat(& mutex_1->m_wait_stat);
-  set_wait_stat(& mutex_2->m_wait_stat);
-  set_wait_stat(& mutex_3->m_wait_stat);
-  set_wait_stat(& rwlock_1->m_wait_stat);
-  set_wait_stat(& rwlock_2->m_wait_stat);
-  set_wait_stat(& rwlock_3->m_wait_stat);
-  set_wait_stat(& cond_1->m_wait_stat);
-  set_wait_stat(& cond_2->m_wait_stat);
-  set_wait_stat(& cond_3->m_wait_stat);
-  set_wait_stat(& file_1->m_wait_stat);
-  set_wait_stat(& file_2->m_wait_stat);
-  set_wait_stat(& file_3->m_wait_stat);
-
-  ok(! is_empty_stat(& mutex_1->m_wait_stat), "mutex_1 stat is populated");
-  ok(! is_empty_stat(& mutex_2->m_wait_stat), "mutex_2 stat is populated");
-  ok(! is_empty_stat(& mutex_3->m_wait_stat), "mutex_3 stat is populated");
-  ok(! is_empty_stat(& rwlock_1->m_wait_stat), "rwlock_1 stat is populated");
-  ok(! is_empty_stat(& rwlock_2->m_wait_stat), "rwlock_2 stat is populated");
-  ok(! is_empty_stat(& rwlock_3->m_wait_stat), "rwlock_3 stat is populated");
-  ok(! is_empty_stat(& cond_1->m_wait_stat), "cond_1 stat is populated");
-  ok(! is_empty_stat(& cond_2->m_wait_stat), "cond_2 stat is populated");
-  ok(! is_empty_stat(& cond_3->m_wait_stat), "cond_3 stat is populated");
-  ok(! is_empty_stat(& file_1->m_wait_stat), "file_1 stat is populated");
-  ok(! is_empty_stat(& file_2->m_wait_stat), "file_2 stat is populated");
-  ok(! is_empty_stat(& file_3->m_wait_stat), "file_3 stat is populated");
-
-  reset_instrument_class_waits();
-
-  ok(is_empty_stat(& mutex_1->m_wait_stat), "mutex_1 stat is cleared");
-  ok(is_empty_stat(& mutex_2->m_wait_stat), "mutex_2 stat is cleared");
-  ok(is_empty_stat(& mutex_3->m_wait_stat), "mutex_3 stat is cleared");
-  ok(is_empty_stat(& rwlock_1->m_wait_stat), "rwlock_1 stat is cleared");
-  ok(is_empty_stat(& rwlock_2->m_wait_stat), "rwlock_2 stat is cleared");
-  ok(is_empty_stat(& rwlock_3->m_wait_stat), "rwlock_3 stat is cleared");
-  ok(is_empty_stat(& cond_1->m_wait_stat), "cond_1 stat is cleared");
-  ok(is_empty_stat(& cond_2->m_wait_stat), "cond_2 stat is cleared");
-  ok(is_empty_stat(& cond_3->m_wait_stat), "cond_3 stat is cleared");
-  ok(is_empty_stat(& file_1->m_wait_stat), "file_1 stat is cleared");
-  ok(is_empty_stat(& file_2->m_wait_stat), "file_2 stat is cleared");
-  ok(is_empty_stat(& file_3->m_wait_stat), "file_3 stat is cleared");
+#ifdef LATER
+  set_wait_stat(mutex_1);
+  set_wait_stat(mutex_2);
+  set_wait_stat(mutex_3);
+  set_wait_stat(rwlock_1);
+  set_wait_stat(rwlock_2);
+  set_wait_stat(rwlock_3);
+  set_wait_stat(cond_1);
+  set_wait_stat(cond_2);
+  set_wait_stat(cond_3);
+  set_wait_stat(file_1);
+  set_wait_stat(file_2);
+  set_wait_stat(file_3);
+
+  ok(! is_empty_stat(mutex_1), "mutex_1 stat is populated");
+  ok(! is_empty_stat(mutex_2), "mutex_2 stat is populated");
+  ok(! is_empty_stat(mutex_3), "mutex_3 stat is populated");
+  ok(! is_empty_stat(rwlock_1), "rwlock_1 stat is populated");
+  ok(! is_empty_stat(rwlock_2), "rwlock_2 stat is populated");
+  ok(! is_empty_stat(rwlock_3), "rwlock_3 stat is populated");
+  ok(! is_empty_stat(cond_1), "cond_1 stat is populated");
+  ok(! is_empty_stat(cond_2), "cond_2 stat is populated");
+  ok(! is_empty_stat(cond_3), "cond_3 stat is populated");
+  ok(! is_empty_stat(file_1), "file_1 stat is populated");
+  ok(! is_empty_stat(file_2), "file_2 stat is populated");
+  ok(! is_empty_stat(file_3), "file_3 stat is populated");
+
+  reset_global_wait_stat();
+
+  ok(is_empty_stat(mutex_1), "mutex_1 stat is cleared");
+  ok(is_empty_stat(mutex_2), "mutex_2 stat is cleared");
+  ok(is_empty_stat(mutex_3), "mutex_3 stat is cleared");
+  ok(is_empty_stat(rwlock_1), "rwlock_1 stat is cleared");
+  ok(is_empty_stat(rwlock_2), "rwlock_2 stat is cleared");
+  ok(is_empty_stat(rwlock_3), "rwlock_3 stat is cleared");
+  ok(is_empty_stat(cond_1), "cond_1 stat is cleared");
+  ok(is_empty_stat(cond_2), "cond_2 stat is cleared");
+  ok(is_empty_stat(cond_3), "cond_3 stat is cleared");
+  ok(is_empty_stat(file_1), "file_1 stat is cleared");
+  ok(is_empty_stat(file_2), "file_2 stat is cleared");
+  ok(is_empty_stat(file_3), "file_3 stat is cleared");
+#endif
 
   cleanup_sync_class();
   cleanup_file_class();
@@ -568,7 +578,7 @@ void do_all_tests()
 
 int main(int, char **)
 {
-  plan(170);
+  plan(146);
   MY_INIT("pfs_instr_info-t");
   do_all_tests();
   return 0;

=== added file 'storage/perfschema/unittest/stub_pfs_defaults.h'
--- a/storage/perfschema/unittest/stub_pfs_defaults.h	1970-01-01 00:00:00 +0000
+++ b/storage/perfschema/unittest/stub_pfs_defaults.h	2010-09-23 16:08:54 +0000
@@ -0,0 +1,23 @@
+/* Copyright (c) 2010, 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, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#include <my_global.h>
+#include <pfs.h>
+#include <pfs_defaults.h>
+
+void install_default_setup(PSI_bootstrap *)
+{
+}
+

=== added file 'storage/perfschema/unittest/stub_server_misc.h'
--- a/storage/perfschema/unittest/stub_server_misc.h	1970-01-01 00:00:00 +0000
+++ b/storage/perfschema/unittest/stub_server_misc.h	2010-09-23 16:08:54 +0000
@@ -0,0 +1,22 @@
+/* Copyright (c) 2010, 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, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+/*
+  Minimal code to be able to link a unit test.
+*/
+
+uint lower_case_table_names= 0;
+CHARSET_INFO *files_charset_info= NULL;
+


Attachment: [text/bzr-bundle] bzr/marc.alff@oracle.com-20100923160854-lq212fzuzrl85nw4.bundle
Thread
bzr push into mysql-next-mr-wl4816 branch (marc.alff:3193 to 3194) WL#4816Marc Alff23 Sep