List:Commits« Previous MessageNext Message »
From:Marc Alff Date:January 7 2011 4:20pm
Subject:bzr commit into mysql-trunk-wl5379 branch (marc.alff:3215) WL#5371 WL#5379
WL#5420
View as plain text  
#At file:///Users/malff/BZR_TREE/mysql-trunk-wl5379/ based on revid:marc.alff@stripped

 3215 Marc Alff	2011-01-07
      WL#5371 PERFORMANCE_SCHEMA Instrumenting Table Locks
      WL#5379 PERFORMANCE SCHEMA TABLE / INDEX IO SUMMARY
      WL#5420 PERFORMANCE SCHEMA TABLE LOCK WAIT SUMMARY
      
      Code cleanup,
      implemented a visitor pattern to reduce code duplication.

    added:
      storage/perfschema/pfs_visitor.cc
      storage/perfschema/pfs_visitor.h
    modified:
      storage/perfschema/CMakeLists.txt
      storage/perfschema/table_ews_by_thread_by_event_name.cc
      storage/perfschema/table_ews_by_thread_by_event_name.h
      storage/perfschema/table_ews_global_by_event_name.cc
      storage/perfschema/table_ews_global_by_event_name.h
      storage/perfschema/table_helper.cc
      storage/perfschema/table_helper.h
      storage/perfschema/table_tiws_by_index_usage.cc
      storage/perfschema/table_tiws_by_index_usage.h
      storage/perfschema/table_tiws_by_table.cc
      storage/perfschema/table_tiws_by_table.h
      storage/perfschema/table_tlws_by_table.cc
      storage/perfschema/table_tlws_by_table.h
=== modified file 'storage/perfschema/CMakeLists.txt'
--- a/storage/perfschema/CMakeLists.txt	2010-12-09 16:17:13 +0000
+++ b/storage/perfschema/CMakeLists.txt	2011-01-07 16:20:19 +0000
@@ -1,4 +1,4 @@
-# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -21,78 +21,84 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}
 
 ADD_DEFINITIONS(-DMYSQL_SERVER)
 
+#
+# Maintainer: keep this list sorted, to avoid merge collisions.
+# Tip: ls -1 *.h, ls -1 *.cc
+#
 SET(PERFSCHEMA_SOURCES ha_perfschema.h
-  pfs_column_types.h
-  pfs_column_values.h
-  pfs_defaults.h
-  pfs_events_waits.h
-  pfs_global.h
-  pfs.h
-  pfs_instr.h
-  pfs_instr_class.h
-  pfs_lock.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
-  table_tiws_by_index_usage.h
-  table_tiws_by_table.h
-  table_tlws_by_table.h
-  ha_perfschema.cc
-  pfs.cc
-  pfs_column_values.cc
-  pfs_defaults.cc
-  pfs_events_waits.cc
-  pfs_global.cc
-  pfs_instr.cc
-  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
-  table_tiws_by_index_usage.cc
-  table_tiws_by_table.cc
-  table_tlws_by_table.cc
-  pfs_atomic.cc
-  pfs_check.cc
+pfs.h
+pfs_atomic.h
+pfs_column_types.h
+pfs_column_values.h
+pfs_defaults.h
+pfs_engine_table.h
+pfs_events_waits.h
+pfs_global.h
+pfs_instr.h
+pfs_instr_class.h
+pfs_lock.h
+pfs_server.h
+pfs_setup_actor.h
+pfs_setup_object.h
+pfs_stat.h
+pfs_timer.h
+pfs_visitor.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
+table_tiws_by_index_usage.h
+table_tiws_by_table.h
+table_tlws_by_table.h
+ha_perfschema.cc
+pfs.cc
+pfs_atomic.cc
+pfs_check.cc
+pfs_column_values.cc
+pfs_defaults.cc
+pfs_engine_table.cc
+pfs_events_waits.cc
+pfs_global.cc
+pfs_instr.cc
+pfs_instr_class.cc
+pfs_server.cc
+pfs_setup_actor.cc
+pfs_setup_object.cc
+pfs_timer.cc
+pfs_visitor.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
+table_tiws_by_index_usage.cc
+table_tiws_by_table.cc
+table_tlws_by_table.cc
 )
 
 MYSQL_ADD_PLUGIN(perfschema ${PERFSCHEMA_SOURCES} STORAGE_ENGINE DEFAULT STATIC_ONLY)

