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 List-Archive: http://lists.mysql.com/commits/128187 Message-Id: <201101071621.p079leaH011918@rcsinet15.oracle.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============1133438916792344765==" --===============1133438916792344765== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #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; }; --===============1133438916792344765== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/marc.alff@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: marc.alff@stripped # target_branch: file:///Users/malff/BZR_TREE/mysql-trunk-wl5379/ # testament_sha1: 033ff4361d8f3627279f9b10a11972439f87fd08 # timestamp: 2011-01-07 17:20:38 +0100 # source_branch: file:///Users/malff/BZR_TREE/mysql-trunk/ # base_revision_id: marc.alff@stripped\ # 5uv9lbp55wrnmdvc # # Begin bundle IyBCYXphYXIgcmV2aXNpb24gYnVuZGxlIHY0CiMKQlpoOTFBWSZTWXZFDmoAGhX/gFQQAIH5//// f///6r////tgKD73pV6znMz6engnbvd71Hu69et1G973s29nY2889o63boqCgUqRQMbe6jqHumHe 416Gx6527FQUE7uFhnITsyABUQqJW63QiVVu3daSx2cVFwhMysbIsONDQNGmRpo0yAxMEAANAaA0 yAwJkCU0ICBARTynqJkMJp6RoABoAaDQANAEgkgSRlJo/UQZGh+pAYgDJoGgDIZDQACTSlPRTGiT 1Sfqnpsmpkm9KeptRpsoMgaA0AADRoARJEIAEAT1NANGVT9NSfqntEeIpnlEyPU/Uhpo/VMagFSR AgTBNExNNMgmqn7VPJ6FT2mUE09IPT1TGjUaekw1MlEHl/f/75QZBnhoTpGKdcBxPZDeWRygcj8e CTw8Pe4e8bSfUDY28m3LAItQJ0ZlF5X9b4Pi7d3l5QG2tyS5V3nlk6nREku3mDwBf9K4oosfAlNM CgJSwS+Gn7M5c5rAxWklOoFFE9RksM8SgUDDpyxRwFAwDbEWoOKbJmwGvqID4RdgM4OWPhYsw6S3 O4oIiGwFEmG46jkHMnzFk5bwOZReqc9ut/MebLoJdMlRhzYlVYaxualeE0kPl7uaG5UOGFYEUZnL 5+coJOKsP/ws6Xicd6FTgWt2IpEEOA4NVLBRtttjTaqqgqgq8EVQ0AxNDbsFVSTTRUFYyPPbj39n u8dj3OiXWF0Os/wURRDd3RNOSh4o2MZn7MY1OMS/s7Jmkxx6bzDyVz2rJXp8tImyCZtFJjHRAk26 qqilxg3jeXiHIjIYOetxA3pxZs4pDmTSEJCbNZStA1JtFHoVYwRbnS1iU9XpbGzx6Ussv611skkk kkkkoqqKv0YTHadEWKTTTRVVVVVVVVVVVVaAHZ/sQFkPAGRDyI0jxzSSaapkYEWMVgQkwUEbgQQR yiCjAVGCwYkAAkRGqhHYqISeo8WoY2JXEM0+6y+MPOOX9EIbbhz4IsNnuNhqj+ozhE+H7/y+fzwL H1zAmYgQ31EiDqjX8h78BN85wvB/7r87paWhcK2xZlZjwFXcttpbbRJ77IDYNwmRC5A6Ctf/nsbB GBBIAvrVnjHzDBCEGRUkJAkUfW8Oo3B2WIH1FDj6e71Hwepeqsrf1Usre7QCoHxfHidEywa6REw6 e8Z11XAcBlhq4vnH1LG+9feYPMCvHJU0U6THEvFN33veN7CmB7uGMKQciqairw1LJRNYfK5Vkpmk pjCUrNtL1SmXYveIdNcWhkNIGLCHisNotBQrUKUnAihe8eAjKtlxsgszNHvpixZVuPpJNRM0wvRb sX8UOx7EhuDusFHePAuEE5z6FL3lueAdnahYstEE+2LihHibT+JklxuOtQzfvT8MctVfzX92afK5 vTXM16/syXvv+CS5AaJx/BCXEganp686+PuH9s+riOcwkSUcRDkFjmsmNtt26pGjANLWYYNsxpzN aYZyIIkWYTJaWNSlpYhg7j5z7xOhOinGOW5e/r/fsYHAzZL9b/SxkdvyXQu/f/Q4Fy5TyEfaMaGC 8K5kLKeQPxyLXT0cBLCKXPsDWMFc9QsN/smrVxn7TtCiHPRmW+6Ed2fC+T/Pfllw4k2ZisDQS47T rGwYumldOI4tiOzX4xsiG5hSofrGyRwklIUSEZYD4xyPUCICJQVDgSUgh0NAhjSh1my7ccSFz2+x gvdJM5Q8gggg4YPvb87BYHY4diaL4F2bGb6HaY1XNEuTNavFSCbbTbPkgwCJXwh4itkWm7s/OSWz 5Nsf5OjkilPve1u3GySVsjuQib/WQKNkkoHgQLp4zUPQsNxY8etboaNweyHRNCpt6bVk1G/K61sK 9rj/PyqqrB6uqAh4jz7m4Va+Y8QiZNDaeKGJ1lNsilMMZ0X4JrcJxl1bNHJJNklje2u9Oh0PYahc 5ob6XtnOuvyRy5Z8cjbXNm2QReo3DDI6ljuS0kYchqSRuzjVpvSk29Eax+2wvDBhPb4gUFgoKCyL IpjbtyW8jpyPUct50OhDQKfFEgJUuJ91K9APx9/xnx+77rlyfD2ncfHndcMVXt4qxVTsd0k37pJw xx83z+R56Y9Hfy4dPIg1AHkIrAhBgj809jaledTyBACFlqSCyC5x4+KSkDxFXHwPkFhE3IeYIFjK XSSSQcLhkmDEufo72y52Jgl5WFFUWllzI0aIs9zlSmlWvH7DF4liOQ5BrugUM57d2CPE+1CEgoSH zxEDNy97kPHQL2CBFhzI9Xp7tCYsK7NuA/vn0j0ya4CgoIwMJ1oezbQ0C5z07NqBmarCBiS6sB1n v8KFgvEmMGU4PJauIYA+jpJJDQIIavl/liLUo6YNUEk0u6uBSvi6cTu6Rs7u7pDp8hgzV29a2XJA gv69/PFDgGuKWG+KkxSVJtx5cbtcI4aqKKkzGc6PvVPcQiEGRCCSJEgwYwJQlBHqjyUlKQiolJA7 Ym9vhNgr1YuAW2h0PMevTcZ0peRD3/D3O/0WH5k3w+M5ny/LiGeElh4dp1BtnnDu7ZWKovSw9qgP c8D2Pa+bx+H1a2FFqUrb6LM3UmLTS7qKTT4WZtCp8wPhqUsf2C0TBgsg4H3Tc8UFjrjCDmrrsWh9 lVUspN1EY+2SOx1vug1nlpc3VgjvONjd6ZGXZvcHBUlG3bLUofJUl/IvQUs0DxxjYY+FMzz8IVe5 qrherSazMC5UBDdxuPF92ZjyZgau3v75pzcqutnRdM/ahJbQGiDGDSBbSXdqPfJqG41d9iS2gMmW I2eVwYcwN0LvQaGbgmGCIDissb4JYjUtAwclUdSfwIQj6gIqRQiJBiidp2naW7Tf08NqvSpDlwki d/4PlaJ8vO3nW4lUjCj20RjQmahhQW0laV3ypi9Qa4NUM2KGkkYMjBsHobWrC7JiywiSWhFQSrIV JFoMllkGTN+GeEZu48rbNyYtqzgybF9e3VKmOxjdIZs+CzU2atijezyYqg1a8s0ihR8ogg3CzAUZ 2bQNTHBoYNMEt7xXYqVFpRacWj2a33HM/2j/go18v3Sbtt+cSNtItTF13WAPwhmRePJlHdrTM3Ej 0dYkzbo92JYY0gRgsKQSlT9eotZBJ2nP/DLPryA2EhGmz+F9hUG7VMstm36Z6ZRFkjVxOxo71tnc av0xXt52WJ5emm/pvanW2R79+OmKbjFAqBQQeJQz5pN0Gi9HGDr6cmDkyrVWyczU/aaOrVvLpFkG rNm19TWjVfIyWtV/nbe5Pn5dbXv3INm1uU47SlG2SdnezcnL5wWc1NbfvevYeZoG/tB5jcmG65cZ +Vktr6xEbhNjA2jlAWMtdi7bUmaRKFQjKDRBrOW9zYpDBA9LyqGvszUKezyB+zKnMPY8ilAohBQH ZzXhgMlzNRQHM6hLYJduQuBGdKJ3IPZ9suENRMLu6q55GDQzLJPd9kDnA+avjv0JJlHXLt50uwFR g1bsdTI52igiNypqbhkt0D4A/6eAfEefnm4mXbtHHCetHrs/VyXJHwmoFQkk1UclnZTTYyuZGZaq bC62dLFSdrs1NrqhcseUGVQkMGZMFB2IR5IRZ/RNVDLxF1aLrgQ+nIi3o5oQcG5sGhJ6xgqccvM5 HIOx7hg8NuTWR177UimadFSdIl6PiWAqFTPZhtFmpBzJYCCSYHBzcWqgQX0Op65SKXjjVtihxJ1N i4UbA7ASemzcVhEnck5kj7uDnfvQwcFdDIB0wGxqWKEm5sXLkGhQ0M9SpDm+zYya2bkzdx5Gs9Db yapnx2MJr7c+3PRTNCd79S0YCEeKJFepRrS3B64TpSQxUKL6AB3htbnI/SV1M2xxe27Hn5uaFLI4 cND3G8ihtPI2c2m/Xpx7251PSjFqQZvW7WK2tws9zq/DYjymW6chc2dMcCY44hJLdcTbrN6ctQoT csdCLXNy01d1iZykW62a6DXBvdSzrZrGys3b2/BBljw3fH1LMOmzL2sNrhu3WevlB5o483e62toP v4muqXiMBJ77AIOOjX1zRjXqtlAV85mYs9js6TjG++Q4MOMB0r2JR3NeKMbFg22gkjBV44DFp8jB qTN4drCqQbEQeF2Ak6GSpLW6MWLBg5vFGUuwaOLipuLo7UHuYY9DmQljdOnRTFY2kftsFK9aOWHc Kv2Oj4weFzQoPzN9Dc5t5muCknfg5a87b5gwEeOli49TdGlCTocipsQeArk+IiD3Tw4YCs7a6j85 2oUVuqv2tSsW7vazMBWDrUkrPByLjMYMHc2iQLnAa5PA8KnI0NRcLnsU2tyKWLo3JNTJwabCKWMZ kghtREli/csdkSWLkiNS1AqXDVuQht5Q6w63MjC+RurPobl3z+DguGOKn2YjxDwIUqmPFeTLTCo8 3JNOJkgclwDDGyBM0xUyAMhDHNLqpo9p2kYR/wYh2RDTGppkP/Q+dC0MKe6pNSl67VNeNp74tF4u bPu31vRmLMyGY72rZIkLruwZCAzZJxs1YaYScOXmXjdWq5wk62RZOoip8BgMB2wUkjHcfgZzLAXr AJt2aQ+Yusot+sKt79aabg6TMKaGZYuC2Q9oBFjOjOuSUAwyMIRkjCEIQ1D6virQ8nmEBoD0KD+k GhPyPvaIRfvD8/eC3fof6mJ8jE/qYn7AcDaWQKEN54RYLJJPyPoAQ+oP7cQNrscZGfZj/4pmH/5s uh/D+C0NkcuEVTrf6LC6bClqPD+oB0KfmmZwMXIHOaE5U/mmLquHSaEkHO8hsKT/MlJ3M4ngftaz FM3f63+zi5MhoGvZH+7SZJNzJjO9dJpE7asU8JznBf2Kf8GI4wl1SmDNbf+zYbYTVNJeOtoXNcfv TWkuvMrhw640drceDKR94Gj5a+kpEMD/X/P9/+zyZDxivkLnyMXSqkQ1tqXVFgHqP3eX4v+5daTq pepAd8rOEtggR/D8c7/Q42xbqRDSYJpRo5wnLGy0laeRZhMY2WkrT0AQYNNaHPWGI9c9g9Ux7IvP awXJRdkmTF6XRgwJ7V2bMlnWp5EkFST562ewl4wXXUl2wexaVFKhiiyfEl1km1Nx7WSzqjqNThiq lUqhVVSOfJZjMqSjqbHmvSKMX4H1Sj7x+4/UeiEIsjnbh7gsHcDqPqmp2bJahpHcSdDqEB3PkDg4 BBotPjiA5AfcP4nyhRNtjwAIP3i7ccW248zLbbbeAqqqxW26Xxzp7ZrYiXC7hbrGQTBtMSO46PRD ZGIIBRBFdm0g/VuAsE1WQTBtQIDcxglkPxurQukikcwUsJiGQlgTBiIFVEIwh2O4btP4t9d7b3TT 5ouRpDeqqiKiohNnZtChULC3SDEHCGDQ0hQ5daFRjQh9TftaGdhcqsgmDYeG7kWpRzVy5WkEVlYD hIOUklxyjmI7FFsIaQwYxl3iqSwu4beHQl72c9QcUAOkhRUZOhRYyDAkaLI4hQwgWVgjYiMIDcLh gN0kxqZWPHMg5rGoGBFWBoZCUJgolk1IUyiiirFFVQddcmuqzryQMyFgYQVRgYxJ10hFJDQQl4YK WoukwLF0qSsRrMmat1VQTSGROvnDkHQMGAdMlGjC0tpRlsjEk5HIAcADSA7gmGefz2hbJLbW7S2l tgW2hI3S24IPmJIPi3SXDX7z5H0MN6BCK/kbIXMUhzNyxcKLmZXHYfT93h82wbxOcId6EUVRYEgG x/A5Hinb7YST6jfDOiZ2tI5v5LD+3k2P8UXVwf4Op3JY6kKDaTfQh+CpdaHpu/u/y9EgiG4W3EQy HqT6qpEA0qDdT6+kdaHWMN4T+ZoEPOipuyIrnCKjfEQ3jwGwblLB10eJPlz1yE3GMSdZUQpRMoFW cJAwDUbBc6ohbFdhCCKVAE6P91XAIvaTnDG5MWdOF4Na0iWht5ybGLb9RrRpIfj6/X/E8ngvhdwe xiu+pR/mzeJoz0dbwZscDWrFT3rrPHYuzejW+tIamTtbWT+KzexfxcWTFm7W1izb1zaQZkEe8k3t x5n9bzm/5/o/SKkucE8lPcUfoukixxAnwFE8eKJ6wgFxTwTYh2IFBioOC0k2Oxn7H044PW1rPF4M Gjval3ixeLyYIt9rxGhdxieau0eD+hVKUqqv6OLk3ONNzi+3tUSKCipJ2oMOS+rt7bXnR2Ok9Oke bYskjqwyY72rmM5Ixepq5PrmOXqPA8vtgfAcaDqqSZ0iLYyJ5xNJLBRUhkK1nB2Hz6NGAmTE61B6 aWwxiyIwIKRIQg9znXETnQNYIM1BQdo1gQibZoAMME1hAjGowplSgUpBJFPHiwmczAUC1EsGYUAc SHeZPKeQ+EHqz6+z2NMMXk1Nbav2nli9Gt7mBy7vVo5we2zzWc4Ny6nBluctGVmHLbJJRaopHZFF rWqHDe4uTR35m1qdrc6Om9qZPUTxe/U2e9757H7sGrgtJIN1fYGxyYrsEyk7e5lnnke2ec+uJPQd QR7xVRFIwURjEBJgS8i1MWhE36CCNh+KfE9nnkzSQbGBEcg4D1IJlCI76j6pgYuhqC0UmjxO1F3K 4kjbcFygkUBjPMMYMO1MihWwG8EenCpswwOguMRTbz2sciEKFt1VdVQqSWeD5Hn63a6tmeLtyeaz ydbBnz4OqqVGFPNtXZNjWp7WkOvlOdbMFL3svK/CSWV5QeeO6T3XckygSIcszQEkVbBG6xQNgkwE L0MuqUA1HCDZxALYl0aKiFKpUSciYLMFCUDg0B6qiMOKMfg63Rkz8PsA1SbYksetzyVsoeSkmEKk u3NcPxbHh9XhnW/pozwVJ0V5MERx0nd0r1/ysyk5yQ2usefwoui8D1zs7lk6S/r9H4D6Qch/iEQO QDOu2RXQi0kYQaQNfkHfd6CynSNsvMFVQYYb+lYK/IwBNO7dN5gm8zmQzJznJKCcyIj8S0KWyW1X h8cGdrO7OGt5mtHFUJ8eTKTaMElkc3SQWQ1oLB1JmKlJUpKlQMgrBYJIIFUq9aGrDvICHJQa4NiD 6YP+gah+woivu8wZjlPb7e3T35HqPWbjuOex9jvNzJra16fc1eo3M2/f+pqYSE1vCU6znJzYvou5 MG5wcHB+pzcnRtDNOKw67tjReQmbvDzGUO89iT7YoLP5SSv1rp90kq9IqSVFU3Q6a/r/CMkpQ8Cn j7yyHyRCYIe9NTLijW6bB9fsVmkNXWidf9YskmpDQnzQdRaJvjnCULRkn7DinzSFMUxkT70h8fcS 0hZYtwKL3iVR/MDv56JiMJJDGF1RDtwwdQtA/PFD+kpmyWd5xtJDghwO4/XBvkDFx/I7/SFFRMA+ i0S1f8xh292KNpEadJJK0fuT0gZeKD6dn5HvWKLFlWsLWWLh+VN6H1oNiPimyRI8Xe3Q+nq2uYg9 GsHiIcrcSAZMoCRGNU0QIliy1H+JahQS23SeJNuzb7ImY0SJFipGFzaqdJEuQy1d/lyxXMnPXRRT ZV1aiDIT9BRQBBGTy+dVMQ8q+hHuDlMBCfyVKkEUSFZl64J2B57ndrAdRA5xYtEFookURPZPU9rm JeE+CZCJM4Zk3fF1BZGMkslJtJ9D6cHyLkH4GUHzhOo6rQeiDqSWhFQb6fJHG78bRtPmWQwGFHvJ aFC1HfsaQ0+2wcg6xiSIQIMRDtIgVE6j2U9xzDnlfvqYouoUbIkfWVKKCpIEVOAhguhHqaHnGBYi L0haSBIximKFFBFYsiO+kpCMUbKDBpXWZ7CWgEjBIAEVikSALIAYlJLKJMdcna2SR3TGqFMxsP1d UhNcMkTSdiNrrmDb28GqQ1Ka4Umz6rJ2AWznXtFDnQ0pwaH+1K0pIkAc5gmZbhpo3LplGMdVOsl2 6DxGSMbpWAoIFlIEyYL1e/4BT0QEoUUs+D25YjPrGCNC6GJQxRv1tUpMCmw2xjT4m6Q+4blEpBGi 60olUDQhZDV1tC5KkwqiN0C3zqqwkdT2yTAP6n5BStez1Bg9Qmh8TzIqbHWPWPJjCEeovKhJtp2t dtvejIxqDM0TZqDQ/A6mxM5UlVEriy155JZthdLNSzWxrBF6R4TcYl0jOUhsRGySUQ/E/a2SIayZ BaSkqRZCwbN599MB+lJAwyT0LmqgeZFz1iMKWgaRpKUduQ54doYu5yRfCJuDe2SE0ATFBSR2QohY YjIiaCoERSoF2BUQdBvqrP27+7zAXSCp48z5nzwxqRHqSHGN0iSlLBH0/TXzdM0OKf0m9gm13n0I juepsG2qkoZoig5E3DQSBCEFShQ/x3A0i2GY01s/1q5bImLKGBrJOyJQnF+ZeW+Miy4RgKD8VBgJ zHjUutg5dWA2dZ8jJ5fR/a5N5yTiLuMtP3JUgejwr6nHj2z0R3ZI6OgHtpWIEyAPxOHIReIHQepW cTDD0hnIewklSMBCWCA0GT7SFggiEPvGIGI5Ymx1FRQKzhyNyJR+uHXgHvDaVBzl0ebvwuPCh3WX UjCleLEPsDp850/NPtPjY8zQuVCPGkHlKhaVJVSFEIQSCSCCx9Nq21jLatrZLKJjafkVdJJgkxP0 heSDYmKbjElGv0HnL4KNKFIKZEBD5CRXUqGQvKNDW2tiQ+ZjJogqHOSn3/jSertwDjIms8PfDCH5 tvNDN4JVGE08U4o12+85As6RgpAigcETQaSSMgSTuVTQo/supiOTFkRmIGQTqMF8GsPZc0AeFUwj 2sy0XMlRMYYWO6dReqOKei6bmcDWQ+TULEYjEGIIMl4BhkiCE4JLIJBZBYYoKBuwBkHAICyAghDi bgzpKaF4yJialSwNXJhu0o5vqGGnNKDms9Jml7ARLdBTGKHiADSUOK0HVEwslillIZWKSn2J83W+ bvMrpmh2yTfzclHWksWKaPHGGT8kZ4BLkPHSHvwFr1RWkEwhIjDa0StoUliWptBqqrgRoHpLAIDS th8KByq9UN93p84cqIBw5dNhDTe4oFIuyKhNEFZIepdwQykMD0gtJYy6KpdYMPNkWfQhq7BygSL1 GhHYEHBYuvwYGQ3KRMSoqSmFxZTOKf1aIyRipFmjBfDGLSRkpJSiUo/WYnxg6Rixhma0LSNC9E1i UJaSYosSotISLEjYpCwOYVgg0sgMMCSARUVFVaIUFViqsIiqoiqryIHMCMh9AsVUbCTunYYIh6/W tVqtVYNa100DJ8lJJZrLJCxNSRJAogpJQ11Wq1Wq1Wq7twHPkbKREYwR1JbUBOQiWLKm3GsCKHh3 LXgyH4MEMnUXwXiEQzqtxXloPkd4mciBAwFSIEYbhpi8/NLFkkCQJDP1ci0hFN9x4ndv5MiRkYKS BEDAA1EQOBAfdNx4wOJphVUVgQYkCTVWCkJYiIjFERGCMGKgGBFLtJeQ/NRakNSk92Yzh5RNHS7S 97r3zMsE30xkir3kkbBPinpMm+HI/7ntDwKp+0eYU5jUIbwYQ7QPtE+A9A/TjxTuLq8TmNaPA4hz X5k6V680TDgNDwQM4aTCwx6JPxOmmKYI2GjowUfdJJgdk+ufc982YDqXeeIuh4lXewdbY2GJ66VT AQiHmip8JaVsSlpWwSiFEpaVsSlpWkYUtK0jClpWgyl4knlAQJuCCEg98BIIH5CoxFH2RWu4BU/O oq0gtD3faC26kJR5cEg4+SOAgWHEc6boqvgGycWO+HoQIf3Bq51WxxekHxpJJJNiAG+KnwQO8KSy SBCSOhR9qCuE/EtJJ1IOj3L6G9L1Wb4x1IyYpi3H470dRrhnSZFih8KFUidjm3Q3QvllkcD8kH1G vbJDPcfDpAcmY2oncL5QPGKH3kFvAYiSED/6MVVtqKQWRGIm4CyTEGZJLCWOTIBfSqKKqr/8XckU 4UJB2RQ5qA== --===============1133438916792344765==--