=== added file 'storage/perfschema/pfs_visitor.cc'
--- a/storage/perfschema/pfs_visitor.cc	1970-01-01 00:00:00 +0000
+++ b/storage/perfschema/pfs_visitor.cc	2011-01-07 16:20:19 +0000
@@ -0,0 +1,454 @@
+/* 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,
+  51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+
+#include "my_global.h"
+#include "my_sys.h"
+#include "pfs_visitor.h"
+#include "pfs_instr.h"
+
+/**
+  @file storage/perfschema/pfs_visitor.cc
+  Visitors (implementation).
+*/
+
+/**
+  @addtogroup Performance_schema_buffers
+  @{
+*/
+
+void PFS_connection_iterator::visit_global(bool with_threads,
+                                           PFS_connection_visitor *visitor)
+{
+  DBUG_ASSERT(visitor != NULL);
+
+  visitor->visit_global();
+
+  if (with_threads)
+  {
+    PFS_thread *pfs= thread_array;
+    PFS_thread *pfs_last= pfs + thread_max;
+    for ( ; pfs < pfs_last; pfs++)
+    {
+      if (pfs->m_lock.is_populated())
+        visitor->visit_thread(pfs);
+    }
+  }
+}
+
+void PFS_instance_iterator::visit_mutex_instances(PFS_mutex_class *klass,
+                                                  PFS_instance_visitor *visitor)
+{
+  DBUG_ASSERT(visitor != NULL);
+
+  visitor->visit_mutex_class(klass);
+
+  if (klass->is_singleton())
+  {
+    PFS_mutex *pfs= sanitize_mutex(klass->m_singleton);
+    if (likely(pfs != NULL))
+    {
+      if (likely(pfs->m_lock.is_populated()))
+      {
+        visitor->visit_mutex(pfs);
+      }
+    }
+  }
+  else
+  {
+    PFS_mutex *pfs= mutex_array;
+    PFS_mutex *pfs_last= pfs + mutex_max;
+    for ( ; pfs < pfs_last; pfs++)
+    {
+      if ((pfs->m_class == klass) && pfs->m_lock.is_populated())
+      {
+        visitor->visit_mutex(pfs);
+      }
+    }
+  }
+}
+
+void PFS_instance_iterator::visit_rwlock_instances(PFS_rwlock_class *klass,
+                                                   PFS_instance_visitor *visitor)
+{
+  DBUG_ASSERT(visitor != NULL);
+
+  visitor->visit_rwlock_class(klass);
+
+  if (klass->is_singleton())
+  {
+    PFS_rwlock *pfs= sanitize_rwlock(klass->m_singleton);
+    if (likely(pfs != NULL))
+    {
+      if (likely(pfs->m_lock.is_populated()))
+      {
+        visitor->visit_rwlock(pfs);
+      }
+    }
+  }
+  else
+  {
+    PFS_rwlock *pfs= rwlock_array;
+    PFS_rwlock *pfs_last= pfs + rwlock_max;
+    for ( ; pfs < pfs_last; pfs++)
+    {
+      if ((pfs->m_class == klass) && pfs->m_lock.is_populated())
+      {
+        visitor->visit_rwlock(pfs);
+      }
+    }
+  }
+}
+
+void PFS_instance_iterator::visit_cond_instances(PFS_cond_class *klass,
+                                                 PFS_instance_visitor *visitor)
+{
+  DBUG_ASSERT(visitor != NULL);
+
+  visitor->visit_cond_class(klass);
+
+  if (klass->is_singleton())
+  {
+    PFS_cond *pfs= sanitize_cond(klass->m_singleton);
+    if (likely(pfs != NULL))
+    {
+      if (likely(pfs->m_lock.is_populated()))
+      {
+        visitor->visit_cond(pfs);
+      }
+    }
+  }
+  else
+  {
+    PFS_cond *pfs= cond_array;
+    PFS_cond *pfs_last= pfs + cond_max;
+    for ( ; pfs < pfs_last; pfs++)
+    {
+      if ((pfs->m_class == klass) && pfs->m_lock.is_populated())
+      {
+        visitor->visit_cond(pfs);
+      }
+    }
+  }
+}
+
+void PFS_instance_iterator::visit_file_instances(PFS_file_class *klass,
+                                                 PFS_instance_visitor *visitor)
+{
+  DBUG_ASSERT(visitor != NULL);
+
+  visitor->visit_file_class(klass);
+
+  if (klass->is_singleton())
+  {
+    PFS_file *pfs= sanitize_file(klass->m_singleton);
+    if (likely(pfs != NULL))
+    {
+      if (likely(pfs->m_lock.is_populated()))
+      {
+        visitor->visit_file(pfs);
+      }
+    }
+  }
+  else
+  {
+    PFS_file *pfs= file_array;
+    PFS_file *pfs_last= pfs + file_max;
+    for ( ; pfs < pfs_last; pfs++)
+    {
+      if ((pfs->m_class == klass) && pfs->m_lock.is_populated())
+      {
+        visitor->visit_file(pfs);
+      }
+    }
+  }
+}
+
+void PFS_object_iterator::visit_all_tables(PFS_object_visitor *visitor)
+{
+  DBUG_ASSERT(visitor != NULL);
+
+  visitor->visit_global();
+
+  /* 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())
+    {
+      visitor->visit_table_share(share);
+    }
+  }
+
+  /* For all the table handles ... */
+  PFS_table *table= table_array;
+  PFS_table *table_last= table_array + table_max;
+  for ( ; table < table_last; table++)
+  {
+    if (table->m_lock.is_populated())
+    {
+      visitor->visit_table(table);
+    }
+  }
+}
+
+void PFS_object_iterator::visit_tables(PFS_table_share *share,
+                                       PFS_object_visitor *visitor)
+{
+  DBUG_ASSERT(visitor != NULL);
+
+  visitor->visit_table_share(share);
+
+  /* For all the table handles ... */
+  PFS_table *table= table_array;
+  PFS_table *table_last= table_array + table_max;
+  for ( ; table < table_last; table++)
+  {
+    if ((table->m_share == share) && table->m_lock.is_populated())
+    {
+      visitor->visit_table(table);
+    }
+  }
+}
+
+void PFS_object_iterator::visit_table_indexes(PFS_table_share *share,
+                                              uint index,
+                                              PFS_object_visitor *visitor)
+{
+  DBUG_ASSERT(visitor != NULL);
+
+  visitor->visit_table_share_index(share, index);
+
+  /* For all the table handles ... */
+  PFS_table *table= table_array;
+  PFS_table *table_last= table_array + table_max;
+  for ( ; table < table_last; table++)
+  {
+    if ((table->m_share == share) && table->m_lock.is_populated())
+    {
+      visitor->visit_table_index(table, index);
+    }
+  }
+}
+
+PFS_connection_wait_visitor
+::PFS_connection_wait_visitor(PFS_instr_class *klass)
+{
+  m_index= klass->m_event_name_index;
+}
+
+PFS_connection_wait_visitor::~PFS_connection_wait_visitor()
+{}
+
+void PFS_connection_wait_visitor::visit_global()
+{
+  /* Sum by instances, not by connection */
+  DBUG_ASSERT(false);
+}
+
+void PFS_connection_wait_visitor::visit_thread(PFS_thread *pfs)
+{
+  m_stat.aggregate(& pfs->m_instr_class_wait_stats[m_index]);
+}
+
+PFS_instance_wait_visitor::PFS_instance_wait_visitor()
+{
+}
+
+PFS_instance_wait_visitor::~PFS_instance_wait_visitor()
+{}
+
+void PFS_instance_wait_visitor::visit_mutex_class(PFS_mutex_class *pfs) 
+{
+  uint index= pfs->m_event_name_index;
+  m_stat.aggregate(& global_instr_class_waits_array[index]);
+}
+
+void PFS_instance_wait_visitor::visit_rwlock_class(PFS_rwlock_class *pfs) 
+{
+  uint index= pfs->m_event_name_index;
+  m_stat.aggregate(& global_instr_class_waits_array[index]);
+}
+
+void PFS_instance_wait_visitor::visit_cond_class(PFS_cond_class *pfs) 
+{
+  uint index= pfs->m_event_name_index;
+  m_stat.aggregate(& global_instr_class_waits_array[index]);
+}
+
+void PFS_instance_wait_visitor::visit_file_class(PFS_file_class *pfs) 
+{
+  uint index= pfs->m_event_name_index;
+  m_stat.aggregate(& global_instr_class_waits_array[index]);
+}
+
+void PFS_instance_wait_visitor::visit_mutex(PFS_mutex *pfs) 
+{
+  m_stat.aggregate(& pfs->m_wait_stat);
+}
+
+void PFS_instance_wait_visitor::visit_rwlock(PFS_rwlock *pfs) 
+{
+  m_stat.aggregate(& pfs->m_wait_stat);
+}
+
+void PFS_instance_wait_visitor::visit_cond(PFS_cond *pfs) 
+{
+  m_stat.aggregate(& pfs->m_wait_stat);
+}
+
+void PFS_instance_wait_visitor::visit_file(PFS_file *pfs) 
+{
+  m_stat.aggregate(& pfs->m_wait_stat);
+}
+
+PFS_table_io_wait_visitor::PFS_table_io_wait_visitor()
+{}
+
+PFS_table_io_wait_visitor::~PFS_table_io_wait_visitor()
+{}
+
+void PFS_table_io_wait_visitor::visit_global()
+{
+  uint index= global_table_io_class.m_event_name_index;
+  m_stat.aggregate(& global_instr_class_waits_array[index]);
+}
+
+void PFS_table_io_wait_visitor::visit_table_share(PFS_table_share *pfs)
+{
+  PFS_table_io_stat io_stat;
+  uint index;
+
+  /* Aggregate index stats */
+  for (index= 0; index < pfs->m_key_count; index++)
+    io_stat.aggregate(& pfs->m_table_stat.m_index_stat[index]);
+
+  /* Aggregate global stats */
+  io_stat.aggregate(& pfs->m_table_stat.m_index_stat[MAX_KEY]);
+
+  io_stat.sum(& m_stat);
+}
+
+void PFS_table_io_wait_visitor::visit_table(PFS_table *pfs)
+{
+  PFS_table_share *safe_share= sanitize_table_share(pfs->m_share);
+
+  if (likely(safe_share != NULL))
+  {
+    PFS_table_io_stat io_stat;
+    uint index;
+
+    /* Aggregate index stats */
+    for (index= 0; index < safe_share->m_key_count; index++)
+      io_stat.aggregate(& pfs->m_table_stat.m_index_stat[index]);
+
+    /* Aggregate global stats */
+    io_stat.aggregate(& pfs->m_table_stat.m_index_stat[MAX_KEY]);
+
+    io_stat.sum(& m_stat);
+  }
+}
+
+PFS_table_io_stat_visitor::PFS_table_io_stat_visitor()
+{}
+
+PFS_table_io_stat_visitor::~PFS_table_io_stat_visitor()
+{}
+
+void PFS_table_io_stat_visitor::visit_table_share(PFS_table_share *pfs)
+{
+  uint index;
+
+  /* Aggregate index stats */
+  for (index= 0; index < pfs->m_key_count; index++)
+    m_stat.aggregate(& pfs->m_table_stat.m_index_stat[index]);
+
+  /* Aggregate global stats */
+  m_stat.aggregate(& pfs->m_table_stat.m_index_stat[MAX_KEY]);
+}
+
+void PFS_table_io_stat_visitor::visit_table(PFS_table *pfs)
+{
+  PFS_table_share *safe_share= sanitize_table_share(pfs->m_share);
+
+  if (likely(safe_share != NULL))
+  {
+    uint index;
+
+    /* Aggregate index stats */
+    for (index= 0; index < safe_share->m_key_count; index++)
+      m_stat.aggregate(& pfs->m_table_stat.m_index_stat[index]);
+
+    /* Aggregate global stats */
+    m_stat.aggregate(& pfs->m_table_stat.m_index_stat[MAX_KEY]);
+  }
+}
+
+PFS_index_io_stat_visitor::PFS_index_io_stat_visitor()
+{}
+
+PFS_index_io_stat_visitor::~PFS_index_io_stat_visitor()
+{}
+
+void PFS_index_io_stat_visitor::visit_table_share_index(PFS_table_share *pfs, uint index)
+{
+  m_stat.aggregate(& pfs->m_table_stat.m_index_stat[index]);
+}
+
+void PFS_index_io_stat_visitor::visit_table_index(PFS_table *pfs, uint index)
+{
+  m_stat.aggregate(& pfs->m_table_stat.m_index_stat[index]);
+}
+
+PFS_table_lock_wait_visitor::PFS_table_lock_wait_visitor()
+{}
+
+PFS_table_lock_wait_visitor::~PFS_table_lock_wait_visitor()
+{}
+
+void PFS_table_lock_wait_visitor::visit_global()
+{
+  uint index= global_table_lock_class.m_event_name_index;
+  m_stat.aggregate(& global_instr_class_waits_array[index]);
+}
+
+void PFS_table_lock_wait_visitor::visit_table_share(PFS_table_share *pfs)
+{
+  pfs->m_table_stat.sum_lock(& m_stat);
+}
+
+void PFS_table_lock_wait_visitor::visit_table(PFS_table *pfs)
+{
+  pfs->m_table_stat.sum_lock(& m_stat);
+}
+
+PFS_table_lock_stat_visitor::PFS_table_lock_stat_visitor()
+{}
+
+PFS_table_lock_stat_visitor::~PFS_table_lock_stat_visitor()
+{}
+
+void PFS_table_lock_stat_visitor::visit_table_share(PFS_table_share *pfs)
+{
+  m_stat.aggregate(& pfs->m_table_stat.m_lock_stat);
+}
+
+void PFS_table_lock_stat_visitor::visit_table(PFS_table *pfs)
+{
+  m_stat.aggregate(& pfs->m_table_stat.m_lock_stat);
+}
+
+/** @} */
+

=== added file 'storage/perfschema/pfs_visitor.h'
--- a/storage/perfschema/pfs_visitor.h	1970-01-01 00:00:00 +0000
+++ b/storage/perfschema/pfs_visitor.h	2011-01-07 16:20:19 +0000
@@ -0,0 +1,313 @@
+/* Copyright (c) 2010, 2011 Oracle and/or its affiliates. All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; version 2 of the License.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software Foundation,
+  51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+
+#ifndef PFS_VISITOR_H
+#define PFS_VISITOR_H
+
+#include "pfs_stat.h"
+
+/**
+  @file storage/perfschema/pfs_visitor.h
+  Visitors (declarations).
+*/
+
+/**
+  @addtogroup Performance_schema_buffers
+  @{
+*/
+
+struct PFS_thread;
+struct PFS_instr_class;
+struct PFS_mutex_class;
+struct PFS_rwlock_class;
+struct PFS_cond_class;
+struct PFS_file_class;
+struct PFS_table_share;
+struct PFS_mutex;
+struct PFS_rwlock;
+struct PFS_cond;
+struct PFS_file;
+struct PFS_table;
+struct PFS_stage_class;
+struct PFS_statement_class;
+
+/**
+  Interface class to visit groups of connections.
+  @sa PFS_connection_iterator
+*/
+class PFS_connection_visitor
+{
+public:
+  PFS_connection_visitor() {}
+  virtual ~PFS_connection_visitor() {}
+  /** Visit all connections. */
+  virtual void visit_global() {}
+  /** Visit all a thread. */
+  virtual void visit_thread(PFS_thread *pfs) {}
+};
+
+/**
+  Iterator over groups of connections.
+  @sa PFS_connection_visitor
+*/
+class PFS_connection_iterator
+{
+public:
+  /**
+    Visit all connections.
+    @param with_threads when true, visit also all threads.
+    @param visitor the visitor to call
+  */
+  static void visit_global(bool with_threads,
+                           PFS_connection_visitor *visitor);
+  /**
+    Visit a thread or connection.
+    @param thread the thread to visit.
+    @param visitor the visitor to call
+  */
+  static inline void visit_thread(PFS_thread *thread,
+                                  PFS_connection_visitor *visitor)
+  { visitor->visit_thread(thread); }
+};
+
+/**
+  Interface class to visit groups of instrumentation point instances.
+  @sa PFS_instance_iterator
+*/
+class PFS_instance_visitor
+{
+public:
+  PFS_instance_visitor() {}
+  virtual ~PFS_instance_visitor() {}
+  /** Visit a mutex class. */
+  virtual void visit_mutex_class(PFS_mutex_class *pfs) {}
+  /** Visit a rwlock class. */
+  virtual void visit_rwlock_class(PFS_rwlock_class *pfs) {}
+  /** Visit a cond class. */
+  virtual void visit_cond_class(PFS_cond_class *pfs) {}
+  /** Visit a file class. */
+  virtual void visit_file_class(PFS_file_class *pfs) {}
+  /** Visit a mutex instance. */
+  virtual void visit_mutex(PFS_mutex *pfs) {}
+  /** Visit a rwlock instance. */
+  virtual void visit_rwlock(PFS_rwlock *pfs) {}
+  /** Visit a cond instance. */
+  virtual void visit_cond(PFS_cond *pfs) {}
+  /** Visit a file instance. */
+  virtual void visit_file(PFS_file *pfs) {}
+};
+
+/**
+  Iterator over groups of instrumentation point instances.
+  @sa PFS_instance_visitor
+*/
+class PFS_instance_iterator
+{
+public:
+  /**
+    Visit a mutex class and related instances.
+    @param klass the klass to visit.
+    @param visitor the visitor to call
+  */
+  static void visit_mutex_instances(PFS_mutex_class *klass,
+                                    PFS_instance_visitor *visitor);
+  /**
+    Visit a rwlock class and related instances.
+    @param klass the klass to visit.
+    @param visitor the visitor to call
+  */
+  static void visit_rwlock_instances(PFS_rwlock_class *klass,
+                                     PFS_instance_visitor *visitor);
+  /**
+    Visit a cond class and related instances.
+    @param klass the klass to visit.
+    @param visitor the visitor to call
+  */
+  static void visit_cond_instances(PFS_cond_class *klass,
+                                   PFS_instance_visitor *visitor);
+  /**
+    Visit a file class and related instances.
+    @param klass the klass to visit.
+    @param visitor the visitor to call
+  */
+  static void visit_file_instances(PFS_file_class *klass,
+                                   PFS_instance_visitor *visitor);
+};
+
+/**
+  Interface class to visit groups of SQL objects.
+  @sa PFS_object_iterator
+*/
+class PFS_object_visitor
+{
+public:
+  PFS_object_visitor() {}
+  virtual ~PFS_object_visitor() {}
+  /** Visit global data. */
+  virtual void visit_global() {}
+  /** Visit a table share. */
+  virtual void visit_table_share(PFS_table_share *pfs) {}
+  /** Visit a table share index. */
+  virtual void visit_table_share_index(PFS_table_share *pfs, uint index) {}
+  /** Visit a table. */
+  virtual void visit_table(PFS_table *pfs) {}
+  /** Visit a table index. */
+  virtual void visit_table_index(PFS_table *pfs, uint index) {}
+};
+
+/**
+  Iterator over groups of SQL objects.
+  @sa PFS_object_visitor
+*/
+class PFS_object_iterator
+{
+public:
+  /** Visit all tables and related handles. */
+  static void visit_all_tables(PFS_object_visitor *visitor);
+  /** Visit a table and related table handles. */
+  static void visit_tables(PFS_table_share *share,
+                           PFS_object_visitor *visitor);
+  /** Visit a table index and related table handles indexes. */
+  static void visit_table_indexes(PFS_table_share *share,
+                                  uint index,
+                                  PFS_object_visitor *visitor);
+};
+
+/**
+  A concrete connection visitor that aggregates
+  wait statistics.
+*/
+class PFS_connection_wait_visitor : public PFS_connection_visitor
+{
+public:
+  /** Constructor. */
+  PFS_connection_wait_visitor(PFS_instr_class *klass);
+  virtual ~PFS_connection_wait_visitor();
+  virtual void visit_global();
+  virtual void visit_thread(PFS_thread *pfs);
+
+  /** EVENT_NAME instrument index. */
+  uint m_index;
+  /** Wait statistic collected. */
+  PFS_single_stat m_stat;
+};
+
+/**
+  A concrete instance visitor that aggregates
+  wait statistics.
+*/
+class PFS_instance_wait_visitor : public PFS_instance_visitor
+{
+public:
+  PFS_instance_wait_visitor();
+  virtual ~PFS_instance_wait_visitor();
+  virtual void visit_mutex_class(PFS_mutex_class *pfs);
+  virtual void visit_rwlock_class(PFS_rwlock_class *pfs);
+  virtual void visit_cond_class(PFS_cond_class *pfs);
+  virtual void visit_file_class(PFS_file_class *pfs);
+  virtual void visit_mutex(PFS_mutex *pfs);
+  virtual void visit_rwlock(PFS_rwlock *pfs);
+  virtual void visit_cond(PFS_cond *pfs);
+  virtual void visit_file(PFS_file *pfs);
+
+  /** Wait statistic collected. */
+  PFS_single_stat m_stat;
+};
+
+/**
+  A concrete object visitor that aggregates
+  table io wait statistics.
+*/
+class PFS_table_io_wait_visitor : public PFS_object_visitor
+{
+public:
+  PFS_table_io_wait_visitor();
+  virtual ~PFS_table_io_wait_visitor();
+  virtual void visit_global();
+  virtual void visit_table_share(PFS_table_share *pfs);
+  virtual void visit_table(PFS_table *pfs);
+
+  /** Table io wait statistic collected. */
+  PFS_single_stat m_stat;
+};
+
+/**
+  A concrete object visitor that aggregates
+  table io statistics.
+*/
+class PFS_table_io_stat_visitor : public PFS_object_visitor
+{
+public:
+  PFS_table_io_stat_visitor();
+  virtual ~PFS_table_io_stat_visitor();
+  virtual void visit_table_share(PFS_table_share *pfs);
+  virtual void visit_table(PFS_table *pfs);
+
+  /** Table io statistic collected. */
+  PFS_table_io_stat m_stat;
+};
+
+/**
+  A concrete object visitor that aggregates
+  index io statistics.
+*/
+class PFS_index_io_stat_visitor : public PFS_object_visitor
+{
+public:
+  PFS_index_io_stat_visitor();
+  virtual ~PFS_index_io_stat_visitor();
+  virtual void visit_table_share_index(PFS_table_share *pfs, uint index);
+  virtual void visit_table_index(PFS_table *pfs, uint index);
+
+  /** Index io statistic collected. */
+  PFS_table_io_stat m_stat;
+};
+
+/**
+  A concrete object visitor that aggregates
+  table lock wait statistics.
+*/
+class PFS_table_lock_wait_visitor : public PFS_object_visitor
+{
+public:
+  PFS_table_lock_wait_visitor();
+  virtual ~PFS_table_lock_wait_visitor();
+  virtual void visit_global();
+  virtual void visit_table_share(PFS_table_share *pfs);
+  virtual void visit_table(PFS_table *pfs);
+
+  /** Table lock wait statistic collected. */
+  PFS_single_stat m_stat;
+};
+
+/**
+  A concrete object visitor that aggregates
+  table lock statistics.
+*/
+class PFS_table_lock_stat_visitor : public PFS_object_visitor
+{
+public:
+  PFS_table_lock_stat_visitor();
+  virtual ~PFS_table_lock_stat_visitor();
+  virtual void visit_table_share(PFS_table_share *pfs);
+  virtual void visit_table(PFS_table *pfs);
+
+  /** Table lock statistic collected. */
+  PFS_table_lock_stat m_stat;
+};
+
+/** @} */
+#endif
+

=== modified file 'storage/perfschema/table_ews_by_thread_by_event_name.cc'
--- a/storage/perfschema/table_ews_by_thread_by_event_name.cc	2010-11-15 09:58:20 +0000
+++ b/storage/perfschema/table_ews_by_thread_by_event_name.cc	2011-01-07 16:20:19 +0000
@@ -25,6 +25,7 @@
 #include "pfs_column_values.h"
 #include "table_ews_by_thread_by_event_name.h"
 #include "pfs_global.h"
+#include "pfs_visitor.h"
 
 THR_LOCK table_ews_by_thread_by_event_name::m_table_lock;
 
@@ -302,26 +303,25 @@ 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);
+  m_row.m_event_name.make_row(klass);
+
+  PFS_connection_wait_visitor visitor(klass);
+  PFS_connection_iterator::visit_thread(thread, & visitor);
+
+  if (! thread->m_lock.end_optimistic_lock(&lock))
+    return;
+
+  m_row_exists= true;
 
-  if (thread->m_lock.end_optimistic_lock(&lock))
-    m_row_exists= true;
+  time_normalizer *normalizer= time_normalizer::get(wait_timer);
+  m_row.m_stat.set(normalizer, & visitor.m_stat);
 }
 
 int table_ews_by_thread_by_event_name
@@ -345,26 +345,12 @@ int table_ews_by_thread_by_event_name
       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);
+      case 1: /* EVENT_NAME */
+        m_row.m_event_name.set_field(f);
         break;
-      case 6: /* MAX */
-        set_field_ulonglong(f, m_row.m_stat.m_max);
+      default: /* 2, ... COUNT/SUM/MIN/AVG/MAX */
+        m_row.m_stat.set_field(f->field_index - 2, f);
         break;
-      default:
-        DBUG_ASSERT(false);
       }
     }
   }

=== modified file 'storage/perfschema/table_ews_by_thread_by_event_name.h'
--- a/storage/perfschema/table_ews_by_thread_by_event_name.h	2010-09-23 16:08:54 +0000
+++ b/storage/perfschema/table_ews_by_thread_by_event_name.h	2011-01-07 16:20:19 +0000
@@ -41,9 +41,7 @@ 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;
+  PFS_event_name_row m_event_name;
   /** Columns COUNT_STAR, SUM/MIN/AVG/MAX TIMER_WAIT. */
   PFS_stat_row m_stat;
 };

=== modified file 'storage/perfschema/table_ews_global_by_event_name.cc'
--- a/storage/perfschema/table_ews_global_by_event_name.cc	2010-12-09 16:17:13 +0000
+++ b/storage/perfschema/table_ews_global_by_event_name.cc	2011-01-07 16:20:19 +0000
@@ -27,6 +27,7 @@
 #include "pfs_global.h"
 #include "pfs_instr.h"
 #include "pfs_timer.h"
+#include "pfs_visitor.h"
 
 THR_LOCK table_ews_global_by_event_name::m_table_lock;
 
@@ -245,270 +246,81 @@ table_ews_global_by_event_name::rnd_pos(
   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];
+  m_row.m_event_name.make_row(klass);
 
-  if (klass->is_singleton())
-  {
-    PFS_mutex *pfs= sanitize_mutex(klass->m_singleton);
-    if (likely(pfs != NULL))
-    {
-      if (likely(pfs->m_lock.is_populated()))
-      {
-        cumulated_stat.aggregate(& pfs->m_wait_stat);
-      }
-    }
-  }
-  else
-  {
-    /* 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);
-      }
-    }
-  }
+  PFS_instance_wait_visitor visitor;
+  PFS_instance_iterator::visit_mutex_instances(klass, & visitor);
 
   time_normalizer *normalizer= time_normalizer::get(wait_timer);
-  m_row.m_stat.set(normalizer, &cumulated_stat);
+  m_row.m_stat.set(normalizer, & visitor.m_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];
+  m_row.m_event_name.make_row(klass);
 
-  if (klass->is_singleton())
-  {
-    PFS_rwlock *pfs= sanitize_rwlock(klass->m_singleton);
-    if (likely(pfs != NULL))
-    {
-      if (likely(pfs->m_lock.is_populated()))
-      {
-        cumulated_stat.aggregate(& pfs->m_wait_stat);
-      }
-    }
-  }
-  else
-  {
-    /* 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);
-      }
-    }
-  }
+  PFS_instance_wait_visitor visitor;
+  PFS_instance_iterator::visit_rwlock_instances(klass, & visitor);
 
   time_normalizer *normalizer= time_normalizer::get(wait_timer);
-  m_row.m_stat.set(normalizer, &cumulated_stat);
+  m_row.m_stat.set(normalizer, & visitor.m_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];
+  m_row.m_event_name.make_row(klass);
 
-  if (klass->is_singleton())
-  {
-    PFS_cond *pfs= sanitize_cond(klass->m_singleton);
-    if (likely(pfs != NULL))
-    {
-      if (likely(pfs->m_lock.is_populated()))
-      {
-        cumulated_stat.aggregate(& pfs->m_wait_stat);
-      }
-    }
-  }
-  else
-  {
-    /* 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);
-      }
-    }
-  }
+  PFS_instance_wait_visitor visitor;
+  PFS_instance_iterator::visit_cond_instances(klass, & visitor);
 
   time_normalizer *normalizer= time_normalizer::get(wait_timer);
-  m_row.m_stat.set(normalizer, &cumulated_stat);
+  m_row.m_stat.set(normalizer, & visitor.m_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];
-
-  if (klass->is_singleton())
-  {
-    PFS_file *pfs= sanitize_file(klass->m_singleton);
-    if (likely(pfs != NULL))
-    {
-      if (likely(pfs->m_lock.is_populated()))
-      {
-        cumulated_stat.aggregate(& pfs->m_wait_stat);
-      }
-    }
-  }
-  else
-  {
-    /* 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);
-      }
-    }
-  }
+  m_row.m_event_name.make_row(klass);
 
-  /* FIXME: */
-  /* For all the file handles ... */
+  PFS_instance_wait_visitor visitor;
+  PFS_instance_iterator::visit_file_instances(klass, & visitor);
 
   time_normalizer *normalizer= time_normalizer::get(wait_timer);
-  m_row.m_stat.set(normalizer, &cumulated_stat);
+  m_row.m_stat.set(normalizer, & visitor.m_stat);
   m_row_exists= true;
 }
 
 void table_ews_global_by_event_name
 ::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]);
-    }
-  }
-
-  /* For all the table handles ... */
-  PFS_table *table= table_array;
-  PFS_table *table_last= table_array + table_max;
-  for ( ; table < table_last; table++)
-  {
-    if (table->m_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]);
+  m_row.m_event_name.make_row(klass);
 
-        /* Aggregate global stats */
-        cumulated_io_stat.aggregate(& table->m_table_stat.m_index_stat[MAX_KEY]);
-      }
-    }
-  }
-
-  cumulated_io_stat.sum(& cumulated_stat);
+  PFS_table_io_wait_visitor visitor;
+  PFS_object_iterator::visit_all_tables(& visitor);
 
   time_normalizer *normalizer= time_normalizer::get(wait_timer);
-  m_row.m_stat.set(normalizer, &cumulated_stat);
+  m_row.m_stat.set(normalizer, & visitor.m_stat);
   m_row_exists= true;
 }
 
 void table_ews_global_by_event_name
 ::make_table_lock_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];
-
-  /* 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 lock stats */
-      share->m_table_stat.sum_lock(& cumulated_stat);
-    }
-  }
-
-  /* For all the table handles ... */
-  PFS_table *table= table_array;
-  PFS_table *table_last= table_array + table_max;
-  for ( ; table < table_last; table++)
-  {
-    if (table->m_lock.is_populated())
-    {
-      PFS_table_share *safe_share= sanitize_table_share(table->m_share);
-
-      if (likely(safe_share != NULL))
-      {
-        /* Aggregate lock stats */
-        table->m_table_stat.sum_lock(& cumulated_stat);
-      }
-    }
-  }
+  m_row.m_event_name.make_row(klass);
 
+  PFS_table_lock_wait_visitor visitor;
+  PFS_object_iterator::visit_all_tables(& visitor);
+  
   time_normalizer *normalizer= time_normalizer::get(wait_timer);
-  m_row.m_stat.set(normalizer, &cumulated_stat);
+  m_row.m_stat.set(normalizer, & visitor.m_stat);
   m_row_exists= true;
 }
 
@@ -530,26 +342,12 @@ int table_ews_global_by_event_name
     {
       switch(f->field_index)
       {
-      case 0: /* 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_stat.m_count);
-        break;
-      case 2: /* SUM */
-        set_field_ulonglong(f, m_row.m_stat.m_sum);
-        break;
-      case 3: /* MIN */
-        set_field_ulonglong(f, m_row.m_stat.m_min);
-        break;
-      case 4: /* AVG */
-        set_field_ulonglong(f, m_row.m_stat.m_avg);
+      case 0: /* EVENT_NAME */
+        m_row.m_event_name.set_field(f);
         break;
-      case 5: /* MAX */
-        set_field_ulonglong(f, m_row.m_stat.m_max);
+      default: /* 1, ... COUNT/SUM/MIN/AVG/MAX */
+        m_row.m_stat.set_field(f->field_index - 1, f);
         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-12-09 16:17:13 +0000
+++ b/storage/perfschema/table_ews_global_by_event_name.h	2011-01-07 16:20:19 +0000
@@ -39,9 +39,7 @@
 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;
+  PFS_event_name_row m_event_name;
   /** Columns COUNT_STAR, SUM/MIN/AVG/MAX TIMER_WAIT. */
   PFS_stat_row m_stat;
 };

=== modified file 'storage/perfschema/table_helper.cc'
--- a/storage/perfschema/table_helper.cc	2010-09-23 16:12:54 +0000
+++ b/storage/perfschema/table_helper.cc	2011-01-07 16:20:19 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -23,6 +23,82 @@
 #include "pfs_engine_table.h"
 #include "table_helper.h"
 
+int PFS_object_row::make_row(PFS_table_share *pfs)
+{
+  m_object_type= pfs->get_object_type();
+
+  m_schema_name_length= pfs->m_schema_name_length;
+  if (m_schema_name_length > sizeof(m_schema_name))
+    return 1;
+  if (m_schema_name_length > 0)
+    memcpy(m_schema_name, pfs->m_schema_name, sizeof(m_schema_name));
+
+  m_object_name_length= pfs->m_table_name_length;
+  if (m_object_name_length > sizeof(m_object_name))
+    return 1;
+  if (m_object_name_length > 0)
+    memcpy(m_object_name, pfs->m_table_name, sizeof(m_object_name));
+
+  return 0;
+}
+
+void PFS_object_row::set_field(uint index, Field *f)
+{
+  switch(index)
+  {
+    case 0: /* OBJECT_TYPE */
+      set_field_object_type(f, m_object_type);
+      break;
+    case 1: /* SCHEMA_NAME */
+      PFS_engine_table::set_field_varchar_utf8(f, m_schema_name, m_schema_name_length);
+      break;
+    case 2: /* OBJECT_NAME */
+      PFS_engine_table::set_field_varchar_utf8(f, m_object_name, m_object_name_length);
+      break;
+    default:
+      DBUG_ASSERT(false);
+  }
+}
+
+int PFS_index_row::make_row(PFS_table_share *pfs, uint table_index)
+{
+  if (m_object_row.make_row(pfs))
+    return 1;
+
+  if (table_index < MAX_KEY)
+  {
+    PFS_table_key *key= &pfs->m_keys[table_index];
+    m_index_name_length= key->m_name_length;
+    if (m_index_name_length > sizeof(m_index_name))
+      return 1;
+    memcpy(m_index_name, key->m_name, sizeof(m_index_name));
+  }
+  else
+    m_index_name_length= 0;
+
+  return 0;
+}
+
+void PFS_index_row::set_field(uint index, Field *f)
+{
+  switch(index)
+  {
+    case 0: /* OBJECT_TYPE */
+    case 1: /* SCHEMA_NAME */
+    case 2: /* OBJECT_NAME */
+      m_object_row.set_field(index, f);
+      break;
+    case 3: /* INDEX_NAME */
+      if (m_index_name_length > 0)
+        PFS_engine_table::set_field_varchar_utf8(f, m_index_name, m_index_name_length);
+      else
+        f->set_null();
+      break;
+    default:
+      DBUG_ASSERT(false);
+  }
+}
+
 void set_field_object_type(Field *f, enum_object_type object_type)
 {
   switch (object_type)

=== modified file 'storage/perfschema/table_helper.h'
--- a/storage/perfschema/table_helper.h	2010-12-09 16:17:13 +0000
+++ b/storage/perfschema/table_helper.h	2011-01-07 16:20:19 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -19,6 +19,8 @@
 #include "pfs_column_types.h"
 #include "pfs_stat.h"
 #include "pfs_timer.h"
+#include "pfs_engine_table.h"
+#include "pfs_instr_class.h"
 
 /**
   @file storage/perfschema/table_helper.h
@@ -53,6 +55,64 @@ struct PFS_object_view_constants
   static const uint VIEW_FUNCTION= 4;
 };
 
+/** Row fragment for column EVENT_NAME. */
+struct PFS_event_name_row
+{
+  /** Column EVENT_NAME. */
+  const char *m_name;
+  /** Length in bytes of @c m_name. */
+  uint m_name_length;
+
+  /** Build a row from a memory buffer. */
+  inline void make_row(PFS_instr_class *pfs)
+  {
+    m_name= pfs->m_name;
+    m_name_length= pfs->m_name_length;
+  }
+
+  /** Set a table field from the row. */
+  inline void set_field(Field *f)
+  {
+    PFS_engine_table::set_field_varchar_utf8(f, m_name, m_name_length);
+  }
+};
+
+/** Row fragment for columns OBJECT_TYPE, SCHEMA_NAME, OBJECT_NAME. */
+struct PFS_object_row
+{
+  /** 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;
+
+  /** Build a row from a memory buffer. */
+  int make_row(PFS_table_share *pfs);
+  /** Set a table field from the row. */
+  void set_field(uint index, Field *f);
+};
+
+/** Row fragment for columns OBJECT_TYPE, SCHEMA_NAME, OBJECT_NAME, INDEX_NAME. */
+struct PFS_index_row
+{
+  PFS_object_row m_object_row;
+  /** Column INDEX_NAME. */
+  char m_index_name[NAME_LEN];
+  /** Length in bytes of @c m_index_name. */
+  uint m_index_name_length;
+
+  /** Build a row from a memory buffer. */
+  int make_row(PFS_table_share *pfs, uint table_index);
+  /** Set a table field from the row. */
+  void set_field(uint index, Field *f);
+};
+
+/** Row fragment for single statistics columns (COUNT, SUM, MIN, AVG, MAX) */
 struct PFS_stat_row
 {
   /** Column COUNT_STAR. */
@@ -66,6 +126,7 @@ struct PFS_stat_row
   /** Column MAX_TIMER_WAIT. */
   ulonglong m_max;
 
+  /** Build a row from a memory buffer. */
   inline void set(time_normalizer *normalizer, const PFS_single_stat *stat)
   {
     m_count= stat->m_count;
@@ -75,7 +136,7 @@ struct PFS_stat_row
       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);
+      m_avg= normalizer->wait_to_pico(stat->m_sum / m_count);
     }
     else
     {
@@ -85,8 +146,34 @@ struct PFS_stat_row
       m_max= 0;
     }
   }
+
+  /** Set a table field from the row. */
+  void set_field(uint index, Field *f)
+  {
+    switch (index)
+    {
+      case 0: /* COUNT */
+        PFS_engine_table::set_field_ulonglong(f, m_count);
+        break;
+      case 1: /* SUM */
+        PFS_engine_table::set_field_ulonglong(f, m_sum);
+        break;
+      case 2: /* MIN */
+        PFS_engine_table::set_field_ulonglong(f, m_min);
+        break;
+      case 3: /* AVG */
+        PFS_engine_table::set_field_ulonglong(f, m_avg);
+        break;
+      case 4: /* MAX */
+        PFS_engine_table::set_field_ulonglong(f, m_max);
+        break;
+      default:
+        DBUG_ASSERT(false);
+    }
+  }
 };
 
+/** Row fragment for table io statistics columns. */
 struct PFS_table_io_stat_row
 {
   PFS_stat_row m_all;
@@ -97,6 +184,7 @@ struct PFS_table_io_stat_row
   PFS_stat_row m_update;
   PFS_stat_row m_delete;
 
+  /** Build a row from a memory buffer. */
   inline void set(time_normalizer *normalizer, const PFS_table_io_stat *stat)
   {
     PFS_single_stat all_read;
@@ -124,6 +212,7 @@ struct PFS_table_io_stat_row
   }
 };
 
+/** Row fragment for table lock statistics columns. */
 struct PFS_table_lock_stat_row
 {
   PFS_stat_row m_all;
@@ -141,6 +230,7 @@ struct PFS_table_lock_stat_row
   PFS_stat_row m_write_normal;
   PFS_stat_row m_write_external;
 
+  /** Build a row from a memory buffer. */
   inline void set(time_normalizer *normalizer, const PFS_table_lock_stat *stat)
   {
     PFS_single_stat all_read;

=== modified file 'storage/perfschema/table_tiws_by_index_usage.cc'
--- a/storage/perfschema/table_tiws_by_index_usage.cc	2010-12-09 16:17:13 +0000
+++ b/storage/perfschema/table_tiws_by_index_usage.cc	2011-01-07 16:20:19 +0000
@@ -25,6 +25,7 @@
 #include "pfs_column_values.h"
 #include "table_tiws_by_index_usage.h"
 #include "pfs_global.h"
+#include "pfs_visitor.h"
 
 THR_LOCK table_tiws_by_index_usage::m_table_lock;
 
@@ -330,53 +331,24 @@ table_tiws_by_index_usage::rnd_pos(const
 void table_tiws_by_index_usage::make_row(PFS_table_share *share, uint index)
 {
   pfs_lock lock;
-  PFS_table_io_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;
-  if (index < MAX_KEY)
-  {
-    PFS_table_key *key= &share->m_keys[index];
-    memcpy(m_row.m_index_name, key->m_name, key->m_name_length);
-    m_row.m_index_name_length= key->m_name_length;
-  }
-  else
-    m_row.m_index_name_length= 0;
+  if (m_row.m_index.make_row(share, index))
+    return;
 
-  cumulated_stat= share->m_table_stat.m_index_stat[index];
+  PFS_index_io_stat_visitor visitor;
+  PFS_object_iterator::visit_table_indexes(share, index, & visitor);
 
   if (! share->m_lock.end_optimistic_lock(&lock))
     return;
 
   m_row_exists= true;
 
-  if (share->get_refcount() > 1)
-  {
-    /* 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.
-        */
-        cumulated_stat.aggregate(&table->m_table_stat.m_index_stat[index]);
-      }
-    }
-  }
-
   time_normalizer *normalizer= time_normalizer::get(wait_timer);
-  m_row.m_stat.set(normalizer, &cumulated_stat);
+  m_row.m_stat.set(normalizer, & visitor.m_stat);
 }
 
 int table_tiws_by_index_usage::read_row_values(TABLE *table,
@@ -400,22 +372,10 @@ int table_tiws_by_index_usage::read_row_
       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: /* INDEX_NAME */
-        if (m_row.m_index_name_length > 0)
-          set_field_varchar_utf8(f, m_row.m_index_name,
-                                 m_row.m_index_name_length);
-        else
-          f->set_null();
+        m_row.m_index.set_field(f->field_index, f);
         break;
       case 4: /* COUNT_STAR */
         set_field_ulonglong(f, m_row.m_stat.m_all.m_count);

=== modified file 'storage/perfschema/table_tiws_by_index_usage.h'
--- a/storage/perfschema/table_tiws_by_index_usage.h	2010-12-09 16:17:13 +0000
+++ b/storage/perfschema/table_tiws_by_index_usage.h	2011-01-07 16:20:19 +0000
@@ -38,20 +38,8 @@
 */
 struct row_tiws_by_index_usage
 {
-  /** Column OBJECT_TYPE. */
-  enum_object_type m_object_type;
-  /** Column SCHEMA_NAME. */
-  char m_schema_name[NAME_LEN];
-  /** Length in bytes of @c m_schema_name. */
-  uint m_schema_name_length;
-  /** Column OBJECT_NAME. */
-  char m_object_name[NAME_LEN];
-  /** Length in bytes of @c m_object_name. */
-  uint m_object_name_length;
-  /** Column INDEX_NAME. */
-  char m_index_name[NAME_LEN];
-  /** Length in bytes of @c m_index_name. */
-  uint m_index_name_length;
+  /** Column OBJECT_TYPE, SCHEMA_NAME, OBJECT_NAME, INDEX_NAME. */
+  PFS_index_row m_index;
   /** Columns COUNT/SUM/MIN/AVG/MAX (+_READ, +WRITE). */
   PFS_table_io_stat_row m_stat;
 };

=== modified file 'storage/perfschema/table_tiws_by_table.cc'
--- a/storage/perfschema/table_tiws_by_table.cc	2010-12-09 16:17:13 +0000
+++ b/storage/perfschema/table_tiws_by_table.cc	2011-01-07 16:20:19 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -25,6 +25,7 @@
 #include "pfs_column_values.h"
 #include "table_tiws_by_table.h"
 #include "pfs_global.h"
+#include "pfs_visitor.h"
 
 THR_LOCK table_tiws_by_table::m_table_lock;
 
@@ -307,57 +308,24 @@ table_tiws_by_table::rnd_pos(const void 
 void table_tiws_by_table::make_row(PFS_table_share *share)
 {
   pfs_lock lock;
-  PFS_table_io_stat cumulated_stat;
-  uint index;
 
   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;
-
-  /* Aggregate index stats */
-  for (index= 0; index <= share->m_key_count; index++)
-    cumulated_stat.aggregate(& share->m_table_stat.m_index_stat[index]);
+  if (m_row.m_object.make_row(share))
+    return;
 
-  /** Aggregate global stats */
-  cumulated_stat.aggregate(& share->m_table_stat.m_index_stat[MAX_KEY]);
+  PFS_table_io_stat_visitor visitor;
+  PFS_object_iterator::visit_tables(share, & visitor);
 
   if (! share->m_lock.end_optimistic_lock(&lock))
     return;
 
   m_row_exists= true;
 
-  if (share->get_refcount() > 1)
-  {
-    /* 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.
-        */
-
-        /* Aggregate index stats */
-        for (index= 0; index <= share->m_key_count; index++)
-          cumulated_stat.aggregate(& table->m_table_stat.m_index_stat[index]);
-
-        /** Aggregate global stats */
-        cumulated_stat.aggregate(& table->m_table_stat.m_index_stat[MAX_KEY]);
-      }
-    }
-  }
-
   time_normalizer *normalizer= time_normalizer::get(wait_timer);
-  m_row.m_stat.set(normalizer, &cumulated_stat);
+  m_row.m_stat.set(normalizer, &visitor.m_stat);
 }
 
 int table_tiws_by_table::read_row_values(TABLE *table,
@@ -381,15 +349,9 @@ int table_tiws_by_table::read_row_values
       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);
+        m_row.m_object.set_field(f->field_index, f);
         break;
       case 3: /* COUNT_STAR */
         set_field_ulonglong(f, m_row.m_stat.m_all.m_count);

=== modified file 'storage/perfschema/table_tiws_by_table.h'
--- a/storage/perfschema/table_tiws_by_table.h	2010-12-09 16:17:13 +0000
+++ b/storage/perfschema/table_tiws_by_table.h	2011-01-07 16:20:19 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -38,16 +38,8 @@
 */
 struct row_tiws_by_table
 {
-  /** Column OBJECT_TYPE. */
-  enum_object_type m_object_type;
-  /** Column SCHEMA_NAME. */
-  char m_schema_name[NAME_LEN];
-  /** Length in bytes of @c m_schema_name. */
-  uint m_schema_name_length;
-  /** Column OBJECT_NAME. */
-  char m_object_name[NAME_LEN];
-  /** Length in bytes of @c m_object_name. */
-  uint m_object_name_length;
+  /** Column OBJECT_TYPE, SCHEMA_NAME, OBJECT_NAME. */
+  PFS_object_row m_object;
   /** Columns COUNT/SUM/MIN/AVG/MAX (+_READ, +WRITE). */
   PFS_table_io_stat_row m_stat;
 };

=== modified file 'storage/perfschema/table_tlws_by_table.cc'
--- a/storage/perfschema/table_tlws_by_table.cc	2010-12-09 16:17:13 +0000
+++ b/storage/perfschema/table_tlws_by_table.cc	2011-01-07 16:20:19 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -25,6 +25,7 @@
 #include "pfs_column_values.h"
 #include "table_tlws_by_table.h"
 #include "pfs_global.h"
+#include "pfs_visitor.h"
 
 THR_LOCK table_tlws_by_table::m_table_lock;
 
@@ -482,48 +483,24 @@ table_tlws_by_table::rnd_pos(const void 
 void table_tlws_by_table::make_row(PFS_table_share *share)
 {
   pfs_lock lock;
-  PFS_table_lock_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;
+  if (m_row.m_object.make_row(share))
+    return;
 
-  /** Aggregate global stats */
-  cumulated_stat.aggregate(& share->m_table_stat.m_lock_stat);
+  PFS_table_lock_stat_visitor visitor;
+  PFS_object_iterator::visit_tables(share, & visitor);
 
   if (! share->m_lock.end_optimistic_lock(&lock))
     return;
 
   m_row_exists= true;
 
-  if (share->get_refcount() > 1)
-  {
-    /* 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.
-        */
-
-        /** Aggregate global stats */
-        cumulated_stat.aggregate(& table->m_table_stat.m_lock_stat);
-      }
-    }
-  }
-
   time_normalizer *normalizer= time_normalizer::get(wait_timer);
-  m_row.m_stat.set(normalizer, &cumulated_stat);
+  m_row.m_stat.set(normalizer, &visitor.m_stat);
 }
 
 int table_tlws_by_table::read_row_values(TABLE *table,
@@ -547,15 +524,9 @@ int table_tlws_by_table::read_row_values
       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);
+        m_row.m_object.set_field(f->field_index, f);
         break;
       case 3: /* COUNT_STAR */
         set_field_ulonglong(f, m_row.m_stat.m_all.m_count);

=== modified file 'storage/perfschema/table_tlws_by_table.h'
--- a/storage/perfschema/table_tlws_by_table.h	2010-12-09 16:17:13 +0000
+++ b/storage/perfschema/table_tlws_by_table.h	2011-01-07 16:20:19 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -38,16 +38,8 @@
 */
 struct row_tlws_by_table
 {
-  /** Column OBJECT_TYPE. */
-  enum_object_type m_object_type;
-  /** Column SCHEMA_NAME. */
-  char m_schema_name[NAME_LEN];
-  /** Length in bytes of @c m_schema_name. */
-  uint m_schema_name_length;
-  /** Column OBJECT_NAME. */
-  char m_object_name[NAME_LEN];
-  /** Length in bytes of @c m_object_name. */
-  uint m_object_name_length;
+  /** Column OBJECT_TYPE, SCHEMA_NAME, OBJECT_NAME. */
+  PFS_object_row m_object;
   /** Columns COUNT/SUM/MIN/AVG/MAX READ/WRITE/READ_NORMAL/etc. */
   PFS_table_lock_stat_row m_stat;
 };


Attachment: [text/bzr-bundle] bzr/marc.alff@oracle.com-20110107162019-6iiew7yxxgk65ccc.bundle
Thread
bzr commit into mysql-trunk-wl5379 branch (marc.alff:3215) WL#5371 WL#5379WL#5420Marc Alff7 Jan