From: Bjorn Munch Date: September 1 2010 1:49pm Subject: bzr commit into mysql-5.5-mtr branch (bjorn.munch:3085) List-Archive: http://lists.mysql.com/commits/117338 Message-Id: <201009011350.o81Dojwn010303@khepri15.norway.sun.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============1831463695==" --===============1831463695== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///home/bm136801/my/mtr-55/ based on revid:bjorn.munch@stripped 3085 Bjorn Munch 2010-09-01 [merge] merge from 5.5 added: include/mysql/service_thd_wait.h include/mysql/service_thread_scheduler.h libservices/my_thread_scheduler_service.c libservices/thd_wait_service.c sql/sql_callback.h modified: client/mysqltest.cc include/Makefile.am include/mysql/plugin.h include/mysql/plugin_audit.h.pp include/mysql/plugin_ftparser.h.pp include/mysql/services.h include/service_versions.h include/thr_lock.h include/violite.h libservices/CMakeLists.txt libservices/Makefile.am mysql-test/r/delete.result mysql-test/r/func_group.result mysql-test/r/mysqld--help-notwin.result mysql-test/r/mysqld--help-win.result mysql-test/r/range.result mysql-test/suite/innodb/r/innodb_mysql.result mysql-test/suite/innodb/t/innodb_mysql.test mysql-test/suite/rpl/r/rpl_flush_logs.result mysql-test/suite/rpl/t/rpl_flush_logs.test mysql-test/t/delete.test mysql-test/t/func_group.test mysql-test/t/range.test mysys/my_init.c mysys/thr_lock.c sql/authors.h sql/item_sum.cc sql/item_sum.h sql/log.cc sql/mysqld.cc sql/mysqld.h sql/opt_range.cc sql/scheduler.cc sql/scheduler.h sql/sql_class.cc sql/sql_class.h sql/sql_connect.cc sql/sql_connect.h sql/sql_plugin_services.h sql/sql_select.cc sql/sql_show.cc sql/sql_yacc.yy sql/sys_vars.cc storage/innobase/buf/buf0flu.c storage/innobase/buf/buf0rea.c storage/innobase/srv/srv0srv.c vio/vio.c vio/vio_priv.h vio/viosocket.c vio/viossl.c === modified file 'client/mysqltest.cc' --- a/client/mysqltest.cc 2010-08-30 13:19:46 +0000 +++ b/client/mysqltest.cc 2010-09-01 13:49:43 +0000 @@ -5255,10 +5255,8 @@ void do_connect(struct st_command *comma } #endif -#ifndef EMBEDDED_LIBRARY if (opt_protocol) mysql_options(&con_slot->mysql, MYSQL_OPT_PROTOCOL, (char*) &opt_protocol); -#endif #ifdef HAVE_SMEM if (con_shm) @@ -7992,10 +7990,8 @@ int main(int argc, char **argv) mysql_options(&con->mysql, MYSQL_SET_CHARSET_DIR, opt_charsets_dir); -#ifndef EMBEDDED_LIBRARY if (opt_protocol) mysql_options(&con->mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); -#endif #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) === modified file 'include/Makefile.am' --- a/include/Makefile.am 2010-07-23 20:14:35 +0000 +++ b/include/Makefile.am 2010-08-16 12:50:27 +0000 @@ -26,6 +26,8 @@ HEADERS_ABI = mysql.h mysql_com.h mysql pkginclude_HEADERS = $(HEADERS_ABI) my_dbug.h m_string.h my_sys.h \ my_xml.h mysql_embed.h mysql/services.h \ mysql/service_my_snprintf.h mysql/service_thd_alloc.h \ + mysql/service_thread_scheduler.h \ + mysql/service_thd_wait.h \ my_pthread.h my_no_pthread.h \ decimal.h errmsg.h my_global.h my_net.h \ my_getopt.h sslopt-longopts.h my_dir.h \ === modified file 'include/mysql/plugin.h' --- a/include/mysql/plugin.h 2010-08-18 07:48:38 +0000 +++ b/include/mysql/plugin.h 2010-08-30 14:07:40 +0000 @@ -71,7 +71,7 @@ typedef struct st_mysql_xid MYSQL_XID; Plugin API. Common for all plugin types. */ -#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0101 +#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0102 /* The allowable types of plugins === modified file 'include/mysql/plugin_audit.h.pp' --- a/include/mysql/plugin_audit.h.pp 2010-08-27 06:45:35 +0000 +++ b/include/mysql/plugin_audit.h.pp 2010-08-30 14:07:40 +0000 @@ -31,6 +31,27 @@ void *thd_memdup(void* thd, const void* MYSQL_LEX_STRING *thd_make_lex_string(void* thd, MYSQL_LEX_STRING *lex_str, const char *str, unsigned int size, int allocate_lex_string); +#include +typedef enum _thd_wait_type_e { + THD_WAIT_MUTEX= 1, + THD_WAIT_DISKIO= 2, + THD_WAIT_ROW_TABLE_LOCK= 3, + THD_WAIT_GLOBAL_LOCK= 4 +} thd_wait_type; +extern struct thd_wait_service_st { + void (*thd_wait_begin_func)(void*, thd_wait_type); + void (*thd_wait_end_func)(void*); +} *thd_wait_service; +void thd_wait_begin(void* thd, thd_wait_type wait_type); +void thd_wait_end(void* thd); +#include +struct scheduler_functions; +extern struct my_thread_scheduler_service { + int (*set)(struct scheduler_functions *scheduler); + int (*reset)(); +} *my_thread_scheduler_service; +int my_thread_scheduler_set(struct scheduler_functions *scheduler); +int my_thread_scheduler_reset(); struct st_mysql_xid { long formatID; long gtrid_length; === modified file 'include/mysql/plugin_ftparser.h.pp' --- a/include/mysql/plugin_ftparser.h.pp 2010-08-27 06:45:35 +0000 +++ b/include/mysql/plugin_ftparser.h.pp 2010-08-30 14:07:40 +0000 @@ -31,6 +31,27 @@ void *thd_memdup(void* thd, const void* MYSQL_LEX_STRING *thd_make_lex_string(void* thd, MYSQL_LEX_STRING *lex_str, const char *str, unsigned int size, int allocate_lex_string); +#include +typedef enum _thd_wait_type_e { + THD_WAIT_MUTEX= 1, + THD_WAIT_DISKIO= 2, + THD_WAIT_ROW_TABLE_LOCK= 3, + THD_WAIT_GLOBAL_LOCK= 4 +} thd_wait_type; +extern struct thd_wait_service_st { + void (*thd_wait_begin_func)(void*, thd_wait_type); + void (*thd_wait_end_func)(void*); +} *thd_wait_service; +void thd_wait_begin(void* thd, thd_wait_type wait_type); +void thd_wait_end(void* thd); +#include +struct scheduler_functions; +extern struct my_thread_scheduler_service { + int (*set)(struct scheduler_functions *scheduler); + int (*reset)(); +} *my_thread_scheduler_service; +int my_thread_scheduler_set(struct scheduler_functions *scheduler); +int my_thread_scheduler_reset(); struct st_mysql_xid { long formatID; long gtrid_length; === added file 'include/mysql/service_thd_wait.h' --- a/include/mysql/service_thd_wait.h 1970-01-01 00:00:00 +0000 +++ b/include/mysql/service_thd_wait.h 2010-06-07 14:01:39 +0000 @@ -0,0 +1,83 @@ +/* Copyright (C) 2010, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef MYSQL_SERVICE_THD_WAIT_INCLUDED +#define MYSQL_SERVICE_THD_WAIT_INCLUDED + +/** + @file include/mysql/service_thd_wait.h + This service provides functions for plugins and storage engines to report + when they are going to sleep/stall. + + SYNOPSIS + thd_wait_begin() - call just before a wait begins + thd Thread object + Use NULL if the thd is NOT known. + wait_type Type of wait + 1 -- short wait (e.g. for mutex) + 2 -- medium wait (e.g. for disk io) + 3 -- large wait (e.g. for locked row/table) + NOTES + This is used by the threadpool to have better knowledge of which + threads that currently are actively running on CPUs. When a thread + reports that it's going to sleep/stall, the threadpool scheduler is + free to start another thread in the pool most likely. The expected wait + time is simply an indication of how long the wait is expected to + become, the real wait time could be very different. + + thd_wait_end() called immediately after the wait is complete + + thd_wait_end() MUST be called if thd_wait_begin() was called. + + Using thd_wait_...() service is optional but recommended. Using it will + improve performance as the thread pool will be more active at managing the + thread workload. +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum _thd_wait_type_e { + THD_WAIT_MUTEX= 1, + THD_WAIT_DISKIO= 2, + THD_WAIT_ROW_TABLE_LOCK= 3, + THD_WAIT_GLOBAL_LOCK= 4 +} thd_wait_type; + +extern struct thd_wait_service_st { + void (*thd_wait_begin_func)(MYSQL_THD, thd_wait_type); + void (*thd_wait_end_func)(MYSQL_THD); +} *thd_wait_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define thd_wait_begin(_THD, _WAIT_TYPE) \ + thd_wait_service->thd_wait_begin_func(_THD, _WAIT_TYPE) +#define thd_wait_end(_THD) thd_wait_service->thd_wait_end_func(_THD) + +#else + +void thd_wait_begin(MYSQL_THD thd, thd_wait_type wait_type); +void thd_wait_end(MYSQL_THD thd); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif + === added file 'include/mysql/service_thread_scheduler.h' --- a/include/mysql/service_thread_scheduler.h 1970-01-01 00:00:00 +0000 +++ b/include/mysql/service_thread_scheduler.h 2010-06-07 14:01:39 +0000 @@ -0,0 +1,65 @@ +/* + Copyright (C) 2010, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef SERVICE_THREAD_SCHEDULER_INCLUDED +#define SERVICE_THREAD_SCHEDULER_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +struct scheduler_functions; + +extern struct my_thread_scheduler_service { + int (*set)(struct scheduler_functions *scheduler); + int (*reset)(); +} *my_thread_scheduler_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define my_thread_scheduler_set(F) my_thread_scheduler_service->set((F)) +#define my_thread_scheduler_reset() my_thread_scheduler_service->reset() + +#else + +/** + Set the thread scheduler to use for the server. + + @param scheduler Pointer to scheduler callbacks to use. + @retval 0 Scheduler installed correctly. + @retval 1 Invalid value (NULL) used for scheduler. +*/ +int my_thread_scheduler_set(struct scheduler_functions *scheduler); + +/** + Restore the previous thread scheduler. + + @note If no thread scheduler was installed previously with + thd_set_thread_scheduler, this function will report an error. + + @retval 0 Scheduler installed correctly. + @retval 1 No scheduler installed. +*/ +int my_thread_scheduler_reset(); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* SERVICE_THREAD_SCHEDULER_INCLUDED */ === modified file 'include/mysql/services.h' --- a/include/mysql/services.h 2009-11-02 20:05:42 +0000 +++ b/include/mysql/services.h 2010-06-07 14:01:39 +0000 @@ -20,6 +20,8 @@ extern "C" { #include #include +#include +#include #ifdef __cplusplus } === modified file 'include/service_versions.h' --- a/include/service_versions.h 2009-11-02 20:05:42 +0000 +++ b/include/service_versions.h 2010-06-07 14:01:39 +0000 @@ -21,4 +21,5 @@ #define VERSION_my_snprintf 0x0100 #define VERSION_thd_alloc 0x0100 - +#define VERSION_thd_wait 0x0100 +#define VERSION_my_thread_scheduler 0x0100 === modified file 'include/thr_lock.h' --- a/include/thr_lock.h 2010-07-27 12:42:36 +0000 +++ b/include/thr_lock.h 2010-08-16 12:50:27 +0000 @@ -155,6 +155,8 @@ void thr_downgrade_write_lock(THR_LOC enum thr_lock_type new_lock_type); my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data, ulong lock_wait_timeout); +void thr_set_lock_wait_callback(void (*before_wait)(void), + void (*after_wait)(void)); #ifdef __cplusplus } #endif === modified file 'include/violite.h' --- a/include/violite.h 2010-04-13 15:04:45 +0000 +++ b/include/violite.h 2010-06-07 14:01:39 +0000 @@ -217,6 +217,7 @@ struct st_vio void (*timeout)(Vio*, unsigned int which, unsigned int timeout); my_bool (*poll_read)(Vio *vio, uint timeout); my_bool (*is_connected)(Vio*); + my_bool (*has_data) (Vio*); #ifdef HAVE_OPENSSL void *ssl_arg; #endif === modified file 'libservices/CMakeLists.txt' --- a/libservices/CMakeLists.txt 2010-08-12 15:19:57 +0000 +++ b/libservices/CMakeLists.txt 2010-08-16 12:50:27 +0000 @@ -15,7 +15,11 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) -SET(MYSQLSERVICES_SOURCES my_snprintf_service.c thd_alloc_service.c) +SET(MYSQLSERVICES_SOURCES + my_snprintf_service.c + thd_alloc_service.c + thd_wait_service.c + my_thread_scheduler_service.c) ADD_LIBRARY(mysqlservices ${MYSQLSERVICES_SOURCES}) INSTALL(TARGETS mysqlservices DESTINATION ${INSTALL_LIBDIR}) === modified file 'libservices/Makefile.am' --- a/libservices/Makefile.am 2009-11-02 20:05:42 +0000 +++ b/libservices/Makefile.am 2010-06-07 14:01:39 +0000 @@ -15,5 +15,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/include pkglib_LIBRARIES = libmysqlservices.a -libmysqlservices_a_SOURCES = my_snprintf_service.c thd_alloc_service.c +libmysqlservices_a_SOURCES = my_snprintf_service.c thd_alloc_service.c \ + thd_wait_service.c \ + my_thread_scheduler_service.c EXTRA_DIST = CMakeLists.txt === added file 'libservices/my_thread_scheduler_service.c' --- a/libservices/my_thread_scheduler_service.c 1970-01-01 00:00:00 +0000 +++ b/libservices/my_thread_scheduler_service.c 2010-06-07 14:01:39 +0000 @@ -0,0 +1,21 @@ +/* + Copyright (C) 2010, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA +*/ + +#include +SERVICE_VERSION my_thread_scheduler_service= + (void*)VERSION_my_thread_scheduler; === added file 'libservices/thd_wait_service.c' --- a/libservices/thd_wait_service.c 1970-01-01 00:00:00 +0000 +++ b/libservices/thd_wait_service.c 2010-06-07 14:01:39 +0000 @@ -0,0 +1,19 @@ +/* + Copyright (C) 2010, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +SERVICE_VERSION *thd_wait_service= (void*)VERSION_thd_wait; === modified file 'mysql-test/r/delete.result' --- a/mysql-test/r/delete.result 2010-05-23 20:41:18 +0000 +++ b/mysql-test/r/delete.result 2010-08-30 22:22:01 +0000 @@ -499,4 +499,13 @@ INDEX(a), INDEX(b), INDEX(c)); INSERT INTO t1 VALUES (1,2,3), (4,5,6), (7,8,9); DELETE FROM t1 WHERE a = 10 OR b = 20 ORDER BY c LIMIT 1; DROP TABLE t1; +# +# Bug #53034: Multiple-table DELETE statements not accepting +# "Access compatibility" syntax +# +CREATE TABLE t1 (id INT); +CREATE TABLE t2 LIKE t1; +CREATE TABLE t3 LIKE t1; +DELETE FROM t1.*, test.t2.*, a.* USING t1, t2, t3 AS a; +DROP TABLE t1, t2, t3; End of 5.1 tests === modified file 'mysql-test/r/func_group.result' --- a/mysql-test/r/func_group.result 2010-08-25 09:21:54 +0000 +++ b/mysql-test/r/func_group.result 2010-08-30 08:36:02 +0000 @@ -1713,6 +1713,17 @@ f1 f2 f3 f4 f1 = f2 NULL NULL NULL NULL NULL drop table t1; # +# Bug #54465: assert: field_types == 0 || field_types[field_pos] == +# MYSQL_TYPE_LONGLONG +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1), (2); +SELECT MAX((SELECT 1 FROM t1 ORDER BY @var LIMIT 1)) m FROM t1 t2, t1 +ORDER BY t1.a; +m +1 +DROP TABLE t1; +# End of 5.1 tests # # Bug#55648: Server crash on MIN/MAX on maximum time value === modified file 'mysql-test/r/mysqld--help-notwin.result' --- a/mysql-test/r/mysqld--help-notwin.result 2010-08-28 16:36:17 +0000 +++ b/mysql-test/r/mysqld--help-notwin.result 2010-08-30 14:07:40 +0000 @@ -688,7 +688,7 @@ The following options may be given as th How many threads we should keep in a cache for reuse --thread-handling=name Define threads usage for handling queries, one of - one-thread-per-connection, no-threads + one-thread-per-connection, no-threads, loaded-dynamically --thread-stack=# The stack size for each thread --time-format=name The TIME format (ignored) --timed-mutexes Specify whether to time mutexes (only InnoDB mutexes are === modified file 'mysql-test/r/mysqld--help-win.result' --- a/mysql-test/r/mysqld--help-win.result 2010-08-28 16:36:17 +0000 +++ b/mysql-test/r/mysqld--help-win.result 2010-08-30 14:07:40 +0000 @@ -692,7 +692,7 @@ The following options may be given as th How many threads we should keep in a cache for reuse --thread-handling=name Define threads usage for handling queries, one of - one-thread-per-connection, no-threads + one-thread-per-connection, no-threads, loaded-dynamically --thread-stack=# The stack size for each thread --time-format=name The TIME format (ignored) --timed-mutexes Specify whether to time mutexes (only InnoDB mutexes are === modified file 'mysql-test/r/range.result' --- a/mysql-test/r/range.result 2010-08-11 15:55:07 +0000 +++ b/mysql-test/r/range.result 2010-08-26 12:35:38 +0000 @@ -1653,4 +1653,17 @@ a b 0 0 1 1 DROP TABLE t1; +# +# Bug #54802: 'NOT BETWEEN' evaluation is incorrect +# +CREATE TABLE t1 (c_key INT, c_notkey INT, KEY(c_key)); +INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3); +EXPLAIN SELECT * FROM t1 WHERE 2 NOT BETWEEN c_notkey AND c_key; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL c_key NULL NULL NULL 3 Using where +SELECT * FROM t1 WHERE 2 NOT BETWEEN c_notkey AND c_key; +c_key c_notkey +1 1 +3 3 +DROP TABLE t1; End of 5.1 tests === modified file 'mysql-test/suite/innodb/r/innodb_mysql.result' --- a/mysql-test/suite/innodb/r/innodb_mysql.result 2010-08-25 10:22:34 +0000 +++ b/mysql-test/suite/innodb/r/innodb_mysql.result 2010-08-30 08:36:02 +0000 @@ -2549,6 +2549,64 @@ LOCK TABLES t1 READ; ALTER TABLE t1 COMMENT 'test'; UNLOCK TABLES; DROP TABLE t1; +# +# Bug#55656: mysqldump can be slower after bug #39653 fix +# +CREATE TABLE t1 (a INT , b INT, c INT, d INT, +KEY (b), PRIMARY KEY (a,b)) ENGINE=INNODB; +INSERT INTO t1 VALUES (1,1,1,1), (2,2,2,2), (3,3,3,3); +EXPLAIN SELECT COUNT(*) FROM t1; +id 1 +select_type SIMPLE +table t1 +type index +possible_keys NULL +key b +key_len 4 +ref NULL +rows 3 +Extra Using index +DROP INDEX b ON t1; +CREATE INDEX b ON t1(a,b); +EXPLAIN SELECT COUNT(*) FROM t1; +id 1 +select_type SIMPLE +table t1 +type index +possible_keys NULL +key b +key_len 8 +ref NULL +rows 3 +Extra Using index +DROP INDEX b ON t1; +CREATE INDEX b ON t1(a,b,c); +EXPLAIN SELECT COUNT(*) FROM t1; +id 1 +select_type SIMPLE +table t1 +type index +possible_keys NULL +key b +key_len 13 +ref NULL +rows 3 +Extra Using index +DROP INDEX b ON t1; +CREATE INDEX b ON t1(a,b,c,d); +EXPLAIN SELECT COUNT(*) FROM t1; +id 1 +select_type SIMPLE +table t1 +type index +possible_keys NULL +key PRIMARY +key_len 8 +ref NULL +rows 3 +Extra Using index +DROP TABLE t1; +# End of 5.1 tests # # Test for bug #39932 "create table fails if column for FK is in different === modified file 'mysql-test/suite/innodb/t/innodb_mysql.test' --- a/mysql-test/suite/innodb/t/innodb_mysql.test 2010-08-20 11:22:46 +0000 +++ b/mysql-test/suite/innodb/t/innodb_mysql.test 2010-08-27 11:33:32 +0000 @@ -746,6 +746,30 @@ UNLOCK TABLES; DROP TABLE t1; +--echo # +--echo # Bug#55656: mysqldump can be slower after bug #39653 fix +--echo # + +CREATE TABLE t1 (a INT , b INT, c INT, d INT, + KEY (b), PRIMARY KEY (a,b)) ENGINE=INNODB; +INSERT INTO t1 VALUES (1,1,1,1), (2,2,2,2), (3,3,3,3); +--query_vertical EXPLAIN SELECT COUNT(*) FROM t1 + +DROP INDEX b ON t1; +CREATE INDEX b ON t1(a,b); +--query_vertical EXPLAIN SELECT COUNT(*) FROM t1 + +DROP INDEX b ON t1; +CREATE INDEX b ON t1(a,b,c); +--query_vertical EXPLAIN SELECT COUNT(*) FROM t1 + +DROP INDEX b ON t1; +CREATE INDEX b ON t1(a,b,c,d); +--query_vertical EXPLAIN SELECT COUNT(*) FROM t1 + +DROP TABLE t1; + +--echo # --echo End of 5.1 tests === modified file 'mysql-test/suite/rpl/r/rpl_flush_logs.result' --- a/mysql-test/suite/rpl/r/rpl_flush_logs.result 2009-12-03 08:59:58 +0000 +++ b/mysql-test/suite/rpl/r/rpl_flush_logs.result 2010-08-30 09:09:28 +0000 @@ -4,12 +4,8 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; -# Make sure the 'master_log.err-old' file does not -# exist before execute 'flush error logs' statement. # Test if support 'flush error logs' statement. flush error logs; -# Check the 'master_log.err-old' file is created -# after executed 'flush error logs' statement. # Make sure binary logs was not be flushed # after execute 'flush error logs' statement. # Make sure relay logs was not be flushed @@ -42,12 +38,8 @@ flush binary logs; # after executed 'flush binary logs' statement. # Make sure the 'slave-relay-bin.000007' file does not exist # exist before execute 'flush error logs, relay logs' statement. -# Make sure the 'master_log.err-old' file does not exist -# before execute 'flush error logs, relay logs' statement. # Test if support to combine all kinds of logs into one statement. flush error logs, relay logs; -# Check the 'master_log.err-old' file is created -# after executed 'flush error logs, relay logs' statement. # Make sure binary logs was not be flushed # after execute 'flush error logs, relay logs' statement. # Check the 'slave-relay-bin.000007' file is created after @@ -55,12 +47,8 @@ flush error logs, relay logs; # Make sure the 'slave-relay-bin.000008' and 'slave-relay-bin.000009' # files do not exist before execute 'flush error logs, relay logs' # statement. -# Make sure the 'master_log.err-old' file does not exist -# before execute 'flush logs' statement. # Test if 'flush logs' statement works fine and flush all the logs. flush logs; -# Check the 'master_log.err-old' file is created -# after executed 'flush logs' statement. # Check 'master-bin.000003' is created # after execute 'flush logs' statement. # Check the 'slave-relay-bin.000008' and 'slave-relay-bin.000009' === modified file 'mysql-test/suite/rpl/t/rpl_flush_logs.test' --- a/mysql-test/suite/rpl/t/rpl_flush_logs.test 2009-12-03 08:59:58 +0000 +++ b/mysql-test/suite/rpl/t/rpl_flush_logs.test 2010-08-30 09:09:28 +0000 @@ -9,17 +9,10 @@ connection master; # Test 'flush error logs' statement. ---echo # Make sure the 'master_log.err-old' file does not ---echo # exist before execute 'flush error logs' statement. ---error 1 -file_exists $MYSQLTEST_VARDIR/tmp/master_log.err-old; --echo # Test if support 'flush error logs' statement. flush error logs; ---echo # Check the 'master_log.err-old' file is created ---echo # after executed 'flush error logs' statement. -file_exists $MYSQLTEST_VARDIR/tmp/master_log.err-old; file_exists $MYSQLTEST_VARDIR/tmp/master_log.err; --echo # Make sure binary logs was not be flushed @@ -109,19 +102,10 @@ sync_slave_with_master; file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000007; connection master; -remove_file $MYSQLTEST_VARDIR/tmp/master_log.err-old; - ---echo # Make sure the 'master_log.err-old' file does not exist ---echo # before execute 'flush error logs, relay logs' statement. ---error 1 -file_exists $MYSQLTEST_VARDIR/tmp/master_log.err-old; --echo # Test if support to combine all kinds of logs into one statement. flush error logs, relay logs; ---echo # Check the 'master_log.err-old' file is created ---echo # after executed 'flush error logs, relay logs' statement. -file_exists $MYSQLTEST_VARDIR/tmp/master_log.err-old; file_exists $MYSQLTEST_VARDIR/tmp/master_log.err; --echo # Make sure binary logs was not be flushed @@ -145,19 +129,10 @@ file_exists $MYSQLTEST_VARDIR/mysqld.2/d file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000009; connection master; -remove_file $MYSQLTEST_VARDIR/tmp/master_log.err-old; - ---echo # Make sure the 'master_log.err-old' file does not exist ---echo # before execute 'flush logs' statement. ---error 1 -file_exists $MYSQLTEST_VARDIR/tmp/master_log.err-old; --echo # Test if 'flush logs' statement works fine and flush all the logs. flush logs; ---echo # Check the 'master_log.err-old' file is created ---echo # after executed 'flush logs' statement. -file_exists $MYSQLTEST_VARDIR/tmp/master_log.err-old; file_exists $MYSQLTEST_VARDIR/tmp/master_log.err; --echo # Check 'master-bin.000003' is created === modified file 'mysql-test/t/delete.test' --- a/mysql-test/t/delete.test 2010-05-23 20:41:18 +0000 +++ b/mysql-test/t/delete.test 2010-08-30 22:22:01 +0000 @@ -540,4 +540,17 @@ DELETE FROM t1 WHERE a = 10 OR b = 20 OR DROP TABLE t1; +--echo # +--echo # Bug #53034: Multiple-table DELETE statements not accepting +--echo # "Access compatibility" syntax +--echo # + +CREATE TABLE t1 (id INT); +CREATE TABLE t2 LIKE t1; +CREATE TABLE t3 LIKE t1; + +DELETE FROM t1.*, test.t2.*, a.* USING t1, t2, t3 AS a; + +DROP TABLE t1, t2, t3; + --echo End of 5.1 tests === modified file 'mysql-test/t/func_group.test' --- a/mysql-test/t/func_group.test 2010-08-25 09:21:54 +0000 +++ b/mysql-test/t/func_group.test 2010-08-30 08:36:02 +0000 @@ -1082,6 +1082,20 @@ select a.f1 as a, b.f4 as b, a.f1 > b.f4 from t1 a, t1 b; select *, f1 = f2 from t1; drop table t1; + +--echo # +--echo # Bug #54465: assert: field_types == 0 || field_types[field_pos] == +--echo # MYSQL_TYPE_LONGLONG +--echo # + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1), (2); + +SELECT MAX((SELECT 1 FROM t1 ORDER BY @var LIMIT 1)) m FROM t1 t2, t1 + ORDER BY t1.a; + +DROP TABLE t1; + --echo # --echo End of 5.1 tests === modified file 'mysql-test/t/range.test' --- a/mysql-test/t/range.test 2010-08-11 12:13:59 +0000 +++ b/mysql-test/t/range.test 2010-08-24 15:51:32 +0000 @@ -1313,4 +1313,16 @@ SELECT * FROM t1 FORCE INDEX (PRIMARY) DROP TABLE t1; +--echo # +--echo # Bug #54802: 'NOT BETWEEN' evaluation is incorrect +--echo # + +CREATE TABLE t1 (c_key INT, c_notkey INT, KEY(c_key)); +INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3); + +EXPLAIN SELECT * FROM t1 WHERE 2 NOT BETWEEN c_notkey AND c_key; +SELECT * FROM t1 WHERE 2 NOT BETWEEN c_notkey AND c_key; + +DROP TABLE t1; + --echo End of 5.1 tests === modified file 'mysys/my_init.c' --- a/mysys/my_init.c 2010-07-23 20:16:29 +0000 +++ b/mysys/my_init.c 2010-08-16 12:50:27 +0000 @@ -477,7 +477,7 @@ static my_bool win32_init_tcp_ip() { if (win32_have_tcpip()) { - WORD wVersionRequested = MAKEWORD( 2, 0 ); + WORD wVersionRequested = MAKEWORD( 2, 2 ); WSADATA wsaData; /* Be a good citizen: maybe another lib has already initialised sockets, so dont clobber them unless necessary */ === modified file 'mysys/thr_lock.c' --- a/mysys/thr_lock.c 2010-08-06 11:29:37 +0000 +++ b/mysys/thr_lock.c 2010-08-30 14:07:40 +0000 @@ -91,6 +91,16 @@ enum thr_lock_type thr_upgraded_concurre LIST *thr_lock_thread_list; /* List of threads in use */ ulong max_write_lock_count= ~(ulong) 0L; +static void (*before_lock_wait)(void)= 0; +static void (*after_lock_wait)(void)= 0; + +void thr_set_lock_wait_callback(void (*before_wait)(void), + void (*after_wait)(void)) +{ + before_lock_wait= before_wait; + after_lock_wait= after_wait; +} + static inline mysql_cond_t *get_cond(void) { return &my_thread_var->suspend; @@ -431,6 +441,19 @@ wait_for_lock(struct st_lock_list *wait, old_proc_info= proc_info_hook(NULL, "Waiting for table level lock", __func__, __FILE__, __LINE__); + /* + Since before_lock_wait potentially can create more threads to + scheduler work for, we don't want to call the before_lock_wait + callback unless it will really start to wait. + + For similar reasons, we do not want to call before_lock_wait and + after_lock_wait for each lap around the loop, so we restrict + ourselves to call it before_lock_wait once before starting to wait + and once after the thread has exited the wait loop. + */ + if ((!thread_var->abort || in_wait_list) && before_lock_wait) + (*before_lock_wait)(); + set_timespec(wait_timeout, lock_wait_timeout); while (!thread_var->abort || in_wait_list) { @@ -462,6 +485,14 @@ wait_for_lock(struct st_lock_list *wait, /* purecov: end */ } } + + /* + We call the after_lock_wait callback once the wait loop has + finished. + */ + if (after_lock_wait) + (*after_lock_wait)(); + DBUG_PRINT("thr_lock", ("aborted: %d in_wait_list: %d", thread_var->abort, in_wait_list)); === modified file 'sql/authors.h' --- a/sql/authors.h 2010-05-11 16:02:50 +0000 +++ b/sql/authors.h 2010-08-16 12:50:27 +0000 @@ -93,6 +93,7 @@ struct show_table_authors_st show_table_ { "Arjen Lentz", "Brisbane, Australia", "Documentation (2001-2004), Dutch error messages, LOG2()" }, { "Marc Liyanage", "", "Created Mac OS X packages" }, + { "Kelly Long", "Denver, CO, USA", "Pool Of Threads" }, { "Zarko Mocnik", "", "Sorting for Slovenian language" }, { "Per-Erik Martin", "Uppsala, Sweden", "Stored Procedures (5.0)" }, { "Alexis Mikhailov", "", "User-defined functions" }, === modified file 'sql/item_sum.cc' --- a/sql/item_sum.cc 2010-08-20 11:22:46 +0000 +++ b/sql/item_sum.cc 2010-08-30 07:36:04 +0000 @@ -434,26 +434,6 @@ void Item_sum::mark_as_sum_func() } -void Item_sum::make_field(Send_field *tmp_field) -{ - if (args[0]->type() == Item::FIELD_ITEM && keep_field_type()) - { - ((Item_field*) args[0])->field->make_field(tmp_field); - /* For expressions only col_name should be non-empty string. */ - char *empty_string= (char*)""; - tmp_field->db_name= empty_string; - tmp_field->org_table_name= empty_string; - tmp_field->table_name= empty_string; - tmp_field->org_col_name= empty_string; - tmp_field->col_name= name; - if (maybe_null) - tmp_field->flags&= ~NOT_NULL_FLAG; - } - else - init_make_field(tmp_field, field_type()); -} - - void Item_sum::print(String *str, enum_query_type query_type) { /* orig_args is not filled with valid values until fix_fields() */ === modified file 'sql/item_sum.h' --- a/sql/item_sum.h 2010-07-19 17:11:47 +0000 +++ b/sql/item_sum.h 2010-08-30 07:36:04 +0000 @@ -427,7 +427,6 @@ public: forced_const= TRUE; } virtual bool const_item() const { return forced_const; } - void make_field(Send_field *field); virtual void print(String *str, enum_query_type query_type); void fix_num_length_and_dec(); === modified file 'sql/log.cc' --- a/sql/log.cc 2010-08-25 10:22:34 +0000 +++ b/sql/log.cc 2010-08-30 08:36:02 +0000 @@ -5447,70 +5447,93 @@ void sql_perror(const char *message) } +#ifdef __WIN__ +extern "C" my_bool reopen_fstreams(const char *filename, + FILE *outstream, FILE *errstream) +{ + int handle_fd; + int stream_fd; + HANDLE osfh; + + DBUG_ASSERT(filename && (outstream || errstream)); + + if ((osfh= CreateFile(filename, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE | + FILE_SHARE_DELETE, NULL, + OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, + NULL)) == INVALID_HANDLE_VALUE) + return TRUE; + + if ((handle_fd= _open_osfhandle((intptr_t)osfh, + _O_APPEND | _O_TEXT)) == -1) + { + CloseHandle(osfh); + return TRUE; + } + + if (outstream) + { + stream_fd= _fileno(outstream); + if (_dup2(handle_fd, stream_fd) < 0) + { + CloseHandle(osfh); + return TRUE; + } + } + + if (errstream) + { + stream_fd= _fileno(errstream); + if (_dup2(handle_fd, stream_fd) < 0) + { + CloseHandle(osfh); + return TRUE; + } + } + + _close(handle_fd); + return FALSE; +} +#else +extern "C" my_bool reopen_fstreams(const char *filename, + FILE *outstream, FILE *errstream) +{ + if (outstream && !freopen(filename, "a+", outstream)) + return TRUE; + + if (errstream && !freopen(filename, "a+", errstream)) + return TRUE; + + return FALSE; +} +#endif + + /* Unfortunately, there seems to be no good way to restore the original streams upon failure. */ static bool redirect_std_streams(const char *file) { - if (freopen(file, "a+", stdout) && freopen(file, "a+", stderr)) - { - setbuf(stderr, NULL); - return FALSE; - } + if (reopen_fstreams(file, stdout, stderr)) + return TRUE; - return TRUE; + setbuf(stderr, NULL); + return FALSE; } bool flush_error_log() { - bool result=0; + bool result= 0; if (opt_error_log) { - char err_renamed[FN_REFLEN], *end; - end= strmake(err_renamed,log_error_file,FN_REFLEN-5); - strmov(end, "-old"); mysql_mutex_lock(&LOCK_error_log); -#ifdef __WIN__ - char err_temp[FN_REFLEN+5]; - /* - On Windows is necessary a temporary file for to rename - the current error file. - */ - strxmov(err_temp, err_renamed,"-tmp",NullS); - my_delete(err_temp, MYF(0)); - if (freopen(err_temp,"a+",stdout)) - { - int fd; - size_t bytes; - uchar buf[IO_SIZE]; - - freopen(err_temp,"a+",stderr); - setbuf(stderr, NULL); - my_delete(err_renamed, MYF(0)); - my_rename(log_error_file, err_renamed, MYF(0)); - redirect_std_streams(log_error_file); - - if ((fd= my_open(err_temp, O_RDONLY, MYF(0))) >= 0) - { - while ((bytes= mysql_file_read(fd, buf, IO_SIZE, MYF(0))) && - bytes != MY_FILE_ERROR) - my_fwrite(stderr, buf, bytes, MYF(0)); - mysql_file_close(fd, MYF(0)); - } - my_delete(err_temp, MYF(0)); - } - else - result= 1; -#else - my_rename(log_error_file, err_renamed, MYF(0)); - if (redirect_std_streams(log_error_file)) - result= 1; -#endif + if (redirect_std_streams(log_error_file)) + result= 1; mysql_mutex_unlock(&LOCK_error_log); } - return result; + return result; } void MYSQL_BIN_LOG::signal_update() === modified file 'sql/mysqld.cc' --- a/sql/mysqld.cc 2010-08-25 19:00:38 +0000 +++ b/sql/mysqld.cc 2010-08-30 14:07:40 +0000 @@ -64,7 +64,9 @@ #include "events.h" #include "sql_audit.h" #include "probes_mysql.h" +#include "scheduler.h" #include "debug_sync.h" +#include "sql_callback.h" #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE #include "../storage/perfschema/pfs_server.h" @@ -193,6 +195,9 @@ typedef fp_except fp_except_t; # endif #endif +extern "C" my_bool reopen_fstreams(const char *filename, + FILE *outstream, FILE *errstream); + inline void setup_fpu() { #if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H) @@ -456,7 +461,7 @@ ulong slave_trans_retries; uint slave_net_timeout; ulong slave_exec_mode_options; ulonglong slave_type_conversions_options; -ulong thread_cache_size=0, thread_pool_size= 0; +ulong thread_cache_size=0; ulong binlog_cache_size=0; ulonglong max_binlog_cache_size=0; ulong query_cache_size=0; @@ -898,8 +903,6 @@ my_bool opt_enable_shared_memory; HANDLE smem_event_connect_request= 0; #endif -scheduler_functions thread_scheduler; - my_bool opt_use_ssl = 0; char *opt_ssl_ca= NULL, *opt_ssl_capath= NULL, *opt_ssl_cert= NULL, *opt_ssl_cipher= NULL, *opt_ssl_key= NULL; @@ -1087,7 +1090,8 @@ static void close_connections(void) continue; tmp->killed= THD::KILL_CONNECTION; - thread_scheduler.post_kill_notification(tmp); + MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (tmp)); + mysql_mutex_lock(&tmp->LOCK_thd_data); if (tmp->mysys_var) { tmp->mysys_var->abort=1; @@ -1100,6 +1104,7 @@ static void close_connections(void) } mysql_mutex_unlock(&tmp->mysys_var->mutex); } + mysql_mutex_unlock(&tmp->LOCK_thd_data); } mysql_mutex_unlock(&LOCK_thread_count); // For unlink from list @@ -1479,7 +1484,7 @@ void clean_up(bool print_message) if (print_message && my_default_lc_messages && server_start_time) sql_print_information(ER_DEFAULT(ER_SHUTDOWN_COMPLETE),my_progname); cleanup_errmsgs(); - thread_scheduler.end(); + MYSQL_CALLBACK(thread_scheduler, end, ()); finish_client_errs(); DBUG_PRINT("quit", ("Error messages freed")); /* Tell main we are ready */ @@ -1752,7 +1757,7 @@ static void network_init(void) DBUG_ENTER("network_init"); LINT_INIT(ret); - if (thread_scheduler.init()) + if (MYSQL_CALLBACK_ELSE(thread_scheduler, init, (), 0)) unireg_abort(1); /* purecov: inspected */ set_ports(); @@ -2000,7 +2005,7 @@ extern "C" sig_handler end_thread_signal if (thd && ! thd->bootstrap) { statistic_increment(killed_threads, &LOCK_status); - thread_scheduler.end_thread(thd,0); /* purecov: inspected */ + MYSQL_CALLBACK(thread_scheduler, end_thread, (thd,0)); /* purecov: inspected */ } DBUG_VOID_RETURN; /* purecov: deadcode */ } @@ -2396,7 +2401,7 @@ and this may fail.\n\n"); (ulong) dflt_key_cache->key_cache_mem_size); fprintf(stderr, "read_buffer_size=%ld\n", (long) global_system_variables.read_buff_size); fprintf(stderr, "max_used_connections=%lu\n", max_used_connections); - fprintf(stderr, "max_threads=%u\n", thread_scheduler.max_threads); + fprintf(stderr, "max_threads=%u\n", thread_scheduler->max_threads); fprintf(stderr, "thread_count=%u\n", thread_count); fprintf(stderr, "connection_count=%u\n", connection_count); fprintf(stderr, "It is possible that mysqld could use up to \n\ @@ -2404,7 +2409,7 @@ key_buffer_size + (read_buffer_size + so bytes of memory\n", ((ulong) dflt_key_cache->key_cache_mem_size + (global_system_variables.read_buff_size + global_system_variables.sortbuff_size) * - thread_scheduler.max_threads + + thread_scheduler->max_threads + max_connections * sizeof(THD)) / 1024); fprintf(stderr, "Hope that's ok; if not, decrease some variables in the equation.\n\n"); @@ -2651,7 +2656,7 @@ pthread_handler_t signal_hand(void *arg This should actually be '+ max_number_of_slaves' instead of +10, but the +10 should be quite safe. */ - init_thr_alarm(thread_scheduler.max_threads + + init_thr_alarm(thread_scheduler->max_threads + global_system_variables.max_insert_delayed_threads + 10); if (thd_lib_detected != THD_LIB_LT && (test_flags & TEST_SIGINT)) { @@ -3738,13 +3743,15 @@ static int init_server_components() opt_error_log= 0; // Too long file name else { + my_bool res; #ifndef EMBEDDED_LIBRARY - if (freopen(log_error_file, "a+", stdout)) + res= reopen_fstreams(log_error_file, stdout, stderr); +#else + res= reopen_fstreams(log_error_file, NULL, stderr); #endif - { - if (freopen(log_error_file, "a+", stderr)) - setbuf(stderr, NULL); - } + + if (!res) + setbuf(stderr, NULL); } } @@ -4353,23 +4360,6 @@ int mysqld_main(int argc, char **argv) } #endif -#ifdef __WIN__ - /* - Before performing any socket operation (like retrieving hostname - in init_common_variables we have to call WSAStartup - */ - { - WSADATA WsaData; - if (SOCKET_ERROR == WSAStartup (0x0101, &WsaData)) - { - /* errors are not read yet, so we use english text here */ - my_message(ER_WSAS_FAILED, "WSAStartup Failed", MYF(0)); - /* Not enough initializations for unireg_abort() */ - return 1; - } - } -#endif /* __WIN__ */ - if (init_common_variables()) unireg_abort(1); // Will do exit @@ -4457,8 +4447,8 @@ int mysqld_main(int argc, char **argv) #ifdef __WIN__ if (!opt_console) { - freopen(log_error_file,"a+",stdout); - freopen(log_error_file,"a+",stderr); + if (reopen_fstreams(log_error_file, stdout, stderr)) + unireg_abort(1); setbuf(stderr, NULL); FreeConsole(); // Remove window } @@ -5028,7 +5018,7 @@ static void create_new_thread(THD *thd) thread_count++; - thread_scheduler.add_connection(thd); + MYSQL_CALLBACK(thread_scheduler, add_connection, (thd)); DBUG_VOID_RETURN; } @@ -7344,14 +7334,12 @@ static int get_options(int *argc_ptr, ch return 1; #ifdef EMBEDDED_LIBRARY - one_thread_scheduler(&thread_scheduler); + one_thread_scheduler(); #else if (thread_handling <= SCHEDULER_ONE_THREAD_PER_CONNECTION) - one_thread_per_connection_scheduler(&thread_scheduler); - else if (thread_handling == SCHEDULER_NO_THREADS) - one_thread_scheduler(&thread_scheduler); - else - pool_of_threads_scheduler(&thread_scheduler); /* purecov: tested */ + one_thread_per_connection_scheduler(); + else /* thread_handling == SCHEDULER_NO_THREADS) */ + one_thread_scheduler(); #endif global_system_variables.engine_condition_pushdown= === modified file 'sql/mysqld.h' --- a/sql/mysqld.h 2010-08-18 11:29:04 +0000 +++ b/sql/mysqld.h 2010-08-30 14:07:40 +0000 @@ -28,7 +28,7 @@ class THD; struct handlerton; class Time_zone; -class scheduler_functions; +struct scheduler_functions; typedef struct st_mysql_const_lex_string LEX_CSTRING; typedef struct st_mysql_show_var SHOW_VAR; @@ -175,7 +175,7 @@ extern ulong binlog_cache_size, open_fil extern ulonglong max_binlog_cache_size; extern ulong max_binlog_size, max_relay_log_size; extern ulong opt_binlog_rows_event_max_size; -extern ulong rpl_recovery_rank, thread_cache_size, thread_pool_size; +extern ulong rpl_recovery_rank, thread_cache_size; extern ulong back_log; extern char language[FN_REFLEN]; extern ulong server_id, concurrency; @@ -207,7 +207,7 @@ extern my_bool old_mode; extern LEX_STRING opt_init_connect, opt_init_slave; extern int bootstrap_error; extern I_List threads; -extern scheduler_functions thread_scheduler; +extern char err_shared_dir[]; extern TYPELIB thread_handling_typelib; extern my_decimal decimal_zero; === modified file 'sql/opt_range.cc' --- a/sql/opt_range.cc 2010-07-15 13:47:50 +0000 +++ b/sql/opt_range.cc 2010-08-26 12:35:38 +0000 @@ -5620,7 +5620,11 @@ static SEL_TREE *get_mm_tree(RANGE_OPT_P SEL_TREE *tmp= get_full_func_mm_tree(param, cond_func, field_item, (Item*)(intptr)i, inv); if (inv) + { tree= !tree ? tmp : tree_or(param, tree, tmp); + if (tree == NULL) + break; + } else tree= tree_and(param, tree, tmp); } === modified file 'sql/scheduler.cc' --- a/sql/scheduler.cc 2010-03-31 14:05:33 +0000 +++ b/sql/scheduler.cc 2010-06-15 07:44:26 +0000 @@ -25,55 +25,103 @@ #include "unireg.h" // REQUIRED: for other includes #include "scheduler.h" #include "sql_connect.h" // init_new_connection_handler_thread +#include "scheduler.h" +#include "sql_callback.h" /* - 'Dummy' functions to be used when we don't need any handling for a scheduler - event - */ + End connection, in case when we are using 'no-threads' +*/ -static bool init_dummy(void) {return 0;} -static void post_kill_dummy(THD* thd) {} -static void end_dummy(void) {} -static bool end_thread_dummy(THD *thd, bool cache_thread) { return 0; } +static bool no_threads_end(THD *thd, bool put_in_cache) +{ + unlink_thd(thd); + mysql_mutex_unlock(&LOCK_thread_count); + return 1; // Abort handle_one_connection +} -/* - Initialize default scheduler with dummy functions so that setup functions - only need to declare those that are relvant for their usage +static scheduler_functions one_thread_scheduler_functions= +{ + 1, // max_threads + NULL, // init + init_new_connection_handler_thread, // init_new_connection_thread +#ifndef EMBEDDED_LIBRARY + handle_connection_in_main_thread, // add_connection +#else + NULL, // add_connection +#endif // EMBEDDED_LIBRARY + NULL, // thd_wait_begin + NULL, // thd_wait_end + NULL, // post_kill_notification + no_threads_end, // end_thread + NULL, // end +}; + +#ifndef EMBEDDED_LIBRARY +static scheduler_functions one_thread_per_connection_scheduler_functions= +{ + 0, // max_threads + NULL, // init + init_new_connection_handler_thread, // init_new_connection_thread + create_thread_to_handle_connection, // add_connection + NULL, // thd_wait_begin + NULL, // thd_wait_end + NULL, // post_kill_notification + one_thread_per_connection_end, // end_thread + NULL, // end +}; +#endif // EMBEDDED_LIBRARY + + +scheduler_functions *thread_scheduler= NULL; + +/** @internal + Helper functions to allow mysys to call the thread scheduler when + waiting for locks. */ -scheduler_functions::scheduler_functions() - :init(init_dummy), - init_new_connection_thread(init_new_connection_handler_thread), - add_connection(0), // Must be defined - post_kill_notification(post_kill_dummy), - end_thread(end_thread_dummy), end(end_dummy) -{} +/**@{*/ +static void scheduler_wait_begin(void) { + MYSQL_CALLBACK(thread_scheduler, + thd_wait_begin, (current_thd, THD_WAIT_ROW_TABLE_LOCK)); +} + +static void scheduler_wait_end(void) { + MYSQL_CALLBACK(thread_scheduler, thd_wait_end, (current_thd)); +} +/**@}*/ +/** + Common scheduler init function. + + The scheduler is either initialized by calling + one_thread_scheduler() or one_thread_per_connection_scheduler() in + mysqld.cc, so this init function will always be called. + */ +static void scheduler_init() { + thr_set_lock_wait_callback(scheduler_wait_begin, scheduler_wait_end); +} /* - End connection, in case when we are using 'no-threads' + Initialize scheduler for --thread-handling=one-thread-per-connection */ -static bool no_threads_end(THD *thd, bool put_in_cache) +#ifndef EMBEDDED_LIBRARY +void one_thread_per_connection_scheduler() { - unlink_thd(thd); - mysql_mutex_unlock(&LOCK_thread_count); - return 1; // Abort handle_one_connection + scheduler_init(); + one_thread_per_connection_scheduler_functions.max_threads= max_connections; + thread_scheduler= &one_thread_per_connection_scheduler_functions; } - +#endif /* Initailize scheduler for --thread-handling=no-threads */ -void one_thread_scheduler(scheduler_functions* func) +void one_thread_scheduler() { - func->max_threads= 1; -#ifndef EMBEDDED_LIBRARY - func->add_connection= handle_connection_in_main_thread; -#endif - func->init_new_connection_thread= init_dummy; - func->end_thread= no_threads_end; + scheduler_init(); + thread_scheduler= &one_thread_scheduler_functions; } @@ -81,11 +129,58 @@ void one_thread_scheduler(scheduler_func Initialize scheduler for --thread-handling=one-thread-per-connection */ -#ifndef EMBEDDED_LIBRARY -void one_thread_per_connection_scheduler(scheduler_functions* func) +/* + thd_scheduler keeps the link between THD and events. + It's embedded in the THD class. +*/ + +thd_scheduler::thd_scheduler() + : m_psi(NULL), data(NULL) +{ +#ifndef DBUG_OFF + dbug_explain[0]= '\0'; + set_explain= FALSE; +#endif +} + + +thd_scheduler::~thd_scheduler() +{ +} + +static scheduler_functions *saved_thread_scheduler; +static uint saved_thread_handling; + +extern "C" +int my_thread_scheduler_set(scheduler_functions *scheduler) +{ + DBUG_ASSERT(scheduler != 0); + + if (scheduler == NULL) + return 1; + + saved_thread_scheduler= thread_scheduler; + saved_thread_handling= thread_handling; + thread_scheduler= scheduler; + // Scheduler loaded dynamically + thread_handling= SCHEDULER_TYPES_COUNT; + return 0; +} + + +extern "C" +int my_thread_scheduler_reset() { - func->max_threads= max_connections; - func->add_connection= create_thread_to_handle_connection; - func->end_thread= one_thread_per_connection_end; + DBUG_ASSERT(saved_thread_scheduler != NULL); + + if (saved_thread_scheduler == NULL) + return 1; + + thread_scheduler= saved_thread_scheduler; + thread_handling= saved_thread_handling; + saved_thread_scheduler= 0; + return 0; } -#endif /* EMBEDDED_LIBRARY */ + + + === modified file 'sql/scheduler.h' --- a/sql/scheduler.h 2009-09-23 21:32:31 +0000 +++ b/sql/scheduler.h 2010-06-07 14:01:39 +0000 @@ -28,38 +28,77 @@ class THD; /* Functions used when manipulating threads */ -class scheduler_functions +struct scheduler_functions { -public: uint max_threads; bool (*init)(void); bool (*init_new_connection_thread)(void); void (*add_connection)(THD *thd); + void (*thd_wait_begin)(THD *thd, int wait_type); + void (*thd_wait_end)(THD *thd); void (*post_kill_notification)(THD *thd); bool (*end_thread)(THD *thd, bool cache_thread); void (*end)(void); - scheduler_functions(); }; + +/** + Scheduler types enumeration. + + The default of --thread-handling is the first one in the + thread_handling_names array, this array has to be consistent with + the order in this array, so to change default one has to change the + first entry in this enum and the first entry in the + thread_handling_names array. + + @note The last entry of the enumeration is also used to mark the + thread handling as dynamic. In this case the name of the thread + handling is fetched from the name of the plugin that implements it. +*/ enum scheduler_types { SCHEDULER_ONE_THREAD_PER_CONNECTION=0, SCHEDULER_NO_THREADS, - SCHEDULER_POOL_OF_THREADS + SCHEDULER_TYPES_COUNT }; -void one_thread_per_connection_scheduler(scheduler_functions* func); -void one_thread_scheduler(scheduler_functions* func); +void one_thread_per_connection_scheduler(); +void one_thread_scheduler(); enum pool_command_op { NOT_IN_USE_OP= 0, NORMAL_OP= 1, CONNECT_OP, KILL_OP, DIE_OP }; -#define HAVE_POOL_OF_THREADS 0 /* For easyer tests */ -#define pool_of_threads_scheduler(A) one_thread_per_connection_scheduler(A) - +/* + To be used for pool-of-threads (implemeneted differently on various OSs) +*/ class thd_scheduler -{}; +{ +public: + /* + Thread instrumentation for the user job. + This member holds the instrumentation while the user job is not run + by a thread. + + Note that this member is not conditionally declared + (ifdef HAVE_PSI_INTERFACE), because doing so will change the binary + layout of THD, which is exposed to plugin code that may be compiled + differently. + */ + PSI_thread *m_psi; + + void *data; /* scheduler-specific data structure */ + +# ifndef DBUG_OFF + char dbug_explain[512]; + bool set_explain; +# endif + + thd_scheduler(); + ~thd_scheduler(); +}; + +extern scheduler_functions *thread_scheduler; -#endif /* SCHEDULER_INCLUDED */ +#endif === added file 'sql/sql_callback.h' --- a/sql/sql_callback.h 1970-01-01 00:00:00 +0000 +++ b/sql/sql_callback.h 2010-06-07 14:01:39 +0000 @@ -0,0 +1,43 @@ +/* + Copyright (C) 2010, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef SQL_CALLBACK_INCLUDED +#define SQL_CALLBACK_INCLUDED + +/** + Macro used for an internal callback. + + The macro will check that the object exists and that the function + is defined. If that is the case, it will call the function with the + given parameters. + + If the object or the function is not defined, the callback will be + considered successful (nothing needed to be done) and will + therefore return no error. + */ + +#define MYSQL_CALLBACK(OBJ, FUNC, PARAMS) \ + do { \ + if ((OBJ) && ((OBJ)->FUNC)) \ + (OBJ)->FUNC PARAMS; \ + } while (0) + +#define MYSQL_CALLBACK_ELSE(OBJ, FUNC, PARAMS, ELSE) \ + (((OBJ) && ((OBJ)->FUNC)) ? (OBJ)->FUNC PARAMS : (ELSE)) + + +#endif /* SQL_CALLBACK_INCLUDED */ === modified file 'sql/sql_class.cc' --- a/sql/sql_class.cc 2010-08-20 02:59:58 +0000 +++ b/sql/sql_class.cc 2010-08-30 14:07:40 +0000 @@ -57,6 +57,7 @@ #include "transaction.h" #include "debug_sync.h" #include "sql_parse.h" // is_update_query +#include "sql_callback.h" /* The following is used to initialise Table_ident with a internal @@ -1075,6 +1076,7 @@ THD::~THD() DBUG_ENTER("~THD()"); /* Ensure that no one is using THD */ mysql_mutex_lock(&LOCK_thd_data); + mysys_var=0; // Safety (shouldn't be needed) mysql_mutex_unlock(&LOCK_thd_data); add_to_status(&global_status_var, &status_var); @@ -1100,7 +1102,6 @@ THD::~THD() my_free(db); db= NULL; free_root(&transaction.mem_root,MYF(0)); - mysys_var=0; // Safety (shouldn't be needed) mysql_mutex_destroy(&LOCK_thd_data); #ifndef DBUG_OFF dbug_sentry= THD_SENTRY_GONE; @@ -1189,7 +1190,7 @@ void THD::awake(THD::killed_state state_ { thr_alarm_kill(thread_id); if (!slave_thread) - thread_scheduler.post_kill_notification(this); + MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (this)); #ifdef SIGNAL_WITH_VIO_CLOSE if (this != current_thd) { @@ -1258,6 +1259,15 @@ bool THD::store_globals() if (my_pthread_setspecific_ptr(THR_THD, this) || my_pthread_setspecific_ptr(THR_MALLOC, &mem_root)) return 1; + /* + mysys_var is concurrently readable by a killer thread. + It is protected by LOCK_thd_data, it is not needed to lock while the + pointer is changing from NULL not non-NULL. If the kill thread reads + NULL it doesn't refer to anything, but if it is non-NULL we need to + ensure that the thread doesn't proceed to assign another thread to + have the mysys_var reference (which in fact refers to the worker + threads local storage with key THR_KEY_mysys. + */ mysys_var=my_thread_var; /* Let mysqld define the thread id (not mysys) @@ -3187,6 +3197,60 @@ extern "C" bool thd_sqlcom_can_generate_ { return sqlcom_can_generate_row_events(thd); } + +#ifndef EMBEDDED_LIBRARY +extern "C" void thd_pool_wait_begin(MYSQL_THD thd, int wait_type); +extern "C" void thd_pool_wait_end(MYSQL_THD thd); + +/* + Interface for MySQL Server, plugins and storage engines to report + when they are going to sleep/stall. + + SYNOPSIS + thd_wait_begin() + thd Thread object + wait_type Type of wait + 1 -- short wait (e.g. for mutex) + 2 -- medium wait (e.g. for disk io) + 3 -- large wait (e.g. for locked row/table) + NOTES + This is used by the threadpool to have better knowledge of which + threads that currently are actively running on CPUs. When a thread + reports that it's going to sleep/stall, the threadpool scheduler is + free to start another thread in the pool most likely. The expected wait + time is simply an indication of how long the wait is expected to + become, the real wait time could be very different. + + thd_wait_end MUST be called immediately after waking up again. +*/ +extern "C" void thd_wait_begin(MYSQL_THD thd, thd_wait_type wait_type) +{ + MYSQL_CALLBACK(thread_scheduler, thd_wait_begin, (thd, wait_type)); +} + +/** + Interface for MySQL Server, plugins and storage engines to report + when they waking up from a sleep/stall. + + @param thd Thread handle +*/ +extern "C" void thd_wait_end(MYSQL_THD thd) +{ + MYSQL_CALLBACK(thread_scheduler, thd_wait_end, (thd)); +} +#else +extern "C" void thd_wait_begin(MYSQL_THD thd, thd_wait_type wait_type) +{ + /* do NOTHING for the embedded library */ + return; +} + +extern "C" void thd_wait_end(MYSQL_THD thd) +{ + /* do NOTHING for the embedded library */ + return; +} +#endif #endif // INNODB_COMPATIBILITY_HOOKS */ /**************************************************************************** @@ -3370,6 +3434,13 @@ void THD::set_query_id(query_id_t new_qu mysql_mutex_unlock(&LOCK_thd_data); } +/** Assign a new value to thd->mysys_var. */ +void THD::set_mysys_var(struct st_my_thread_var *new_mysys_var) +{ + mysql_mutex_lock(&LOCK_thd_data); + mysys_var= new_mysys_var; + mysql_mutex_unlock(&LOCK_thd_data); +} /** Leave explicit LOCK TABLES or prelocked mode and restore value of === modified file 'sql/sql_class.h' --- a/sql/sql_class.h 2010-08-25 10:22:34 +0000 +++ b/sql/sql_class.h 2010-08-30 14:07:40 +0000 @@ -1634,6 +1634,10 @@ public: xid_state.xid.null(); free_root(&mem_root,MYF(MY_KEEP_PREALLOC)); } + my_bool is_active() + { + return (all.ha_list != NULL); + } st_transactions() { bzero((char*)this, sizeof(*this)); @@ -2664,7 +2668,7 @@ public: virtual void set_statement(Statement *stmt); /** - Assign a new value to thd->query and thd->query_id. + Assign a new value to thd->query and thd->query_id and mysys_var. Protected with LOCK_thd_data mutex. */ void set_query(char *query_arg, uint32 query_length_arg); @@ -2677,6 +2681,7 @@ public: open_tables= open_tables_arg; mysql_mutex_unlock(&LOCK_thd_data); } + void set_mysys_var(struct st_my_thread_var *new_mysys_var); void enter_locked_tables_mode(enum_locked_tables_mode mode_arg) { DBUG_ASSERT(locked_tables_mode == LTM_NONE); === modified file 'sql/sql_connect.cc' --- a/sql/sql_connect.cc 2010-08-05 12:53:09 +0000 +++ b/sql/sql_connect.cc 2010-08-16 12:50:27 +0000 @@ -35,6 +35,7 @@ #include "hostname.h" // inc_host_errors, ip_to_hostname, // reset_host_errors #include "sql_acl.h" // acl_getroot, NO_ACCESS, SUPER_ACL +#include "sql_callback.h" #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) /* @@ -966,7 +967,7 @@ bool setup_connection_thread_globals(THD { close_connection(thd, ER_OUT_OF_RESOURCES, 1); statistic_increment(aborted_connects,&LOCK_status); - thread_scheduler.end_thread(thd, 0); + MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0)); return 1; // Error } return 0; @@ -989,7 +990,7 @@ bool setup_connection_thread_globals(THD */ -static bool login_connection(THD *thd) +bool login_connection(THD *thd) { NET *net= &thd->net; int error; @@ -1027,7 +1028,7 @@ static bool login_connection(THD *thd) This mainly updates status variables */ -static void end_connection(THD *thd) +void end_connection(THD *thd) { NET *net= &thd->net; plugin_thdvar_cleanup(thd); @@ -1068,7 +1069,7 @@ static void end_connection(THD *thd) Initialize THD to handle queries */ -static void prepare_new_connection_state(THD* thd) +void prepare_new_connection_state(THD* thd) { Security_context *sctx= thd->security_ctx; @@ -1137,11 +1138,11 @@ void do_handle_one_connection(THD *thd_a thd->thr_create_utime= my_micro_time(); - if (thread_scheduler.init_new_connection_thread()) + if (MYSQL_CALLBACK_ELSE(thread_scheduler, init_new_connection_thread, (), 0)) { close_connection(thd, ER_OUT_OF_RESOURCES, 1); statistic_increment(aborted_connects,&LOCK_status); - thread_scheduler.end_thread(thd,0); + MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0)); return; } @@ -1195,7 +1196,7 @@ void do_handle_one_connection(THD *thd_a end_thread: close_connection(thd, 0, 1); - if (thread_scheduler.end_thread(thd,1)) + if (MYSQL_CALLBACK_ELSE(thread_scheduler, end_thread, (thd, 1), 0)) return; // Probably no-threads /* === modified file 'sql/sql_connect.h' --- a/sql/sql_connect.h 2010-03-31 14:05:33 +0000 +++ b/sql/sql_connect.h 2010-06-07 14:01:39 +0000 @@ -40,4 +40,8 @@ int check_user(THD *thd, enum enum_serve const char *passwd, uint passwd_len, const char *db, bool check_count); +bool login_connection(THD *thd); +void prepare_new_connection_state(THD* thd); +void end_connection(THD *thd); + #endif /* SQL_CONNECT_INCLUDED */ === modified file 'sql/sql_plugin_services.h' --- a/sql/sql_plugin_services.h 2009-11-02 20:05:42 +0000 +++ b/sql/sql_plugin_services.h 2010-06-07 14:01:39 +0000 @@ -36,9 +36,23 @@ static struct thd_alloc_service_st thd_a thd_make_lex_string }; +static struct thd_wait_service_st thd_wait_handler= { + thd_wait_begin, + thd_wait_end +}; + +static struct my_thread_scheduler_service my_thread_scheduler_handler= { + my_thread_scheduler_set, + my_thread_scheduler_reset, +}; + + static struct st_service_ref list_of_services[]= { { "my_snprintf_service", VERSION_my_snprintf, &my_snprintf_handler }, - { "thd_alloc_service", VERSION_thd_alloc, &thd_alloc_handler } + { "thd_alloc_service", VERSION_thd_alloc, &thd_alloc_handler }, + { "thd_wait_service", VERSION_thd_wait, &thd_wait_handler }, + { "my_thread_scheduler_service", + VERSION_my_thread_scheduler, &my_thread_scheduler_handler }, }; === modified file 'sql/sql_select.cc' --- a/sql/sql_select.cc 2010-08-17 12:12:52 +0000 +++ b/sql/sql_select.cc 2010-08-27 11:33:32 +0000 @@ -13243,6 +13243,34 @@ ok: } +/** + Find shortest key suitable for full table scan. + + @param table Table to scan + @param usable_keys Allowed keys + + @note + As far as + 1) clustered primary key entry data set is a set of all record + fields (key fields and not key fields) and + 2) secondary index entry data is a union of its key fields and + primary key fields (at least InnoDB and its derivatives don't + duplicate primary key fields there, even if the primary and + the secondary keys have a common subset of key fields), + then secondary index entry data is always a subset of primary key entry. + Unfortunately, key_info[nr].key_length doesn't show the length + of key/pointer pair but a sum of key field lengths only, thus + we can't estimate index IO volume comparing only this key_length + value of secondary keys and clustered PK. + So, try secondary keys first, and choose PK only if there are no + usable secondary covering keys or found best secondary key include + all table fields (i.e. same as PK): + + @return + MAX_KEY no suitable key found + key index otherwise +*/ + uint find_shortest_key(TABLE *table, const key_map *usable_keys) { uint best= MAX_KEY; @@ -13255,23 +13283,6 @@ uint find_shortest_key(TABLE *table, con uint min_length= (uint) ~0; for (uint nr=0; nr < table->s->keys ; nr++) { - /* - As far as - 1) clustered primary key entry data set is a set of all record - fields (key fields and not key fields) and - 2) secondary index entry data is a union of its key fields and - primary key fields (at least InnoDB and its derivatives don't - duplicate primary key fields there, even if the primary and - the secondary keys have a common subset of key fields), - then secondary index entry data is always a subset of primary key - entry, and the PK is always longer. - Unfortunately, key_info[nr].key_length doesn't show the length - of key/pointer pair but a sum of key field lengths only, thus - we can't estimate index IO volume comparing only this key_length - value of seconday keys and clustered PK. - So, try secondary keys first, and choose PK only if there are no - usable secondary covering keys: - */ if (nr == usable_clustered_pk) continue; if (usable_keys->is_set(nr)) @@ -13284,7 +13295,20 @@ uint find_shortest_key(TABLE *table, con } } } - return best != MAX_KEY ? best : usable_clustered_pk; + if (usable_clustered_pk != MAX_KEY) + { + /* + If the primary key is clustered and found shorter key covers all table + fields then primary key scan normally would be faster because amount of + data to scan is the same but PK is clustered. + It's safe to compare key parts with table fields since duplicate key + parts aren't allowed. + */ + if (best == MAX_KEY || + table->key_info[best].key_parts >= table->s->fields) + best= usable_clustered_pk; + } + return best; } /** === modified file 'sql/sql_show.cc' --- a/sql/sql_show.cc 2010-08-18 11:29:04 +0000 +++ b/sql/sql_show.cc 2010-08-30 14:07:40 +0000 @@ -1815,6 +1815,7 @@ void mysqld_list_processes(THD *thd,cons if ((thd_info->db=tmp->db)) // Safe test thd_info->db=thd->strdup(thd_info->db); thd_info->command=(int) tmp->command; + mysql_mutex_lock(&tmp->LOCK_thd_data); if ((mysys_var= tmp->mysys_var)) mysql_mutex_lock(&mysys_var->mutex); thd_info->proc_info= (char*) (tmp->killed == THD::KILL_CONNECTION? "Killed" : 0); @@ -1822,16 +1823,15 @@ void mysqld_list_processes(THD *thd,cons if (mysys_var) mysql_mutex_unlock(&mysys_var->mutex); - thd_info->start_time= tmp->start_time; thd_info->query=0; /* Lock THD mutex that protects its data when looking at it. */ - mysql_mutex_lock(&tmp->LOCK_thd_data); if (tmp->query()) { uint length= min(max_query_length, tmp->query_length()); thd_info->query= (char*) thd->strmake(tmp->query(),length); } mysql_mutex_unlock(&tmp->LOCK_thd_data); + thd_info->start_time= tmp->start_time; thread_infos.append(thd_info); } } @@ -1918,6 +1918,7 @@ int fill_schema_processlist(THD* thd, TA table->field[3]->set_notnull(); } + mysql_mutex_lock(&tmp->LOCK_thd_data); if ((mysys_var= tmp->mysys_var)) mysql_mutex_lock(&mysys_var->mutex); /* COMMAND */ @@ -1938,6 +1939,7 @@ int fill_schema_processlist(THD* thd, TA if (mysys_var) mysql_mutex_unlock(&mysys_var->mutex); + mysql_mutex_unlock(&tmp->LOCK_thd_data); /* INFO */ /* Lock THD mutex that protects its data when looking at it. */ @@ -7490,13 +7492,16 @@ int finalize_schema_table(st_plugin_int ST_SCHEMA_TABLE *schema_table= (ST_SCHEMA_TABLE *)plugin->data; DBUG_ENTER("finalize_schema_table"); - if (schema_table && plugin->plugin->deinit) + if (schema_table) { - DBUG_PRINT("info", ("Deinitializing plugin: '%s'", plugin->name.str)); - if (plugin->plugin->deinit(NULL)) + if (plugin->plugin->deinit) { - DBUG_PRINT("warning", ("Plugin '%s' deinit function returned error.", - plugin->name.str)); + DBUG_PRINT("info", ("Deinitializing plugin: '%s'", plugin->name.str)); + if (plugin->plugin->deinit(NULL)) + { + DBUG_PRINT("warning", ("Plugin '%s' deinit function returned error.", + plugin->name.str)); + } } my_free(schema_table); } === modified file 'sql/sql_yacc.yy' --- a/sql/sql_yacc.yy 2010-08-25 10:22:34 +0000 +++ b/sql/sql_yacc.yy 2010-08-30 22:22:01 +0000 @@ -1425,6 +1425,7 @@ bool my_yyoverflow(short **a, YYSTYPE ** %type table_ident table_ident_nodb references xid + table_ident_opt_wild %type remember_name remember_end opt_db text_or_password @@ -10371,7 +10372,7 @@ table_alias_ref_list: ; table_alias_ref: - table_ident + table_ident_opt_wild { if (!Select->add_table_to_list(YYTHD, $1, NULL, TL_OPTION_UPDATING | TL_OPTION_ALIAS, @@ -12159,6 +12160,21 @@ table_ident: if ($$ == NULL) MYSQL_YYABORT; } + ; + +table_ident_opt_wild: + ident opt_wild + { + $$= new Table_ident($1); + if ($$ == NULL) + MYSQL_YYABORT; + } + | ident '.' ident opt_wild + { + $$= new Table_ident(YYTHD, $1,$3,0); + if ($$ == NULL) + MYSQL_YYABORT; + } ; table_ident_nodb: === modified file 'sql/sys_vars.cc' --- a/sql/sys_vars.cc 2010-08-25 00:21:43 +0000 +++ b/sql/sys_vars.cc 2010-08-30 14:07:40 +0000 @@ -1673,19 +1673,13 @@ static Sys_var_ulong Sys_trans_prealloc_ static const char *thread_handling_names[]= { - "one-thread-per-connection", "no-threads", -#if HAVE_POOL_OF_THREADS == 1 - "pool-of-threads", -#endif + "one-thread-per-connection", "no-threads", "loaded-dynamically", 0 }; static Sys_var_enum Sys_thread_handling( "thread_handling", "Define threads usage for handling queries, one of " - "one-thread-per-connection, no-threads" -#if HAVE_POOL_OF_THREADS == 1 - ", pool-of-threads" -#endif + "one-thread-per-connection, no-threads, loaded-dynamically" , READ_ONLY GLOBAL_VAR(thread_handling), CMD_LINE(REQUIRED_ARG), thread_handling_names, DEFAULT(0)); === modified file 'storage/innobase/buf/buf0flu.c' --- a/storage/innobase/buf/buf0flu.c 2010-07-30 14:39:16 +0000 +++ b/storage/innobase/buf/buf0flu.c 2010-08-30 14:07:40 +0000 @@ -43,6 +43,8 @@ Created 11/11/1995 Heikki Tuuri #include "log0log.h" #include "os0file.h" #include "trx0sys.h" +#include "mysql/plugin.h" +#include "mysql/service_thd_wait.h" /********************************************************************** These statistics are generated for heuristics used in estimating the @@ -1744,10 +1746,14 @@ buf_flush_wait_batch_end( buf_pool = buf_pool_from_array(i); + thd_wait_begin(NULL, THD_WAIT_DISKIO); os_event_wait(buf_pool->no_flush[type]); + thd_wait_end(NULL); } } else { + thd_wait_begin(NULL, THD_WAIT_DISKIO); os_event_wait(buf_pool->no_flush[type]); + thd_wait_end(NULL); } } === modified file 'storage/innobase/buf/buf0rea.c' --- a/storage/innobase/buf/buf0rea.c 2010-06-22 15:58:28 +0000 +++ b/storage/innobase/buf/buf0rea.c 2010-08-16 12:50:27 +0000 @@ -37,6 +37,8 @@ Created 11/5/1995 Heikki Tuuri #include "os0file.h" #include "srv0start.h" #include "srv0srv.h" +#include "mysql/plugin.h" +#include "mysql/service_thd_wait.h" /** The linear read-ahead area size */ #define BUF_READ_AHEAD_LINEAR_AREA BUF_READ_AHEAD_AREA @@ -135,6 +137,7 @@ buf_read_page_low( ut_ad(buf_page_in_file(bpage)); + thd_wait_begin(NULL, THD_WAIT_DISKIO); if (zip_size) { *err = fil_io(OS_FILE_READ | wake_later, sync, space, zip_size, offset, 0, zip_size, @@ -146,6 +149,7 @@ buf_read_page_low( sync, space, 0, offset, 0, UNIV_PAGE_SIZE, ((buf_block_t*) bpage)->frame, bpage); } + thd_wait_end(NULL); ut_a(*err == DB_SUCCESS); if (sync) { === modified file 'storage/innobase/srv/srv0srv.c' --- a/storage/innobase/srv/srv0srv.c 2010-08-17 08:19:24 +0000 +++ b/storage/innobase/srv/srv0srv.c 2010-08-30 14:07:40 +0000 @@ -84,6 +84,8 @@ Created 10/8/1995 Heikki Tuuri #include "ha_prototypes.h" #include "trx0i_s.h" #include "os0sync.h" /* for HAVE_ATOMIC_BUILTINS */ +#include "mysql/plugin.h" +#include "mysql/service_thd_wait.h" /* This is set to TRUE if the MySQL user has set it in MySQL; currently affects only FOREIGN KEY definition parsing */ @@ -1232,7 +1234,9 @@ retry: trx->op_info = "waiting in InnoDB queue"; + thd_wait_begin(trx->mysql_thd, THD_WAIT_ROW_TABLE_LOCK); os_event_wait(slot->event); + thd_wait_end(trx->mysql_thd); trx->op_info = ""; @@ -1597,7 +1601,9 @@ srv_suspend_mysql_thread( /* Suspend this thread and wait for the event. */ + thd_wait_begin(trx->mysql_thd, THD_WAIT_ROW_TABLE_LOCK); os_event_wait(event); + thd_wait_end(trx->mysql_thd); /* After resuming, reacquire the data dictionary latch if necessary. */ === modified file 'vio/vio.c' --- a/vio/vio.c 2010-07-08 21:20:08 +0000 +++ b/vio/vio.c 2010-08-16 12:50:27 +0000 @@ -44,6 +44,11 @@ static my_bool no_poll_read(Vio *vio __a #endif +static my_bool has_no_data(Vio *vio __attribute__((unused))) +{ + return FALSE; +} + /* * Helper to fill most of the Vio* with defaults. */ @@ -83,6 +88,7 @@ static void vio_init(Vio* vio, enum enum vio->poll_read =no_poll_read; vio->is_connected =vio_is_connected_pipe; + vio->has_data =has_no_data; vio->timeout=vio_win32_timeout; /* Set default timeout */ @@ -110,6 +116,7 @@ static void vio_init(Vio* vio, enum enum vio->poll_read =no_poll_read; vio->is_connected =vio_is_connected_shared_memory; + vio->has_data =has_no_data; /* Currently, shared memory is on Windows only, hence the below is ok*/ vio->timeout= vio_win32_timeout; @@ -137,6 +144,7 @@ static void vio_init(Vio* vio, enum enum vio->timeout =vio_timeout; vio->poll_read =vio_poll_read; vio->is_connected =vio_is_connected; + vio->has_data =vio_ssl_has_data; DBUG_VOID_RETURN; } #endif /* HAVE_OPENSSL */ @@ -155,6 +163,8 @@ static void vio_init(Vio* vio, enum enum vio->timeout =vio_timeout; vio->poll_read =vio_poll_read; vio->is_connected =vio_is_connected; + vio->has_data= (flags & VIO_BUFFERED_READ) ? + vio_buff_has_data : has_no_data; DBUG_VOID_RETURN; } === modified file 'vio/vio_priv.h' --- a/vio/vio_priv.h 2009-12-16 08:33:54 +0000 +++ b/vio/vio_priv.h 2010-06-07 14:01:39 +0000 @@ -49,6 +49,7 @@ int vio_close_shared_memory(Vio * vio); #endif void vio_timeout(Vio *vio,uint which, uint timeout); +my_bool vio_buff_has_data(Vio *vio); #ifdef HAVE_OPENSSL #include "my_net.h" /* needed because of struct in_addr */ @@ -62,5 +63,7 @@ void vio_ssl_delete(Vio *vio); int vio_ssl_blocking(Vio *vio, my_bool set_blocking_mode, my_bool *old_mode); +my_bool vio_ssl_has_data(Vio *vio); + #endif /* HAVE_OPENSSL */ #endif /* VIO_PRIV_INCLUDED */ === modified file 'vio/viosocket.c' --- a/vio/viosocket.c 2010-05-21 13:17:01 +0000 +++ b/vio/viosocket.c 2010-08-16 12:50:27 +0000 @@ -98,6 +98,10 @@ size_t vio_read_buff(Vio *vio, uchar* bu #undef VIO_UNBUFFERED_READ_MIN_SIZE } +my_bool vio_buff_has_data(Vio *vio) +{ + return (vio->read_pos != vio->read_end); +} size_t vio_write(Vio * vio, const uchar* buf, size_t size) { === modified file 'vio/viossl.c' --- a/vio/viossl.c 2010-07-15 11:13:30 +0000 +++ b/vio/viossl.c 2010-08-16 12:50:27 +0000 @@ -244,6 +244,9 @@ int vio_ssl_blocking(Vio *vio __attribut return (set_blocking_mode ? 0 : 1); } - +my_bool vio_ssl_has_data(Vio *vio) +{ + return SSL_pending(vio->ssl_arg) > 0 ? TRUE : FALSE; +} #endif /* HAVE_OPENSSL */ --===============1831463695== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/bjorn.munch@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: bjorn.munch@stripped # target_branch: file:///home/bm136801/my/mtr-55/ # testament_sha1: ddd06fccd7a3e9880b93cf7340dba118ab1b36d2 # timestamp: 2010-09-01 15:50:45 +0200 # source_branch: file:///home/bm136801/my/mysql-5.5/ # base_revision_id: bjorn.munch@stripped\ # 1fnvzg7oldv64ia9 # # Begin bundle IyBCYXphYXIgcmV2aXNpb24gYnVuZGxlIHY0CiMKQlpoOTFBWSZTWfKS8GQAh9N/gH/7p03///// ////7v////9grz71deWu8d7B92PqeLWKGtB3V8PNosBez2AKACgA8AeXFSJEO29q0J9fXAivifMp 1d55O7LRO51FT5ttNUx6d77ZN9rtHvfTvQnbVXzlAJAya0BneinffHz3eEgfbElBQUfbKr7eDup2 ApR61VEhX0ec+HaAACilCg7ZZbi6AuynoDQ5SJnh956APS+j11ABTxvjh3sD0AAKHavHfX0B7YGg 2YPu74bwH09AFBT58H3dAUA8g7u3dpt9je4BhWmhe0dljUOnTmwBC3anZ3Mu8KBB5Ku3mAV6965q ipC7pRW1wAW667tu56Xs9x673B6rV73XsT3TYb3voHz5GSkped93Xu7O6PW27dFO83XbROzvAooT eNGtmI3u6NtUFQrovYdPTSE8YbloloxAe7veHXVXbdoWnQd26da23UqCgZtsNbC2jjBTp0AN75N9 59N21ObKNbdNR8ffeDyqpltbYyKQfSmpLbGzVtY2b3nuemg1cEkgIAAQBARpkI0FNhNMin6JPE9U aMajQyaANqPTTRqBKBABBCImSYyamJNU/KnoE9TQaAyaGjQAAaaBoAAaniAkohJ6KZlTwNU/SAan lMIyMAA0AAgyZMAAAEmkkESZBGKfpqDSmym01PQ01NPUeiAaaDagaAGgGgAABEkgmgIxDQEME0Aj FMmmmjRPU0myn6ST9TKeCT02po1NpBo8oCpJCYQAgCYTIAUwTaJBNT01GQAepkAZANMjTATyOcD1 owR1EAP7xhrihIrI2gKFQKfaYWKuHx/hD+79b5P8wybXc2P+cD+oLt4g/oDK5xlwY192ku0Z9P8t ya3AiwgVH+549ihYePL/b5W4fmMMT694c/mvznnYfn+ew/ReGSb2Ih2Z5HDJr/CKThF4Y/vzg/0W ExYFyzUlmz0sLDyy0UqH0Z7j1+bjtfZB9mMXodj3iVf9tf9aFNej7r9483kp97Pz6FfIvo4MMm8b iypOe3FXNGa4gtraYDp5DCAlkOXUbNQYLmLucJuKpcguKqg5WZ+jIT6T4Pnp6M8xjjjDLfS2efbF mIoL3J97n3cT/uuxhmLYa9Pxf+78Gs+Pwj5qWmqMqklTDDo28ttsbe9of5c2hsyiuv/OmgNk5Z16 UNIKB8PlMatniSKcIpTDdHNG2bXdbkz4dPSZ2p1hw6erFKtkB/9/vo6/49lf+MW/hN+I37aDhSPo PAd/gf5n7rv3V3q/Aw9NYf5/L7rP8qlxuHlvspkY7tIvuZmcfwsqxpVDq+h/m+opKb4NO6whcYGH YzV49hMz58BqS1y0uwdRl8Z6lv5NpysoqqqP7e5B5PcYvL2ot5Y/DCrge3Ktbg4//KDUe+vx1938 vr9f7w8qcvn0/qA/E/qS+VCFIV9XnrLOM5rrJdXYraVLoPdRQ6L4Rpb5bS20br7YYP6yeew5+6tq I+MFh0j/v/aTd7puq8+4rc99Sb5Z3mTrifx8JRs3UWaUmgqLdD3+woLFNTWn2VV3QTt7VY7Xv11x OuGHDF6s1jOI4aOXGOmkWn/F49pUc6oRIHxlR/CqAxpWysHg39r0t5gY7+DgfFjrxPfl+Tg2+zbd Z37GrGmMRXtSzGnWKITHZC/cVZQCn8uvUZ9Kpva+94qcT27MupZrGhRxR5/G3SqOewpd6k/8e1+U q0kbuOMxdfspH298j3CiC/uB/38fCRLVpOHeL2g9M1jvVG8iRwkPw68ONruFPDEqxgt1GYTluH3O GJtbcSB6IY69NhyyCF+9tikxakzmawOzu9nzfZe7n6qM/ssY2+qBD8i+OO6IzFF+qewyY4G95wY5 Q12FhhPETK1Kz7fWbHm9rv6/2A08aaTchrtQ7GFvybt24L0QnwypB4y4Mjybf2+nywKGMwb0eIO+ L5hCh4rVgTClAqMZEQW1RBoB7TizNXIAbvAnt8WvF7tXf7Pl433vGyHSYiayc9yuJy7yPgfOsiDl qFw9LyVQ7IQ7pqu3nTEz2g+GrXetqQhsJwr24wUpqMrN2Zy8m4oSd6clcU3DFS/kIcE+8cz4SSSa FX0qrWdd9ZqGgslIzw8Ppvsno9ku5xtb6tjaBNkfkjPz6VvXLHalCQDmZsdHEGHtbx3uhCcH5AxN menvocjDE54sd7jM24LgaZp5NVGCLIZDOH5DySJIJkQ3WpHDdrerQekDt6+CLQ40gyBMrgEnncSa 0iiaCGkBWtNEYZIEA8QPMiIyR0gdINhDuokWRiY51sOu9kqcrzQmszMTdDGHCszKdSNOkLYqKak4 bPSANPMFoDYfYJ4IIHBuzat7ci6pXPVyDKtczoqhJMmR282tp9jVmNzyK7mkgXc0u9Gu9V1mCVYk 0putkOtiZjjOOpe0hNCjGGhhjL3exWfD+D9D4/OcAAXxY5bkQaz1PI/5XfbbD4pNwHEEzLLRabla zh7MboblATyAJHz0KS+fIkhLAxXKFIe2gzcIEIVtPaDNS0rtlbqzcVYIiblzctiawUH4vvvPMlHw afBHOQIEtFvShffKqNicWnbjZcMZFmnJMbgIYKmxyYEkG5eGae5wbY2lkJ7etzNEPli41RrlyHu1 gRrZWg5yz6jnOZtwRr67GmTO5ze33rTpbugir04cNdVbpEELIQ3pWUKPKWvYdSitjbtyxs3aHvbS Hx4T9Fz2/c0ZmTds6UUXG2iGkrEctE1FdFu237w+tbZ2115iSogoRaqO/82ZTgbwrPV2+2dmtLS3 8cZUUWc2iGkrEfc0TUVpL5DPRYPUnPZY8nv8CEBvFfeGdOsV4cPCTgbxdUiVSdylY+7noOe1DJM/ I5z1kF6JgnCD1QNxFOoM3HaHpUEb9XfZKigjrIoAGNBGIEhoigGyP8kC7KgTxZxddC35qXTAPUGa jkZsrnxvM2AYRSlIENuwqWEvtS9sLiEkjDbQ+UPcERdKkWRSCyBqCQKqCwfflcuIpFkUFDuSsAqS UZAUCfkJJWDMJIY8/yNnn/aZoXphkwT2LNnqqJKUQT7LE8V5O5XuFOXHJ2aTgZpfo0k2fZlG7E5s SOM2kLOkX0UgOET+gURF0UV0KX13WQO0O0d7sa4EKZFhYJ8D45yGZsIYsgjQgcVWZVev5Adz7fnJ 7tHK0k6HvXVO+YHD1mIpFAPc9dUMXFm3oYjjrqWn366/i/FoGJD1yp4igH2CC/I1SRkEhBkGRUYC hIKKqyChLIRQWCxRYsGMkFBViigskUEYxjEVRIyKiqMiqRRFYKiKqKiJFFUFYxWICixVFFBURBBE UWIxEiJFFRigLAWLGIKKpBRVRILFARgCixYRQkURJFAUBUYjIQg/Hzml/iedKy8/noLBY29H+wKp zfUfPn4vr+mY+/BdVSu/w9jbydexsq7cj/vGVRhZpD6APvPuBwOhwyKApC2MFiqoxjEFhEiAKsgL JBGRQUiohA9c9AnnTwHmZvrGdZBeZcRVl/vP27CqSZmVrlntCsjq5efOYRrFV27M1UOZAlqYb6VX kxPe5Ars97OnuWxRmFMpxDRZBT6XElEQZJkNjOwXfTVpT1oMihZOhWhLAu5bUsdUQhBMqmMBD3mT eXUPo7OikmXiFkTncjWUrXO8mHnawRzSa6HwxM1AUgISpYVkLVpe96LoVSSaGUg3DHbeGBJEkPG6 xcBwKjhBS4YWR18EpcS0sRCBPCQotzc7kCSaJxBNSxrkEEGNmoAZFGiCdadGFMRbqK7jyEeti0EN LMw8+Iezo4AJ6c8tp7t5yeeSrRMR2aS2Tj94e20HNh/i1xycvuIUyp9UHu57YhFYfaA01zTJkh+4 SqUWR0wPgp0dgptpZAylWzmmqAQMEUYQ8ne0yLpdIojal80O28YuJFpNaWbCjsHovdklFaFhGFO1 E7k+vQBHm0x3rqBGzA7HsHQEO1f/X0eV2/ApEA5JEmIkL0unSdRJRHH8vA/YYkrpQEUnFvptKKpt a0Ti5k3kCqoZkVUdTPIGhclw7JIcKDBgg4UBceD2ATEgOhANDwRz1AkUCa5zvnpkzSgL0k+TPiAZ HkKki0jcrcxyaPEepXqYlUMQETbYpWQUkZPExbEnMIRfWmg6u8E9d5VVXqPg59L7n69eh530XT7E kRBAfo3z1p+yLJ9qmOKgVNrcjbFiJllIaUqPZaWb0Wa07uP2xTrM6EkyoQzY99OGMtjPjyEZWG99 AfBc3hSInqFUq1emNwZNEItLD0j4eB40bnvfTy7uOgz5MEaYLB15MqYsIWYMysLs4dxSUoGLg2Xu CYEhCHTh0+6woyb6gSDsujpZJk0rsxNII4pYRZZRMIG5s4ZBxDbUHqQOLp5nUInOwe2Z7PE08UJc zsMEGkoKtUneXXIFrll4gshgKUYTONGSETXUdi4GkvitcQRs2Rs2xTxi3Bc1jsgggXCplaZIswkg d0xdqrIJsNS9YvYkxWJXUgE6VK4U2phi0g3sQDvd6ei725edS7SaVCu5NWHTNw+QwoTMvNihgxh8 IMXAbiHxHLXNESPcmlF8GlJw0mJyhAb5N/0ceBUvvRBb0vtTOOouQD2IFXEf7/9BX7k3hHoN/cdI 5k3GmfuYF8x+9Dj8d/zhVp7Ecj/vMVcN7CMywPFH2C3wcfWpxmgsKzCtg9GXyHBFH3PZluKwpqpa xigOv6MER6diN1gMYh7jxIA1Z389RapKFzgT1+hCZatypS/wF+6srGGOw/OMfMdBcfv9ZharmWSH G/uiPN7dAk7rQ/AqlCPiTmdvrFkj1eg3eP/abJLFD6Ua7DFiPo7dKICbqMNK9oZeIarA4ZhViVUn AdDvsFkzEkiLn8a0uYJxHfJHH9rhtkYWz1kW+aIoticK7ElO9m+kZgKDh41Vc36cT1+0lD+s0Fcx rdAm1PIDyAgabte3BMgYkDN/Jiv4n5E5Dtxo0VUhFO0kNP8mFyacOUedgqXMfna880RDsUigMHI8 T5Dy+Fxj5ME+5eQL9j7t/xfxCFvELyjE1s/D2cqCn2rK+z+kd6oZYPqk7FVxSqFwx/O9Reea/6v8 0uXPDWOSlkIPsqYF2sqFm9oj/TxXuR+3df8jR/eUL/C1FQyie3cwihDSUdnKnD4ayCGUjjZXOAo+ Kla0Pnqtjmf5Arf5d93zlMX0JxK0P4CQzNw00IMQpVK6Js32+X3x+6V8MW+LvUllAewyzptHyUXy Yti9JmO9goYKJH3n6F1D5ggZ6csHnpc69sOWt7Sk0anVNqz6eYav/nRGtBOln4QwqMy9LSaYnul/ Xfi49+F6UebWL0cJMzKxlWyzTQWQ8lF+txrV/WK4mcnMj82bHxeXeO+d9XuZ3/kkOPCEjupYkh/E +NPjqR+1sfaklFUWGu9FcF4M/sdd2HjgooWP1mVybYLZNq66iyv21bJ7kQi6lUDMczmVVxWLSa5z 47K5RixEc5aW0s0BIAsZGTV+07KIOaf+tO7zHV2cp59THUgmxAov9H4GoGNsgxehmcqqU/UYl9mX pERM7v1lB6X4YSd4rGluyr+S3aHeTnxrmRBd6MrR/v5++hTLHt8K/ImhuaHQsob4/PaSzwt/Uih+ X0R2okWYtRaiO0iSq4sP7WKXUVwqZLKcPnym9jk7WtNmDyLC7KSJ3E6+eZAdc+HBiTQK4iJGY8Kp ljalJyjVMz5Pg7ctnUV/4a0wqw3ovg0SraKPXcolJQ9/0tThJ45w4pkokM8XIdLl12izYIiVHgjf GEfPXgcaJgR4u+/4GhZo26fCXkdpzzynmx/LH6ErW6ualCSce0spLHykTU5Fbk/cXosCqWHJ1tUW ZvfZ0NImJAoKTF5EVYXok9yHXjOWu/4pdbqFYcF+HWoZ4elilnaHo39D59inYSAHDfHDe3sKe4zm PY+CYvaTAZU+6MOi1QnMzcZaemDC7B5cLno4vXiDD7MN8cNCnkYbg9dt9ptZZN+MMfpr+ydU2rUZ lVhvybW26lg+E5e39lBvlOY88/S11m+8fYJAFppSXsToahvcdhQpDR+7vJjsabOtSyqinuxwtO0A ZUP5TH6ZjjhkKPFUHkKdP6euPxa8ULXT8TROk0l6WSFYJ9Kq/ebo4YsgMrKQ9+wQEOKIULcnOqm/ nghOdqpylJF8fhKDltjyDwtuMZ+igXYZCcxT3Wxjuo9Jd8xI7+T2Wih9hvK5ybcWDPzvqbLxH2NU 6h3wRVPjYVsezQuKmKwrXhFcZRRraUDmftZ2opSlioPKN+8GYKyoc79+Wey/VPGM37GttFmiUnyT 816571pL0qXDH0kxOGMe9u3Dk87sDZivXuejQWvO4l8m5JIAdcTPmGxOHTk29E6LVZnd8AgQI3GN /XKI27PSWLIqlk/CI4HqDKBXDtZyHiPwCRxZX14nHK++bRKEMoSJIifcspV+6YQM0w1vFZfvmbxB F36q8oLVxuaIUnZs3uaX5q2aj8Ue5DSXEjVYO4ySxQbn+wt0tCCjMtKNzYsUzUyNwuMUo3HCOt1T hWWk6a6QlbB9xlVddiwvHLGVz3Stm317/fMIZgsI+uUkwY4xusGSYyqevF3VeVejT6OY/zVjx5ai xRnR9mpS7uEzSkpshWFksCs/1uOn87xXyo1S3y84RdnZW1WuupQNXYnS1Z+MHg9MlvuLN4750RJb XbBmPSGTdReuR2XWlxmWGZs5FpOweb5DgeTfro4jWhxHV0uPlRRUcrMVRZKTVWriccjh99Hf3TjU V1vhq4nB8WlTt2erbI6krodHzQWdK8IVlNDsPYqBzHWBaXSD1cl7OX2qiSLaWHCPwLemVLhDMlR+ Y09f2/1P0/y19v7LKdOkfxffJoH7fKvIi93dIrMimDusZRiOS3eZFhizuXENxgPGnsaNVhBXGzJi sFaYuqhyKU4WkHGK3979L15g8++CEgl+1jkDuO5d6uVn614rYif0LcVzD+lJkegWG4HhyKHH3FOU oObxCgNiEZlYGpxpTVL8p9Rr8ex0KQMxMer0oUL1gvUVimaANoygYqCxYesSxUYiiqMQFDJ6e3P2 hLRtKJBH2oIem+8PTZNw/TwQWBqKlKgkPUj6coBn6PZUaFIX1KmLpI0IYczDBMlwlKPqhPqXsENt WnivifWSTA/N756Pg5ajzT0YZl5/g17en2T865Ov3QjGE/NbifiXx/W7MX6HNXyuSMN7FQEq0xZl an7Dz4pEZHtIY931UyJ7nq5BklEjvxy/dSlFjhbD/gv4+H7T4vLH4ehf3FY+lrc3eXUSlm1MeqU7 wWOooLtfg+l7AjfMVQZTRhejjaZ8pehXp5jmG1Slt0WQ7F72zRs7ru0ltTWJzXjWr63BWX2Esp7R 6UdGOz6pdnWH5z5oVHwEgA1y6a8+zlvuq7jjDf2dtOk+7pjXbsMsj/kfwPcjyk90KapoVSESEkAk ESB+FCloraKoSMkRiLD+yimCREgQiDCQRkmUmoIMFWKqqPtsD5wSH3DAozQBKhJ+A3Oo6+fR0x1o coweIPOX/uTCQciJ/Ck4fyPp/V5XYvZ9FOiPzA5OuvJD81+uH85C/etFS6H4k1z+m+3oz1LWa0S7 l/6ntOE3Uo7Qx4VC0YS1EK/3CQWBRYFcF55A2pTMgU2QhsIPVgWBSZwn9MkSRQR/rcfh+Zxe55OM 0Jm0T3aJjYD7Bj3xf1G9pT6K24mn+2fmOLMHJKhmCXtqcomUk2ddHg23BHnLgOVOWQZHR5sGQWvO VhCNYmTk5RGTN2z5yUDg2V8GPQ4kli3l0WSfyPRK4vx+Xgti/9ehXbezvSpGHWZpb/4I/vMeyEvs RYTOGzl5ASrydiyzZKxpjI/4Mu1hVT+39P1aSwGzFzH9XiHix6LicbWqwqx3d8XYmpKqvbGA/8dp 9xf4SJUOKhbwqc1hk69ugfyutaxlhW47NKb4xbH7efvKn9+2aqrjkRCrEKsST8PN8JVqeftxO6i8 i/61GYXqs7BpqYb3QWTp37/N/kQztEGT1aqWLKrgsl7LNB73sy5sYZ+j7v0Q1EFiCfJS+kEwQ6cs jXbkBwuS4HAKffmISJ+2UEf7qGgn9s0mcClkEgQSBBgkV/l4zx7s5N3J4dRdcdm9fn5dgdQ6BA58 rie+nvJEoFrK5I7re6KpKHZN2OoyLtolaCBJCmjInE8Z1pqTP7e5npNmlOet49EzfClHAwHo1Rgj 1anUq16FFNHI90IYBvYdSjhHk8pNMI+yS1VBQDqbec/PEratWnQwBgzLVAWj06VzK0sn8MH+VGUi u5F0exwrxOFoB5hoetBwP+AxaVmQUlB7ux/lzifJX6RDUDrDZ1b8ePWL/0bP/TB8Pwg4eRKKXUU0 Ur8y6MwMZvEXq5Dj5T0DnT3ECJFYLAXSkV/aocE5gy5QTU6yOyihrMBxoMBiaDmGA0rYKIG32pgT oL2VFzymUuTFkfwdkYF8NFllFKKRgSn9Kkln9TJZ5LxINpUSALLQApDTOxI6aJaEVHcHU3NxpBCh RzpczqXDUHN6FdK2iLEwxJn6vXWmIlgiagz6zYTRTWVMkvlDivVFmLeimMkw345ZTCWNBIkI7/MN UWeRz7w2gvrA4yBiJFNNnEDJDacDzNx5cZOj2aonXJmTcZuCY6I6kOmSYBtMqhMjRcujpklRkyLR CZSMhaNU4yBmepCCaXS5bdKasNM2iuQrcjnTraIZpukm9KRvHFRrDJFzYljcIUjcaMVxFWBo4kiN w5k471HUC6bpGzWjwSTb0r5O310MGiaWuGhjomyToNRhJdjinFF4yidMTlq1JePVJNOO0iYSCJ5I Lm36hklvddQIrTxO2C4rCqeCE868kZkUFeiMUrABwWJRDpvLUnrYLkapFAtwDES02GQExIOOYjOp JPwy9mr33cN7ubMSCSEwqeWZI+cfh+sWrL+7Fu8U0ui30U/ql9ztdS9rSH5WD4NGVfy+BFqHOptn Gn5ET5wRN+TfF6/LC/stfVLEhzs84yO6fAVBLL73P5GZcYIrJLzPTwuQu7xq8YRHbPjDW/TeY4mO aUi9+ai+rZW47tFo2zaeDzJ+2N5veJD2Aa3mfH6frFyHwuGtFLS3DXto/V/Gq3jbA2IgIAkD64FD BgwWAR9gfH9j5fqtpsmohNfKIcRxWtKwTELkxXADBHBW4MQsN+N992l2ECIkEZARnSECLARQtqRg 0tAtIVJEhASMkqBYDAiQEYLECgClWhIDSMEFpIKFIsFoCJUZGSQpC4Q1jghecZ14bZ14VrtcZj6C 5zvtI+EgEIr1HHszBMSpI9oW0lNPl1VVc8WMZMBkYMBcYqMUZNSl9YJRTLymnRchlAvQ/OQQF2I6 wRLtJdQkUy+xObO9pMXVMllL7pLoXyWLy612YIcaOhxd4m8YWRKBhmYYTf0gfZIB9xU7w/R8RKT/ EoGj7p+q//R/9v+tFj/4KHu7ITMKAfr+ny+zLaWrQtoWrbbbQLbJLVWlttp7Rw+8353pnfzzyW0t pbZrWtaltnxs22O+XffaEC220kLbbS2kx1efW9NK/Ad4h4pRiUVH01vroEUMDMhihqGc3Wxm/F7c ff5uc5D9j7PzJTJM+/fPQkQofrOfE/uPd824JcGPvTMpBJFd2zDR1PPcThmFUVVUMIsIe6e3t7Mz IOe58Ckd56j7X3/uf2n9kc+e2pkfRCFPlh0MnA0LuZEP/ljnZdFuSaXLaVnggEIAnhAvUQ7qbQuc PHMz3JAknPByZIBxlCpA5GbpKkOUviZ4raNYZrOEXLGgC+K4wFzxcIF8DMvRJywNnrzcedZgHW85 DqzGdWjNMhcsDgZsyoLDqk24sJywrmayTGQKwWbMhMejOjA25pOGQ4ZN0KwFkWCk6ukNPVhMZHfn IGyTdnVm6SCl0agEgGES+6ktnpUuwxyzZX57oKxXLo2Y2u/5/hpX8ZJrTOB2LpIUJYNgNyypYNgo TvxlWEGVDkmFkBQrCzZbOsySTQAd0DugBMCaYOQJv8pvp4oO/GFGAdGoJNEGhIDBgVcUtkQYBEco BiuELARkLAL7pwXSJBICIMCEhcMEUIqFG4srSDZSCJMatrzlXHsHcmbzxQUEGKqxe0p6KS5oOcG9 cq002L6u17LGEdBqy1HgjNCHYZqQRIBEEg0hE0X3wJcTZScdRsk4WM9mTAbcspJjgvsSxfCVn1aa Yt+G+MUtEJwuSB7sQXXhASxixT/j/trcMGWykpPMQ5KGhhh98nk4HKgpszyUkiqVTmH4Wzc1VWas oeb7mhJhhgl+GZdlTHPpi9iYwVbYxXppEmKLITxIUfATmTXCYZX3QCiSGYRESlyxIwdk7OlTgSJE 2UQMiF6tpmB6irPTlIaCXfdRyaACZLMwmCok5gYOxz5CIFZOInDimgqXuYIC5uRyeAkMJQulcZF3 B0bKGCBd5IMyXF8UgVpSIam7A4BQuUQBSCyLYatWBaMURFEoLMC6gpZ5po0TQZQxIlP+rBrQtjxn AJi3A47mDRzyVPHixQ/uWvvxPMiBV8Zm+nikzisCWQUQmlBkEmBCJIoTJDSBLYIU1M4ZMpqiccnL IykZHDZfe3Rtk/wTY2aK3QVnXNtq3NvKub9iicNF5mwb2RF3ubyqvDUV40gkJUEQSSgLYfIkQIqI VWiMWRkTJJ4W8+CxVMkoFFHkBRiYtDIttFaQcmCDgsWtrYbJEy2JTkd/bjC53NwViGFyM6X5RIZy kCDK8CGyaCAkJQcKEiNFWAORiRSBApEWkIgMglUDRPkJ0AalJUnc4KFZKRUYuimBjooWOjbFMmHf SuuJXXHG/ZhiX4XY6dzWUDYMVb8KTKJjFcwEAB0XUiYhakHPmoFAhBRwIN8NDBAQdUESY6TWQwBi kycjggYphc+fFSCeiue61yVOShM5F6OHNy3XPTMywEkQlhESQoE3KSJa2+Xopmvy0peTSRngGDGJ fWgVEChxxokgAlSRQ0qNd8HfRya46mdiHYgueIgaXLU6i5QCC6jDXiiuln4nAf9Xd47qVNdDGZmz wpUkcCno4FMHgmd91PPGzZUkbJIlBaEEbEXJMkaKlvXXB1MsRNiw1jczYopYY5LnBB+iDqFhpHJ0 WOhUonPM+DgGDs3o5FO01knIzAqVKjEi4TscnYVGKkjq4nRkcmDiMbMObJ4JjPQGKuylrjolqmKG rljLk+ed6ERKdiInDb2z/DiH8A724FOThTgU6cwZJgprJsU0WPdETI5rsmUIQ/ZnC73+xDNy8I90 jTs19L+SPordIvTiG5PKH+EufRHyPoi4n8vX/oq49kn7fOryLHs7+k968xSCIuta9zPd97XSSByy bB/BSEk87nntEBu4B+XzvfNzIY9hjpqcuvpxyZgPw2bciZqm/FnY7DNCFcRYbnZtsa6vD1YsDTwq YdocZPGDEg6/yLJN+zp25qAHUQXhDdDdk6MMfEmtqdo88UNkOjO10nRXXU4w5dqDZkloW0Elx6r3 WO2ECQyCeCcQHBt0ybZZWDenOpU3QWdLc3sDW1kMQ1zbv1ydOlIpKivFF5QNM360HrRd3oqTV3Si rNxl4SENCJXBlRbPYaOUNIKIhd7cWp7R9F3haKr6bz4hj4hnf0uQ4pmEIhAuDAWmJZpPejkXwXaO CwbwocDhoLWov/rS2q/GmZVMuTbYyx9orgBgJzBTmAiZSiIEhILGKiFQb4KoBy+Px0YyEjegjmIb T+G5NUad3cY8WmqqpjaC26xxi68Z8FxlAmrL5L5xa1prDDPHkuwmteNCcIl5pUncPaIO3IuB2SOg pnOpUhgmE2hQtKF3Akuf2wMB5QGZ7BJYxQW9UWTZaDKTDmZqjxCSQZCHhxQdgY6EQ4oA/InJUfqy DEw7FoIeXiNUehAGR3wHkQ0MIQopYjPEp7rO81ifUU3641rJY3wCDAMIcgnJWqbOEEa6lKDIXW91 almf8ArDijaRZAyoG+GHcaW3kFdcIJiuZQMRJbCS+cikq4XmVZjpPA4Dig9oZ6NhnLJ6LhrWSdLW 2FGrVNo0yqV4ngWAn3ygMCjCApnDBq9ibBF7gvfRTRUlBCDBNARZe7JV2NBMQd+UQxcYQdxVFJGx t8jSFmIiIpR7JqLAT5rE6NMVFdRzOiD3JTgHFERlEFDEpOMpR0ZPR2fKffUJVX9jPnfeNG1GWrp4 9jedWXE9x5eDjN21ulMtaK8W0NU3WaxJTEmJrq9M31KMqNstxud6VaM4nKbYeuM5raAuXvp6enpB 9vh7PtxV7Ku6q1VOcnxupn2z6USmLZiSpvNc7YsRTZq3Jw9sGUWWPhOF0uKwjTdOA6rZSFRKIZaY WPA9parQQkYSeRMofxElpECogNLyMlBaCTe8aQEcEGosrjMgNkvMCUh2yjFpCFVBFILTY7pMUWsm FHLFyQSikrIERKdiECcbEEKnpgazsNgkbjYkWyIItNWLGyYMDFjTR8pvWZMgm0tSQLKCyEggOtEA EXQlJbLpXYz4QQqhRGEIbAsgrhxppDOfeIClfkjTDIhMzFeCbzirodnh3EHzScL4hJdRJS3U21bt xBboOrdXmzXuHOe4gGEiVT4EgkUT1JA+B0UmWu3sO58uDAkg+B3QupdWuNkQUhEWgvNS1czPVDYs sCAxys/ezzbtAScI44zXs4aWFKKcn7kQ9IofCZuoxyaNevBg6pMsNoV2rHLlYweKQo3MwdTKCY8l xxEAfIssNl6igTIAGVeCEk5QVBxZ3YYUOLSHsyTaRdfsVkHFoxjPa4kfvSWeIQVNshi1znmlbwlT sB6OP7VEJLZZ0RBuCSJFLA1jmQnQo/PkfQqQYLP5Kh4HTYiohGWR4NYglwMpAxRFRPw9hPfR4rkv tfBoUd+D5lNKpxhjA6uUX1anEioT8qgxrxq4SREnRFS17J5UIp7+W7JMpQU3LRiaAW4Esx2NQtQQ L5TkiSlzHsYiJSw50ns9yT8ZEFUt5M28695eW50GBZE6lAWFmvSt55Rx+pSZT3xANKoeACdiQT97 YTQ+M1mxhxK4EgpVykdi0S4zdskxSqmUPY49omSw5yCwg9SRgdyBvggAmHDobybOSQFcdhqx0has T2HOYbeSbTbtFbwGCsh2mojIrxCQBWZbE7yopSW+suFPcKgv4EgorNc98nxzqNEzKnBcXTwKgItK leM5ngkSoZOuHNkdC2pmtiUrEyVzgwWIPmgGDjDoJk4OjBSlGz8MeCQSBHYhIUgtLzLIsKyuvMuJ FI6McCBVxdxe86LnRoYuSPI5sWZk/tFjJcUq4Yx2WlxbIlGVY8pIkB3c9dAaU6bzqIIagAKs14Nn E+TzyVJGD79nrJK58TAxB7HRwVJ+jhyRrasWma9mabmLsjgjdkmp+Do+z8jsmcY+f4/n+atPOTqz ZyDEKgRxF01EKKF4XRYmcF04dYrlYB8nxokDBQu9XfOAEgBkcA9DNH0YquYTlzBIOBRkCCB4bpXk 3O1j5kKBb5lgIHgPDwHlBghETdG/RYZ5zdlgwqbYY0kCyTMIPhvYsj7I2++eReVGwOmOVTQZcKLx kNyamq8uFAsulMjWNy2wUXtTNSGRWnai3lEkpOy1kcp+ZoQngWuS0QuNnBlkTGtfNrMcSzyv239D 8eD8H4LRTmlxZmTWRssN0SbktAgKDKIEKKoOB/Kpwb8NJ52yItvNZoQJr+Yx5oTppZSGZUJk6b87 5IyVEYypEd+tsUlVtY7GZMUSJGQ3ZExXQy2oVIQ2O0RXFU4zEV4qVhAFSXk0UAqzy8bH3p+Yr615 F2fw1ohOzBt64xdEPvr/AXwbGMGTs3Lwp78svKFLnHL2xJb7YJopHMg/Q6wuMISS65hhAa/phAiC YstdcKdVo/BOudVHB1B8CNVFCgX8Pp+lAH7LlnCZxdAOCJYO9EzxPx56LDEx3MHmZI2ebH7J+35o HlBJ8DeqdtKSXd33Rk3VVrXxabhJHmKp4o9pgFkEsMgnB78kTkiJ4MnoWUOZgPqIcnL0VbMbtsdA RhYdzkg2kXG4iYlhkbZDFhneTDyA9AYDQhkZqtnV14x0rzfwrMLQsNCpyUEKCCclChXFS4LeKgpg LoTsxAUVEGFoKiHeRsWGBPVBoLEh5UWDnoFiZOTyNPKko06osxVUDRbi4xMdcKPPgdSWe2lz5A65 rKkzJO3kXKZLiBZz1A5cnmsEqI3yqM6izrBWQoWJxB7ZJgm4UcPfNQsei7HRVThEP5Iih4sZuulH dyhzaStfl6T8SwxwmN1CrhSBlDHhSpuweVsDgQ5C62fLSJCQjpVoKDJ2pFD2Vw2lxvFUwPY6rCJy szvRUSLYE3GpYUk9svkDgKQegkE7zTbPFotjubXRqyKRKlKVeGeqBQ4UAdURJOMnkkiXndnGAKCR kVU4ySS1nKxxBCKmmMagSNSguLTki2i6EHEeD2jRs6kPwVKpxv8PNpCYLjOKR7iGJy3ysYvtqK9Y jRQKRg7tkB5JdoF6JbYyYreM0fdGGf1RFeTjqL7TE04iImx2+JQ+ZdESwVQGRAxmzggzGFGcyw3S iQ3xeMCjiroZvlJy4kGB3pd3MpEEDUyUpJVke8z2/rIk/uomT5GtLjUtreFhqaBENO5HRC8LDBi/ OlzmrH2vgDM7VmaxAQ5myBYwRnXJUNIozYsBmTDBWwjKirIVCrMheLTaC58BhzGfieCTmfjSR78f fQseD4UMnTHwJnAdpIn4OuPMsyPXqtYUq7zVYktXHceqlHFnKubefPJ5zZMWREuIPvbdCpC/8/7l 2T7JrQrdPel3PdSnk0ewxU75NIpWqf0cCFFXSJF01TXTFIAULdF9wwzJhj96BRlQWnC0gVjHwKDD HZobsY8kEhSR/JEgGHn+oUGL149cGTnunh01oTYKeAlPOWnqhvR8ZrxJKdSjx0WH5JVJksngSZnw UOi3FFLmDZrUydeKMMaqnuNa9oIlM/ETPRuD7Ih/NDk0c0wnRtcAshUvMiZIglQYXxydfgI545Nr osfUqQbYrkUqvwzNT2hT9OKGpGsdcmUTPph3oy+BobeLbHySonzfX1iE7R3PA1SYMm8jLqELkLQP kRblffX1VWymI2C1BjeGtBxiLgI1OFqMgMT0Pf83l3b5lbt3ccx2PL3nSEWrVYzPc9k+lzvN8RUU 6Erz04NneZ9DD0NkdMHRlj1SJNwJvJHnHFaNFb28D2ENFaXIuQ44EEgPwA1EkYM1rtQiXCMR2+qU /JVap7bGy87HRtQ9wV23eu6GUFcXBd7lypEy4XzgO8vgtA2xMqRSrb9Ii2VheUH15bNHbPqnP9Kq of0n9hwYuIpF0BOsBksSswclk5CIkRG6WuGOCPeh7z1ei0suYl2SSQ6sqVpNmIWiCgtZaoaRKoCB ++cOiCDTB8DrCCIs82ki4A5PytBK5ZnFV/ck9yFNGHQrDakMpHAppICEAE/CZ+hyQOaOSh0fYYrR 8mj4jcFY40vSnKjsShlgXPbnZOUmAg05gAsiaOCQlRCyIjEyVJ0xnbaWJZeRlARyQlRBlQwI9xSF sWP57fkYyBe9WJjYdAv0fYuW/h5RlOfAxcuJ9/oTl56GET0qF44k7q0icAhMQOgKqXCyCVai2KjF aGCj7NFEBHOcTWpg0kzxkGn2ogxIrewiBJ7GZila8KJP+jtjclGmC58InAexNk2Nt02ccta/EMR4 JXhVHaIW0GESYlVqoNbQoiczR4uCHgZASklkOgh3+YRSWzANTmJvmJQHK4yQ5f38XkSKFU8GDwTP R49XNBsqcGTnxkj6h7XuqB5G1TEAuAoOhJYO5lGotZolHnz8nhBF6FwEyp4LcqIaPRmw8b2OU92K FLzBxRwpPwTAsYKlg9bsCpx5LnBxbroc/YSnd+e1Si66eCLrdYoiAxVCQ7ImDoqX/jnJ4l4yiDUY UzSN7szUJGA8WlXTL0RYQBXBSU4DFhk4yeqVMB1z0xB5JGjOqHIfEihI7nVeGOiafmG+eYOKMyoe 4+oHeJoGBitaoos5oInhALeCp4HnIq4pQgtSmxFtItAVJrg6FEJHEkx0QGLSVHQHxgYbpQeVF5qc VnaU84zWYXrMmcAD/LGE3HB61252yHcqSJ1Jk6hNF7GqVPKvOQnfKAMeZKpo+iAkOXLaLMeHKj6o w5grQtOngUQu1doZFGwMPLTY7AMMIm82Clqdi95m50HgiIZtQ8uQDhkQhBPNMOEYkMeLr0YTAq+C 5OEugVuWITk0ZMFzXZwdHx6Ocps+QB4Ex4MsbMluzg4BW4Knw0EinPd0deaoIrCjdr5zPxMpKGk5 TNqoCWQQErvZexyaoPMgbRCJX/AezWEGkV3vM0U41l49ZyAMDfKovNKgsIJdTHklJBDHgfmqInzN iXM5HBjZxFR2Oh87PjBQsWLmjBY5KjYW+bFSZyUGLDuWSDr9kPkhWdDRoVIi52KOdGEQINHjdzAI JMctckfxRDs0mSpU56O3IMgyGz8wLBJ+iZixWeA4IHLHIWLyTg/pt0SPUpngkVMDkhGKcrN7FDok vcH4JdOOFU4uLeyNGtyptcGoinldIyvYZ5WZGyK59dnvaRYZauPAk3e93x7yN5dPRQQLHox8D3p7 uFT3BzrB0fY7bivPsHLGbD9VNjC5e87ikyfmjliDv5h8SDyYfyaRD+RUELgHf2JdX4pXJEhGqA5J FyuD4ypC1Qu0b3wi6J38CJhDoPE6x0rcxxewy4NmceDe8ZG5geZyj5ScE4tb5PCTuantj9G8gwCo OxAZh380XLNLgGBPsFejQsXmkerod2Z+TH45Gj7yBZeijR++apq1h0+i2X0tJRS8ERJJCkk9eztR GxdlAEHgkU4G7iAYc9MWYmOfaIF9u6Xk6TW+AsJSRl2lnjSNO420lqGERaPRyFImAEH0VJ2E7FUc TpyusKmNDVi9LLeb3Yy6kfgjKApAOnN7+vT2plhQyqJvFmBdFiXyol914XEqIs+19t2NUb6aGVGG y14HEQP0tIQIZfqzIICVJOV7gReDZQ1BiDgrm5VKjoJoj+ErbFYRAoqY3VjJaQgAnRI+Qly7mToq R0eN8lMq7zq0DilpQa++hJEqJOdfBWTgtizEHyKNkhNrzGb48xaOXSQ35Hm5Tqp16YqdUVgQvIkn BgfngqUjOBRQ2cafk6LFxey/MYsCKqA3pVuzxvTu6wTthwsd3udkpXrXHK0CZpW5PH67Ipl1Oa5Q NoNrJrO8aNDfwyNGlc3G9tZ22uGx8vPxtt7HF2hsZ3LJi8ahnAM9aM7OUIaymhbgGokxDMIF1s4M EpknJnskNYUPXsarpECWNA5/Ho2ZUkXPcvYLzN7JWjssQlCCTfiT6LijFSfZ5QXuQmJzszwsThs4 NKNL8KJwEqE8FIRfEZhB8dADOrEiRUcQkqg6IHA6YS9MoU7F5qT1FzLSFJHdkPRolo6ALIqfJfiK KqqDKhmIXKxVtmXxRsch4+5MyTV83hfEPkKek6GjB5Yg755p5VgUdFtdnHazAHpK0EOuOKGiZ5xC xyeRvognAZKZ8W6mVOjwbO4Nngr9ALyULi1k7grb9fGDeTlTkqS4PzSXW7NnQLLyo6TeXvJdeLIS CVFylp2mdTmnC0sZKPPg9/eKkcHBoQ2SJySeiLxxs4qm5HhBPiVL4HNGNCmT2gP0RN33s458QYsz 7rDwsLZXgyRYdRosAeMWZYUnI5FwQUHwYle0C9wuT1sXx9hVVfHjg4EYmhkWK8meVhmkcjOT8Wyp hnHN46LNFoydcIZEkhomXL2ScSR2cU15HIFJrJ+yXZwYpNYVeiDBKVsm44JJ6PfjPSqzcmT5+DR4 NmTv0S7JyJlOxZoBrtSsuFO5QzthhoLOeFND8eFNhJe6GMLGSRrLAd8gnBOsjoshC0pz76KmiViy lze3qXtbXyXtRvSS+3TwkRmIVEmCSUlpbPxPdKqo4EI2GGOIUx34NLKD0SGTkdTZcebHcXJMKfp+ 8ITB015nRY0Lv2K5SMlDbKemwqSZs3CtHQ2Ln0zG9uZOS+5lGxkubSnM3qWcTNvYs87maavOEcj4 CQWsGTng7Y0SLkixNzBjEFzByKT/Zi5pjlEOcnRYcuFEFMksGjitXIHvsuMJUkOww5yRG6UqOHIx YanGZqJUmTN4FZ3+G1sZNjR4Ro2KxkfUieZcdqdsmTl82UnKOn4+kTLAyifAwksbj5bpOSbvmazB gkSrQlkFyUeJyFtV080VpdBWFIPGt7bWxR7UGCK0KzQPTQ09C8DxQqkV8uB3cOVcK/Vwy8gaqcqz OqYPk1P3a+U4zNeCWfVAitlULOzeZ613q5AfB25U8cnjzIQ27Hl+dfg0Bklzq6Y8PZnvZuSNUx5c OIDG8iTr3dNSK2cyHUSMo8qBVwsyFRVJNGLyKnBuW8UUphJ7cblUtktYzX6g1GWXjp0KFgCLGGtU tQHlsPDITWlIdUUVUEFWp+ydYx1mCrXmIdE3ko25kB+ipJVWYdjUERE6tE1wolCcWkVklbc/Quhg qZZs7TLKzDFGLVC9NdUFKrjZtYPb6uk1NNO6LxkmUGFLzN72R3svx0uMsVIiICO2k+mEaaFluhNI 0CKqAtIQTA5CJIUU+nWuaXP7UHqt6KsxAZ7jJYdzyKSyEIHIo6JPY51v9HmuBKTO7wDHpBKQxtUT Wj2mSsWRT3aymWYw7RnsEmqIyGBAUSUJkEowIvqIdRAlk5gRijEj9rFzNReqsshcFS/70BKM6BM4 nGRS3xGG1IQkMnj8/0bBc9ztjkwL7k+wCoRrndpxwSu0S8VZD8qZcQiyIohe12VT5/5QkgiTc3vW 4GebZspd15JQSdBPlLk+R7YIJ/QToHzg6GvH3JGHMsuHRKcDVbx3rdKCGZNwMSnUeCFwCRHo+6xS PYnaDSId9+Pv6kXmUu7wqq9F7r5gvcpc8wVLgVwVKklUyhv2M0MlyEKoe045sIXcXBGxijiXJ9pY nyLyLyyw3Atu5zh7kzCbP1nF9TraCh3XwTAXqlYKG3hZOTg7Tu3PId4OM58oQEx4nYheQXo7qjeT RU91cGeWE+ZAmMiT57xBbFKMaS45jSiKbC6DWXpFhGBBJllv2RHkQIzXOAsVKORcTIYE1IkbuHm3 bwhZpX7oRwnd6uF8w57ciQWQJEkQkQz7znMcO7kuQbs3mOQe4iB0VSOHPLTgzcKNoxgmHwYnIuGJ +rGBJATByoJcwiNhSdx16FhxjVBPCHw5IPsBU1x7y+V8L0jbvEZYNa1BnB+RlCLBFzNatby2mYUs ryKpzQ7mWGHHHscnqqUPP2/MZAuYPiXDlE6OS9JdnsVKWOz8zz583GpqvnLv4aVpIiVSiKpUUU4F LSFKGyeVKlLTocQj7FGPc1hfRJOB58sN1YlIY+Cmeyx1Olpr2K7NHJR1YZCWZ9IhUUROhQEYFAEW fggm86Wkd2NnVuHJF4VV2ieWax2UsvlDdivVuueZTyU9eut/TJrJzu6jHnweTgkN2dpjF4QECiIM qJa3iTs9ypUgZCQ5ySNGhwWpOReR2PosfcJgt2ZNchr9RD8UQnMWmx+dy7HOjjnshSoxuthZiW5s cjHYurilhMFi6SYkbNMb0MZLsnnz8pcyOOS5fLCjEuBLuE8lDg8kGDksQKdIiTM2NlQXiJRFnnEx J4lhMuH3rqSrJELLj0C6kqID3BmhypFiY2rmyhI7mSKH65Res5Nc2NTf+gPiJ5BJ+y7J7uL1gkMQ fCrVLEjdR2Kk+SMEyRZycmbJ4R8Gs6Uc4S92JDz8TxeMjVsniel6O1htj1+Q+LaxNTgm+TWaonRO B8IhPAcWcOmKcTrI2szXJtNQ6ZOPZL0ggpoZEQySLAyDsmM3Oy13G01N5QT8Z8r6q4Pngj5t0ZDH pvdmJDtwFRqlq6F3psCzqwVNR0dp1blO84FdzMTlzIiXditbyq6LvYGYaqEIqOxV8NtDFheOpgxi LKtssPVUxg8KTZ3FrDMOlFZpUoK9FYieDpE0B6t9+PD7tfX7llvE2mhT8xH5QHqqOInLoEwkKotJ i1AnKZB0rzk9IQkKOTQAlHbz1FyJj1QRFd21MtEE0AoibHKoJLCoI0C2OSxRIWoiCUoamNy9fnYM mmpZ1p1sVNTFhtaNztMMVmchsmrRlrLZEyl65gMQau133Il4qzvmlov4zPh8WpwrYYwCiGUgUZRh ZQgQISI3nk2UJuTRb6Mn5WMkGNimSgp0oxwcyhPYT7Y4762Ujuz3F7UtQlGZky70SUlUiVeuTCSV RBS6rJFvSq+C52MXctvOC5OJlhTwS32TmcqREzk+8S3dul0sNxdmxCI6J3Q4OeitOCaJciFgkSB4 JGy5qYI5yfenAHchi+uD5rqQBoZbETOsdMNYTLi8uNAoMq4kiwzY3JcSKM8Fajci0uvTKzvC0gdN xI0oeqNY1gqCRJiRiCxsYoOfRpjpbo2RTZI9KMION2eLzw4XNGDRYVYOrlBRzZQ+CEkTvZVZ4VeG QXscfJf5nZI7sbKF5kiRhCQhcBhhyJlTlFQkc8EqU8J8TIwRCK8EoU5ofQu/XDpQtQSxycEZVe78 p0nMg5JSoTwrK5NV1w6PP4EjZwlSdVTk7ydGzBPNSo+lcMGRZQQagnkWVrmbqT1kmmz29sbF+yBy eaeOZp2y8Qdyk0u8UWUqjmtcnZhFLRZORQopO/fB9W3NEmSREXyU8gxsYrz4LFOy40ylPHF5sEEt BHhGu+Jr3c43NycqsqUOByeiNOQ5IfgcpWddZmVkxwKnBoo6vMFN7KDD1LaP20Mfkn6Amdc88l1h e1Nzac9U6VORTlzhbrCJmbZyMyh7FCkisFDPdCQxoidnJi69e3Jv1s1YcgrFjgQqFRlCTOh+IiJ3 VAUEBDxJwsa04s63MHBo6C53wcm2JYPzwWPZFNFjQxHoWRYnSmM2A5NsbJnoUlVJKdUjFLQv00dO 52RhKULyDiI4uGI3Fw8xHpJuVKlb1gydGSh5HOwXfApGA6cVLKaLF+RRRhyk25L+CGrcyOcUFrks TJhwC/Q0MgJo5s44yyQscudZw5SxMvjOzcaLFD8+UCOc167bx9kTRBY2LxMkxuRBXrySJmuzVipk MFz3XaZq546nPLYzbLHY+RY9h0XI7vHEcZF8clYIyAGQV+7oljEnqCtOKNMY6XiSVWwXhoROEmVS +T0HWOxulkdB1Hj6+EmocxoKSGr4meJexxbTNYznGl3b0lVORGbWUOINB9bqKLVr00pWFDGzg2Il TPbQypeq6YegSaxw1d33BI3MEaHKzL3Ar0zBeG5wUomHE1OOdN0aFimMh7iOg7KVTEPGEN3DUrIG zisNaztaVIslGpE3wmaW8EvjeErMTBlGUdE0wHaGiSTW0LK7U7rxwvHLyNOM41vnt9hAJU3gGpJT FriDDBM18hAzSzaNF4EPkWLoYF1UTzy5GZr8cSYl5QmCNRQv1PYGBoMjxsXAzlpX6rtc0ajaaGdh DJIfQpb61BDxWLlCTEMUebPozcwZQQEsTFQZMDcDkPMcNv4YmPB0owKmTUyZ14MD91jXVVww1d+6 BWaa5Z0oia4/KCS5TA+CDzYeFWJ8n7RJIYUgZ1VdWaQzIolHUMQZFR7oiMYcYcjz44NdnuCCUylx eCTxwcOP7b9FiSojxUcRLKhk6GLEF3FsgHrl4EwzCcCpFvM60Kex9QDHHR4MYePLyWpMiYlZina9 xSgXckT1xax+SlU2rM6LRxwFCXzVoxtMLwk1Edd7vCxoLSox4aEdBZGQKMEz0QYNgEtkj3xNVrM0 ukf16vJJNJEwQyplUGpTZ0SBOdeVKnYx74Dhj9A+88RGLePHeJEYnGXZnJkxGq1RFY8MhBRhPCkp DBJPJa6JeUD3JQKqF5njc931kPgexqQxyiJ6ODJycG9nNWvVtLlVhXXnnWFFXgucGU8nLWFquLmX osGShBYaSnCNf7msjlDr6BnyfekxzorycFAesOYdqLtqGTqHD23PftCDtfWRmiReOm1Coo3EqLPw SPc948VXI9cxFCMtPCiSJMvwF9iNMp5Pj98kSZQPrzk1zeibZ4qa4fsopyCiu8EhxyR8Ch9x+6Vc mrwc5yeC2q5PHjyYJtk7OuTjAtUGF7hxV6avRSiTZvR83khk9Nk2eDsTmsDLccybLKUjRWVBilvs iHJJJdFeKnr80E+6ACUJpZ5C5kc/b2+mLU2eij0ztgGMOLtzWC0HYmkQBWgOn2FhteYjygmbzU0H 1wTmN/Xq46lZSNQCvLjePIji8vrrmYF54HQxIlI1hjfBIz5mV119C4PHkpnR0aPJQ7g1qxeZfk6N 1rXRgvo8GSIPJwVOa7PEYVS5gmqBBBYKEzZ3BMuFpCjHehNIn6hmbi0JZLexMmbmfUdHMaJHR6wZ OabJmS5YsekE+8RES2jVjwcCHRffjoY0GiAsdDEw1Mn7e2CRQ2UodH1BL/NE0iI40+UcJHTmYZR1 SNZ5Rvi+JgLNr2SeKPU2AdmCNjsVsvMcF8kgcy6tB5AelHP3o6grk3sAPM8IIMsEQC5GxJGYDw8t 3h2ddGfAeT6Qv+fn0n8Q+Pu6eis86qvLJFdmd8rpDvsdJzO1AvcsIRmbEzive9sfYFV5O98dYoh3 bVU2TF9pCK7dUuW0TjnMONGZwKzvlcuYWPM4q7AJmurbh97nYydHcVTUbgnZuQ1G0INZW01FZZV2 XVnAIXt9qimStlJBpHQARxcZzSx+xuq4xtlzIsZlNEEkNcMDpocSX5/nCVCZ99nxqyF0BOkRIB/w 1IZQWnyrZCStQZlUuNWouDIn4QckGjoZbmHIL5dlUGFQRUVCGnOHQl5OCUuF4FN3a1nYUsUrNPoS JogIKRQlv3GhZogyuZIB0EMqV8rknyfwrqx0eDsc9uLxKt+rKq5bhlQQ25aBSnEwYWZUerlTkuWx YQTYTGsogMOeCdJIiCOXL8my9d+IEm6QUwvl8ub7ASbJFaY9c8TsIdiKLLhhaD+CHOP1ti8eEs9c 5Mw0nbDtJu7c4vW6AIFR3dEpSokkBUQ6bMxDPBdiRH51eXBm9rkFCEtSeZI5ilTIvMryJMhIywNb yJEuIOMCB4cqbHKZI+qIUOZnGEy1lV1NNZ1lNBVCR2JwZNwclx9e/Q9Li3vxB6uAfImeUQg155N/ LF8H6T2hydXJibFF8m290FUy3rT+059G5mCwgUMHomaD88lpnx1a/v8ooVNk8sQVFKmjs2NUcmMM jkziVTqlFz2s9WYVmKLHjApBcb2mTuplOAfZ2QYgUofF6hzA2yW5kYNk76wUl3ipcyZqW95keZeP u99pT1p1sUz16JDD9DEOLI9E2rfpes1MD+oJXNGHPZKeNs1yRUsKPn22dTdymlxJ0JNyP1/CtCY3 B7U6FVIdnI2dQZlJDEmbtjMJQ605X3hWyzZovg9zPUY1OZxs20rvJClGbU8NBdeN+o8EjqCDskxI 5MnQqiIPEhES0hY+giIxyd6ZJOWuXLlNmCh56gqWMkxvBAxSirexYwcnRwWLWFWpMySKPYsL2UoU XZQXk47KjlRg+zHHHGk2VMlzIpU4OuipwLzc7JFDswKUIIcqVmXFxoXBOciwt1g2RTWX2FgUkGIj qSR0GDy7PTDEeLIuMSUyppkzg4qdlzseYw8+DP67N51Y0eCOe72McHEPYsb6PJ5KFzxwVczUYcmU JFC2Scyxv6JhPlv+IeMSXk+JrdTUbINM7/jb4fKe8Oo+CdDxkfE5HpijYziEwGd8a568Hmu5OaZG 6vf7/kX1o+PiTr6S+ANTPPqF/MLwOvk8vas2QmueCu1EyrWrloAhDgSKN5XbqJVkXEQDwuOs5xra yoqQQLwFZlzNQphdDuJraiq2xVVJkHbJ5km6wsA1JGJhMZFZVRxsxtTE5txumdUZMjlGVkmKtnX5 9PfhWVPiAuAEec93FqjRAoLkGhIiDC0AYahaBHRK/kO9EE0qXazV2VHWeDiooURE/I+3UuJFDOC7 Bm4tbKGwx+ZLk3tb0zXpri9sa2zCDQ+oXKHZaRpF4GI8njpc1uOVkLFFzwKAjV/ew4hDMiRGacTx xfR4kmF+jN2yCMiYRjulDgsYmVpY62crSC7HB+kKpSWy4kmM2aa51ZprmCxOrnJMU7sCvMlSUy5B vWxhfIXEQYtofqyn6cki6tQ2m+B35leU5p2froAgrJVQqfMZzHR8dt2T8mitfflnrscqkk2gkIJz SG6H8LfxuMIidnBcpTkkXPwD70A+FY6OODl4uzrJF0NMdccRqMZhuRgvkKeydkcctWMXMSzoss5s SD3O2F9rU4krHDdCOyylzNoUkOvNp81iDkEqiQVjkz0Z9eviTN/jmvObXCwWOA+FLBiZ7IgCdJg9 iVzigdRYoOve7syHlCTTkaGxY6iaovKYPaxq9OkJDpRRkqFZHNGialylDouMeSqb5vxzp9D9Q1eZ yborXM5dQgAkrvu9fipgKqdC81MqeTz2TOPIoYJUKN7+b66VUU8+tL6PS0NBs1Kw43Ubvm63rUz2 YnUmY5N+ihVQnzVrwiPdmMyNXk8p8ceYzcoqnVk6HM8SxgnxxnbFqunRciSIjhiwbA1Jj3IunVf2 iS7PStlHxlISVw7eK0ePN1ukjyDqt0LCWhvNYFtiN5oRiTGu12MTorYnUspQoLnQtSZ8iZNWQDVy SzLmzJdQqOMaRCDZo2MXM4GFJkEypQqVv7C7cFF2SwXJEigOWKlTAxAxWxM66tQd1XByclDEXNwK NyUzB0VL5OoqOfgdkGD9nPEFCqAfq4xwVMj7OhvJ+R+XtnFerMsiPBIXk9HV5NRmC+ixYKyLi4Ss jgtI8q4x4p0b+cd2pF3FGdJ5yPdNXNcj09zvwDi4729sDi7doqyoxb8/dX6anSvzsXj+X+/4P03h 1DqsDBS9GidQjh2CdcM4rBU4TTEAPLcQH8eQ0mkzr3Jam2ZFDDs8r4B1UZSifkJRp1Vj9KFvA0Us CVBEZYxfJcIaYJpRnUXwmaSWGSSVCiwQKvyUKQsDEbxxFzmcVxFbI4RLqxySSqZFXw01VjjjdiyR ZnnNAKlQytmSM9IhGN0XapGOF12jHK9JMUBHERhERgLiIl6hDEgQEHV53Yet4nBW9Y457jFQBvyg BnzithXFW4vwDIxy/hb7Z5uiGvsfRijse5h5fOaw9zXfr3z4typDSVgppEoKhRUyrKG8CtOrH+1J j/9u38Ob5YxJCoofp/hGOf3b/2YQeGKzYfP+BtRCoYw3R+9gKuIwqcsgf1z0yrdO0mEQjp8qOa4Z JIoNXXbwjrpWVWk4hm/fXcl6f1pnTwAfSKAQgrATVb8DQaL2JvlIP1YWyb+sH/0g39AHfhTY1TJM VO5R6BSYfeTcb0/rt8m/XDwIYSTUKwiigLILEGAqxZBSJ0IJYLIiCjGKrGCkYkYpEWIIwGKKIpGM RFkYIHWYiIKCKqAskZhkhhiozIoyZEtASUjJhUUcAstAwmTGJZBgxsICqSCqKRosAYCERVCtiigi KkIEVkEZBY1YNjFYT63Xv513AfhZNH852j9yj/OpuiqFMRKipAMPtjAesQ/wYhQgWfQr1vzS3is4 zUG82/bmLObmoA+9G5VlZNCo33zIpwsGwJeAhnqkeYvstkH9GCSKBQxyDPEz6vv+8oz5XVoNBiYX NrimBgp294lXQaZ2SyB3MLA0QNQk6CUiXCUUoQEopAiKWUgi2JYf1HsDYGbygA9/vEB5n9h70g7E vkEfxElM/j+n+9QzDZf7sg/qP+wbB4p/mtkpMNSf5heFjWlkwTXIYl7sEOO62ahzeQY/oDSQH/sl k/0n9c/t2A+Q/GCTmAsjFSCqKSIm7ALFYxYLFJJEWEUkBYiLIiRIrIBY2qH1hqHIH/mlgIq/6j/p tvMy3UG/U0kISEhD+yl4G5GyUWhmUM/Mac62lk8y2BuRiwDADIzf0sygEhtENQQ7IGHs/uFk0B3k 6qCxA7u0y860kL/EdxlGf/HonQOhNzjwyitxvJaFMEm/NL260lnYC5G8Oh5lNAa+pqKFokR/TGMC uYMPG1V6XrReUqUW4soT2ZIXV0DzTelk1eZM5C5HQdXhe2ZXp0k4f+65bM8o1R65OD1Rrg4pe6Oh K1RWtWrUjmTp2kzO9vKDoCJajIKhQthAK0MydRvVIeOBqSJCf2GT3/Vh/EiO+An3hD7FYdc1ushJ PCwJReJihqJoJeUUTrCksrqLlpXI5ysNqWC2qSE9LqhwK5QtbUVuwEkcx5XKSNUjkiKubY8HtRnm MyXqw8VP7G5L2ikmKpMeG+7xhnOCpL6eUN+5ra9I4xhHBJMtiqj5VvUHda11rJVQ5jzdUSqKoe4z 26pjaymiGCtu+KeSakf9iJxBFDPETSJ1JSi0bU6N5HvkNSUi+6FF+9Mtib8Iyl9FGKHOGCPoT/uZ m4LpE0DgOzaBS63lKvL0SgiJqyBOwnnwgpSVOfiZR+noovGJnJgtBRrDxoMH1ygsxIJ015EKJtOp 70LCaDSbChKWkY17jnGgNgF1A0Q8cPpwziKgmCSmjg8vQD78YXYnVBARZnSgInQrxKYG2cf6aTc+ uVEisSFplknFxWki3ZZFLdxjB3wPQGgDhSJvNpRYESUlQCgkPeggJXzOaO8oPzWxj4HaiUACsTzH rTShs1zDFdwsQ6TPagLB+wTyTFyTh0YFx6cirDsNtJ55IocaKWwTpDOhoTcPivjBKjXOg2IXZFKd 9nOOxkt1kfFJpDXGcZSGK0Zi4WhU11PafvyuncpOutEUHdaRubjB14oqpN1FghhboMx2H4OAeb2d 1HY45Fze5ywdaU9InOG9DIwP3G1AzsVORORlsc5XNC5gnfYoTzPd7LCc0T+IHJxegKI6jUmKlkNw wwLYCa73usLRBzgm5DHB4xCDoJVYGRoDGdA5FlKN1NlYRG8xSwW0Jqz3pnHz4AXaQb0vTMJSuMV/ +8V3kOcgSMhGb2Cz/yUn/kzq7uoDikWD1sYupPQOCC947wexNA5iPoLkgZdXFif5egMxNHLYYzd+ +iq59oFx/h1jTiKxOPqBoNd1Jzho6rjehfdAuB0sVjpWk3FGxNCWLgcjobjgPEUbgERtMaLEfnPI /G5M8I/8sf/cP4ez9VK/qP9f6vufgQIb+PQ+C0e9IOA84IHn2g4OVHSEBzhvbCHvUJCoQUAwog0K z+/b0JwJD6KEFY5VzJBb+n+RBhEDoMw0h7KovICeFQJXGj7olv2SHh+2c137k4fv09zZAPrU73As 4KujMXF2UL0LDKqwth9V1haP/jWbDXUYi1qV1MjXImGmGSdwfuUp+A4ioqQ/t5niDuDyHkJrxQiq yNyj/EU2VptVXF6H8DEk0t27ULWLTCFLKUSIFI2DSJJZbAsJCISQWimkKoxuMzBvcMgwINhoIoA3 Lp67srBlkriQhIQkl7XENxhcaF5GjFT/iA+95uUDQrFAeMtQqqDBLSKIY770i5UJwtVoc6YBxezt kfN3HQDxIoKshBFGAG4HPBHupRfPlbcEVjFJvKQ3wkAFqIxuSBWjZLRivalNkJlaGXTaxVDf4AQy Vm0L8jOducosuKmqpKSsKGrBCiABIcy6727jrDYUlQkGMRIODDaRYYRm8OQ/BsMUnYaKZALmGE8j CYyLDIwMSGILA8SEDkDQH2vHuH4W7Dwekt1BcUjooKPyQ1WpkkJEYw5uH/J6bwJsl+cYqAsE6kqF /cZH9oq4H9wfD4YSP+lBJ6xgP9DEjsmf4ixITBf/Ep/1Ez6IkrWC5Y90CUrz4veCXU10zPKmzSH0 EAEc5KmcmDkoIgBMhSZI4OTs2UNUPkIT0SXJjh0hZW5LmlGKCmjpcFpFLYLKOSGSoyWJXJB7H+4H ZehfJrRSOYkpDiKuSWo0ikoKDvFUXlI4jx+6JkF1w5kOELgyP2LQuQHocbY5YuOpwNI8TOhXPRoc 8SE7sVNJXRIv/j/NAyaQkpkpnglc4M8nJQS5M6Cx+AGjoUitzBU7Jlxifr1QoUOHPvROHF9GTo0R EKOeDvbFcHAxyHgydmSxg+YWJW6MnjxbBzsFK8lKWKnyRHySbryQYCpdbnWIcveuRTCSMJo6HFGM nMj6gteiQ5SKKjmhxjQYkbbCkdFUlTisHlppVzAOv83AHOcPXFAGef9iGGBlABHxcfZaXjXGpy4c WdxOJy+s68m3llYzVTcPIhzJDtfiR3diROQykWGXYdnZaamZAiV01EjGgmPwDEzGLPMOqXeyObbm FDc4i/53qTJmIDPGQ5mQY/s6+fidC8uNssxaDGzrdUm5cxymFVh9hXU2xurTUfVR1IuWbzhT374M UJD5j+77stfTS3XC2uH1ok4VIO6FhDY9XZ4J/fEp5kSkekkJw1p1E850mxEpLxWMG4wFXUTOY/uG SRkFXUJ4F98DG3vHYuIXNGLRiszc2bQ8S9nhxjW+WOTY5MGTNxwai2tiBhQojbvaEzHI+qkBxpSb JL8vxf2D2G8PRx4DxcCRaQJaTw9rHqESWdh/iao+l9ai104r/H2qKnbA9wdoBzGkm/O+kgkYJpzG K2mFoY+/eDklAefFC0xxR51IiKHsQfsPQGTkCWJQS2SlghQEsEKT5Ik47vCYQmxvQlKNhEo2CWAg UglAGRpIVQUVQf3r9WtNGJCB+6l5E4UIURkJPzakwSwY763cKPMGA8axOoOGLAZJvYjBh6uCUFyR NBkxHpgoBZIXaCl+6wug6Q2iuIPqDNfFgxTDiylCtyPxj4xQ+K7T/ixF8D6RPnbKEViRdGnJudpw wS7yPoMB0Gd8PiN2mfWm7pTT7BP8lyxfMHtqsbqUwg+tMncJtC0KSjC1Cgp2nnbi7vgHVAmWMywx DuAzmxcqSBi5k845Mp3bS44JCRERl7PN06j3NcltaIpLKZnfA1JH1+EjvzrsLXbQXMlVy5a76R31 UgNhXJRNZx/ja/imXdo75gkjrIkM95niiE5rQkh88CJcREUMQcscSzI5+1saC6jBL7Ults9w5xUX nDjToiPKRqjWPq9x9bjrZE64cTeLr+WDIIe87EjNLwSySNWZdewryQk9HcL+biD+RI/BZJPFwwYK u91cfo78v8j1UnCSa+2fyV5M37Pgp91WNn2BDoPqfUtY/qKEpf1SDOtMWPR5L5maPReJtOFalxSx O+D+3WYpxyVCgxUgixRkKFhUoXDqx9BLMrJlScTIleVA+46e8EckGAnoNdejs88ZNd7bs80OzycK OQFezGioxo/tk/MEGtXlR4JHek7TRmdeaVNjVoZmZgZDy+hAUEEg8nQGsEEjRorUpK58EycUJGEB KHBjeRBx2LGhigNoX3BGKXUkx7BY6c6NGiZk75v65LNbfIxouayPxU8HeDk31wCbBBPoJGENBWUj riTjAuMOthgRkPMJR45GSR4I3BebbamhpT2RDycjCEiDkWb8HQps9DiuxanNjsyK8JFF5IoVoxIi rrnGhtskfA9mSQsczMxe4vcZRKjJZ6YxSJ9cjggJmoV/HzEVd9puKBi0xqIG8HRLkpM+J8KnBL4k Fy+/RB/UEjAtCEyQfqiUo+BVJmCp8DbqNUmKQJIkOiJfZyUODxgMUFgkfDq5ahs7KqaGsTPckOUO DmpzMseMlCRwYRHFJlcC/P2EAZELcsVL10k1FGHGffj6ZlMikwL3GYxnexo6sqiYhX8pAovRUST9 WRZfsJCe9AI81+Y608rz+z/Ok3mgzBkauBtLjpcLnGmLM71/Q8tSYraLFNknqt5vIMz1eCdvDOl6 /ELJyT6PT4ekecPQh9p3MKSFEoSFMK+1+gPlwMUB1pFMtAA8yINtwa1yiepkO3tF9w7XX1vdP2Ud ijbNtO48tvOJ6ki611qbugD3HHcpzisP4/AcwGR3ZzBIdB4JVg5g+kDt608cg/ghedxQR7pRCp0v Uj7PIp7jORGj6WI7FO0CLuoO8GkXaPed6QxH4VE0kxft80YnW5Jebu+o+qp8hBQ0wUJABE0nGrmL 2gJBtSSIcAochyAGS+CRSvk19d04Rh29vv4WqVpawHznGyykl6KkRRFCkpKcMI+0vGM0aXRL4xj5 hxiRHGPxDTGzJZEF71RMedpoRLSgi0hSnv/D9x/M5OCidFXvj48rThyfSXHlzdyYtTJ3oscbOzg2 MbMFEwXMGqlBjJVMHdY4Mhc4INln/lUYwZHLFCDgmaIN8ExSmRTpHRcHdMizKFiZVy5BDGysiBSA UyKCn1RAcgyTHGOipwXwXKKgH82KlBS569Ktkeczaeqkxz1s8lCPBc8HoclUmTqdmRJBZj5CUIc0 ebnmCpxBcwKI45BIg5LMTH5KnlIKh7poLoj5KsMLvRA1R0RHOQwDyt0SyxUsKWOTfM/jvyu6qbKl g4O+g5OUEoSsfEFsbKZEjgsXggvQUz3kg6nk3kmQKNccqMiJQqWFODErmz6SwU8aqaJmNGzg4N5Y qUGP7H4Gugkbv5O7yDvB7CgrCwz4HYcr9TUYnoHvCAb8FlM2j5uxp4PBZsXOo48umqpJ760lVJSM B6jnsmEpgxivTeZiCVtC73IulXYdfZx3Lm1g/ImbqZc8tS9zkwdDz4HwiHdQhQSRE0dv8S5vowaN EiRskfEe5A6kEZpB95PRa5qe+Toaam0yvbmjhGC6P7Tw3PxXug+Xvks3l2xcMWlLPG1NjQkRWtTE yYRJkyJI4HdQZjlNJtOWij4ibA8d5AokPTYbSBYpYkDU57pCllTDm2c17Cmtg2M5EbXXsKrQYkSy GK+2Crus1OZtIZErrwRBFt4M8E8JLWoliCrelILjcijFODBYsFyD1yTO0sYmXnuB3mhOzpA2lzCo Gjda1wrrLqVS3oU+lcSgx7hf0kSQkVEPoUDSreZVuCcr4tWe0fVPa7eFErhZKCQQRQS+MJFLIFEI Ru1rfaS2Do8gHaGAgocN4Xl+oEaWj6T3nnzAXt54qAqVpbYHnFbhLQ0ESjsQNuph+I2CZEjEgZ2O 315Sc+GxdM0pLr7Kse11dBodfQig9j1kNJOTvuTj2Aa+iATJKMbWRLKt0SIwSRAgpItwUxS3mDAT u9I9XIajPn+Inp5dIRcvLnEDxEHAWSLiZ6ESy1mzG3MSHjhgaD3PeFjfRL0AFy1TylNnRr1ZIXWn iR1ICatZpwcdMK6mQoKQplvDm2qmwymjMzQUw0GGQqa1TCajrMsKlJErEO6Qog0MAyvFh6fXX0p9 Jbra4oKoiiBnCHlO006dREDTPsibGgDbsmRRDQGJgQahiFFPUFBe0KkGKLKWQJNtVUYCVIqSYo0b 4dO52viwNrjsZa2T2NmCCpQY/WPQaPRgZP2M/yyN+wiItytsRluHzs1rowaMnByVMEiomjcihk2Q TzYYmaYwVLkDn7FdHBYUzepMeUG2kUKUmOkiwxwbKFSDY1JFiZp7lFIME/yEBblBigHgTkMFTouR 8ECDJImdEEpnRHP6uZU2DEEu/0pSQrHSsJvVBDGJBGCZetDdEyON9FBeZyrJGRcaLeCwxI77p7Fb EWLeTR2WHLNEYPRPjBZqqGhxSeF6uVZVMxLDExa4jkbX3IQIqttpJ5ZDGLGEweDw6nEs55Ozg7Nl DZ4G5PPIKqqKtO5AmTJz05sUv5rm1r0j800Zb1Y0suXW4IKOb4NehESaWCZYoeSRQqSG9iRUoMOW asdbJcmtuYqapnexZuKlm/qZxUEh4Q7TqexPKOgNbTjaGQNGFgbmFyJKKhCIMIgMuOcg3oXXqRvV F1nGcfEWNlShPRM7Doc5OQqSW0dkqUvYmSJjMWJGwBF5SKehbef0hTSz9PRYuRkugfZPSZhKQPBc s+wyxKzYaUTQmbQ3kTzSKCtIWpsSKqa0VL+DPuLc+B8SvOuhjBQj8fFzR+Iw1FT6Iidpo0HVDupK RUT3/nOfQx0YaIPR4yZPBIpBbweTBEw4KlbClSw5yGKltgqKzb52QaRPsg480Jb/BiNsBFI59tZc Xj13+sZxcLEzY1hakX4FRkaFRryCxKbCwTkdHRJDiZkWyFJMmRgW+sLmjwk/glJpm/yEwk/sfTY3 8Mc3lGuy0Vw3qcS+2JN9tfrXmLWTBQ7VdxqNljoOI6B619Tvd7e8FmClzqMO40xZNbZ4tbRvfST+ Jkj0kebP2jRwXmaHuIR8+ufr7z7FR8GObBl2OihVngvAVYPQyO1SKWWqidoVnVK7gD7gyXtTUHOe hTzJrB9UFPHxN7C5CFMKGFMKDr8DZygHyU1ufrGjeH1bUwDceS8IJuTmMzsJIQzVRUKIyWKKWLzK cBXhxq5+kdvmsiiZB7i7/pLJxq48Ya/qTSg/ADe8pPrnGvUpTD3xlJoG9O2G4qu32/I61vnf376+ Da/VuAmQYOqZlOm2GO1P2k2M1nBAdWkfp8971MSCwhXFLIUQuIhWwyH5AuSaDOWOBUwvrfhazw6d L0cKHPOzwVZk2w+Cg/axynuzaYm9TTRApzpCuVnXlqItEYMjswCAKgPQmKFpMhtRVnNEVC5IjEIX hkHVrZdgsRRXuWohIWT0BtshUzPi+CYbm11SXU9WVujkptWU27CcVYuqSQlnUCaqxI+gwws1E5YF Qm4iLlDpstGytE3NjeRYjhesHNHe1TAI9Ov1WRPI5JCll5BFFNDIciVmw5WJP+IXB+pZ4ePb79jk Uq63W8eYEMmE83OHJG5OZQdQhnbM5NAo1QWJMRmzJ7hGdQqEUVRe0aT0JQEUg3jSKIRwgfkHU5yx RAg4lUsJgIsYiBoizafA8ww0Fi3vLz4HKXd5u5SxXMUDBWPPAc69KQ59ByjGzjdYU18rp8b/Uzuz y17+nfGWj6el0uHl3Quv7qrLteG80OBUxA24D/f7nTvNjq5AulBqkEisIkjsSxSCrAl01IYELkj2 BDHFmzHkWpUc+ZB+HWBihl5noqaJ9UsXLRT5CHznnAkjIxEWF0C5PZHDBQmWTsYkcLgbBu5kyDTI Gux1HhWw1d5XeVWm8rYYrMyxMYFpYXlhj1IUb9eNs3x+Lda/pTOD5kO2qxt0Gnwrd5ZyL+ym+BFt odtvjxe9T2+TH31Zevo/mnnPM/h7fS1/bPLvD+ufeFtaGf8Op8vlz9N8q8d2W3Q5Zb5a7+Gs8Gl3 2QK+mENrn1up1yotplXzwtrqHmHjzw15b9sK4juBAuHDHa+85FiRKgTzuIHcFRckfkkDin4jsbRL GYFKZYsUNYELolQ7pUlmIg2SUwL4K3IsFvYnMjkzuh9fr1AYDFuSsY0D3h3iNMOFBjCFRTiriBna c76iowI5laqmAOTKntbGGPZD7HhBIK1NFKlhRA+xnXYSLExi5wMezHg6uMwpQ8DcOeJCtnx0i/Cp U4JEyV+RI8EBMnC8pJxLzfz6u0O7s9QPFFDD4EgAkgA4cgbsgdgVqjIstFIsgRYRQGRQEYowUkWE GlJCSCQJWZ8Cu5M4RLCQFQ7WDuUCZjvkZ33Mnm3EeEKVFJS5aL5jSdo44Hd1cb+g4z58OaeRf0qP baBkywZIRewAllqyQ7tHxAaNE3EkSMGCEqoCe1tDxc62w27ol8rw7SgO0ZaA43kjYyIm/faVm5mG ORyp2HA9iD4C9HJo2SmTRpzCRJSHkZKzojt5r3qRw8e4toy8iUeilK52U1qShZhYc+CGoAanvu3X nqcvfZ6zhhoOM525g0f6KyOWSg1b3/OYXnRK/RyyoTtn8pF5DWkZJR9RYsn5FYdWMq6UQZnh1XGh w2hmmsTgadaqQgm7kGZX16HWpSYhEKBYC6vkSOB16DqTruMjWGp4sWttcGxoucUvWmynedD3N0KY f2dkRCJiigX0oYCfcaEQoNYtA235EyhojF+mZqaGhH4/cN/K5zDdznbmcMwmaLFml/VvIVhyIK4x FAiFCmdW4+nDFJaiSup3dnj4tH2vqZ8evex4eGl+Pphq2ebVa4V1mSdckhOSLynm8ITWmOcE0Ckj 1YV7uQ7kMaBMELuOJQWSIHeaBI9PSSro7qkRi22nVraaZNzJwTfDNJhdRO6Nl30jhggt6w6sg9pC 47xWDgaF/32X3+/mT3r0BrQ5TuVmAyS5oqs75PnH1+OlXCOlXq6cvdXDnjRTTTjpHxEl33ZH049o 9vzm3isEC0SJanEpRcREVnT6rKtr72zGKZ+++TdnwxrPfyK/MV4hR6VU6edXIAhRyB4H9/6w/vUc z909vfE0+jX5LbFPKu9UDXq/jofZiBhIo0HyMD+ZLsEwTMchCENM8CqNcaS6kyvaimFiDy13zWZy EhnipUIRIOvaVEfnrwNH71fiZtXRnaTD3hR8fFXORN+P2ZzPOOG65la10pzMAUuskC6KWRfaMkRM y3IfC1wgDcvSKvw47kYj1jm63oToUDA6EidwhF+KfYfMI0v68M3MnKKvpEPFL4bAQ8faLHqcGM2X JJuVYRHIZ7hhx2++UJsjd12FyI8YXeCbzbPracqiSTdARIs5Il8dknMQ4zckm2gg7wKAGEQAWBbW raHOWvc56pgmUCtC0JfoDMfsgByMUPguX369OJpokn8R+EmEnq/lU+sfd/cXKtrz8k0WT/GJsYG4 VoTaRhERN5tLyEgdHSTqGwGNSyUuspz84awebUfRxXsPXOpD4PQ8VEVZLrkk4fZhBsKeUajhxJFl /7Rhrn5qktQFjEHAV30nTid8skQAzvMJwgDyvcWTpVDWnbFnflB14Rrk3zqNoL7mNyOeQy4TMqSz br3ZSCTrwSMq3QZv2Kkvk0vWSSLN5R5FMERCvOSLGtDvhNx0lKEkjZBSdEF60YpRx+0H6A4CuCax Ox0kozLEWEbga/opK47rJLMiZfoYOGmXLIClEtKVEYbh5ybT3J0dX0fjh98NSVTtkl6ZEuagkaUG px8Waz9Pc2sHzU9qZt/8zJpivfp+dlrX8fyZ7Niljm5QXsLurGvCRaU112WWH1GHkZlBJ4xkMDNm QjIlVFoSPw6TqqwcjpwUK/kEQcmBjJvsOVKFy4q+fmlhD95HAvg9bLFjixAmCCrmguWPHvm4ePD9 0MmhjvAIJ4EPqbcmcSOTQp7jD5oc+DOzBIsSDdmLg548h1q/FNCnnh7lTnaVNW4lksJBU8uP2XJH 9CFrnbYLDjlBjJ2bFJDngU0ULuQXNHYxQ6iTjFCZ+Qh6QNhBIxkPMzOzJUGBIkRGwMpBWHiktgOg W20ZF4opBY79HJ66FgrSpycmCZYs+S51MmQXIOyINbNN60bDJI2YMJexHgOCpIoT52cFxpExPvNx yiNjJ8OrGSJiSlQgwKmx+iDFbHkRyHlhQONNCIbDFKEWlUR48tMvHmENiW2Js4JKXwefNrlzu52W DgA9YJFKxUNmzBImWShI9e5o5N+D/OLlyZvBwiJcrcc0QKbmOKe3x/RDgudmihY8GRihqsiZIshM 8EoGryX4LdH1AY8hwhtS/BY3euyobLmiRcmQTNFJcPmVkikSBGtQ64oHG0dY61j9/LDEKkdHHKik kaGZjSakTIoAgMXDScxkak6Tku5aVgM9rJko7CEbdq0amDsvjY+RE2T3ROuTsDpE3g6R5Ajy9Uin 8zGhPvifrlg+6jyZ9YoB/fRfJ84dQ286HwFALC2FAL/yMcC3UkMRftpHEh4e0jAgkGT6eZEHn9om wTtaVGR60ELxN5pHkfdXzgCFYI5liEyXkjSnkQdAcUBDhBDlFlxppV5BW1B3L8KyyeMbJwJ/1LqB 38FOgoTxD8ILyFn4K+O5Mt+4V6sRPg6l+6mlrFG4WQkUyA96fTzHm/KR66PBHJHk0ZI70PJx6ZJl 4k+xJSy0pKkIIcIImSwuQ899qltNP6xvUpU9BwiudyMPFL41ikfKB86CggvFCsDAOBbbedv7xqP6 o49vp2W0GopfmaLm2didCgtIjGZs2185Ncfd90nVtGyTqLbcpJsm7bLDrWaLRoZUkaQpENhZSjrE hoSCgN5EuWSeg6O9G9sXnUcENe7kDsXUBBxR5rzACCkgREKI0kTOGq8uuWXjoty75Nc+7XtO5inG Gl5hOk8Q+xqHB8yJ5+CbU849XlHQaG41HhpOcPtyknwSOE4XJ2vB8XyKlpKWKlj8nHZE2I7YnjF4 8S+aCWoIT9/iCOYsQgDj1GPcl3pVdxSXeBaNedT6iWDRr8zQVgoCYQNjfeYSTwh5wpBcBXGgYuCB EfAI9g0cRpC7wA1Wh9Ib2txSHS3nuX4R+3TEy+PNzRjJI+cZEEE0rb1hzh5Y+FfQyUBT56GEM4fj HJ9w4FggHzcE+Uq3/STgA+6GQ3AfP2e08OGpes6Tb5Ch9p0IBbWKqZLBfugQirIkQBYIrIRSLIsg sgoCkRkKoVVr+5Gj8KLkqVUSI45R+Qu5v76mdlQasoESoJ8g9E0+ZPMHtLLiJiB8hpHFVVSKSq+J 9T6FHD836x+oiT8I4R601LzBvV9xrDuvOi+yXDgtoJS2aRL03HhIwkNioclVRVUqlCQqoeStw6JP ySSdIcIqOUdIweSbxGb7D6PnOb/s7PfD3j2ofx/aBDWRNnwcbu0fi6InUjzwSTtQrq3opdOxOPuS PlCWj7htO2T5v4/DCJNcmuGofGRgxe/xdbXqRnGacT70SIc1ZyksGZPsW1AdKnapZdgZlPUtmTp7 tCfTVhcXJZsalrLTgUVIh/aRRMiETN1CsxPMnigeHnKqN8Eb4Kc4rcLcRRELhp5/A//JeBy6kzCu ARHY5J2LQv4kVfNcOmHdyitg5w5Uf6P6Dj+cJCEkC1FSO6Xs5Yjy/tW5BE3aQoC+5DrLJ+eOW+PB Sfl2zsTBh/TI8Dr91TUoEaDD2Rj9LnJ7wsLRPiL1GrtgCBDPXmgAoVFe0JCW5lUJyFGpFmpUKhGi RNCAuwduPn3EejpC9CwTHwKIQMl4rrJdEhEMIOyySKsg8cCEF0seKwFXGYUhQvdArH5zi5p9B8uI L/MC9S6LFKRejUoA9B+4aEBbkfzgwE2X0SEsVr9MqxMTPFbjf8bjnk6DjjCUDi9Z/nv4+LhUX5/h epaG/o1Et/xtqMcUeYKwaKUJpiesTrziX+b5FHDebIQORhVDF4S2b7HnedapoCjF2I2HjDVAmSBn E8aeRg/TOdneQx/SK+ArkK3f7k6qIFQE5BiHOPyCnoA6kiEgl8AChWBBWDFQCMFYB2SVIWiiXk3U fb6n74H9bNx9iHTO1fiMke5ewdOtdwBtJCDIJIhCBFgMVjCKTvr92hD3FxhrTVkAC4BkBcXnXcQ+ xo+YQ7+A9iTqMncpFVLGerAo4UyFhCy0pJVDSmTARKGCEnHEXzLzpnaTTm9Hcdqd1FJV29Q7DcNL rTUGwfSzgkjIUpSSbzqjCcaeUjkuP6Hm3xTfNWr8wN69b7yBvAga2wxXz9i58D5CbTzAIE3wuDHO yKkN4ew/N7BQ+xTfvCvL3eW3C2oNrb9z55EOiH9HFsse+6T6ycd89P6IOCXnM8Ds3dkToeMZ9jQx j+GtnJgdfvm69rHme9mn7w5f9U3SSPsdAfA9h4yPdEJRvNsPd7ZO+JybHucnqm+u31h2RCWieBHY OYa/IdjV54GosX97duzUYEahzEMXM1eVKwVgkiDYsSgHYaRoKTmR5DlTV3h4GfvwV1gMqoAmuJ2o Vxgez1o2Fckcy/xEWb9xdOtCSCKAfUg0DRGQuFAbpqnwzrHOgCenv2OUwQpINA0JUWRCoyXHeEJL v9vuBv5L+DMJ45L5aLKfz1FlUf12xMbfJhFqo6f2hwOcna+zujzeo6jTWV3yRaQJtQSdPU65O/uj 1YSd45PKTblFjnhyk1ye84T7SLm+BPGGoevT0yT5Sci8z1ocmFOfE9x34zlEwhca08DwYSSMSQk9 oe45U1BZfh7Dee09XbJiTsPJ4OvdwPjIk7dWSJtAqoopTIyiCDFGDHBgUYhR4nJydDRW9IcTclEU Uui2DcNACZNqBcSDiRAwI/ZHMST3Yen1a3sid6xGuUUqRHWKYyAOsIqb4CmUQXx6kuNq9AWHcK8y 7NanJtUN8U6ealedIK7YKHrhCBCDIG4XoEBd2QCcBppdgRsQFkA6ChtMX9sYRzUYt0e/2Y+dy+xJ brKplw6Izg0jE8ZM49hlvuS2w1jhUWrmstda6RqUTDvG4bkDIvAxst0xhUW4LJ0jrvojDtg9sE2y miQAeTWZiFQRTdZQpkYQbwooTBFEIKAYYGTW8vjg5lxBEKV4w0T956gsrftEwQ0JozpzJwt58OJD 1JnXZssyxxomqJewVCEAAhEu9n1mXAPQfP+9B2kRe1z4l0+CkyibEkfJ4x23nhq4Rv5P1jpDGeTH Wl0eKcXlgCM5/htzdkVSL/ghsjufztDwnI0jSJiRUDrRgZLORHATCJBknQko4ECo54knKK2D2FlG vm4WMyOSPs8yNyGzTVB5xrMK++nXG0Dzake34BkF4cvu4J5+NKhC7XJCRAKAlzoX6vkF7ePtZssT QlrD5/2PRY2609YQ6QhyCQYB60q8fMty92rWqhSgYCtIeKFzrBGB4e+KLnOdoMAIGCFs6N41XahX tTO3homhPgmtEHSp6MA0Go0i9/OWlYVZzJw5DLajpEbKA5kH+wCgp+P7IHrO/fxs47x9kF6miGEy lNimGaynBZ8et8gwlKkBPWSgIsxCsH5SOhdFQ95M2KQh5BERNwbB3JZC0Sw8RJK0LgvTRhScSjEq zbb+y5B9RLe8+BXjdTcJnDy9XcHNhPji2j3qXKsgriYihEQuAYUSghSpBSlYUSkhTChhSwaE/OMB wD6nVhZ5l5hPp+jiXt7k5e0T4dtkpelOnkKgwNFoIkgB6jxlgkvZvIMUVUWJfRz47ykxiWYBmLgU wFbxtA/JYV4I2fIV843JlDJ32kmTb8pOH9KdQiwMPr700cqO4ctgI8ip3Bf0o60e00nAEJY6gbhi ROxPr3V1xzUNxTqcmkWNizCUTSHgt4rNY6AQSF6YiVEJXSCNqP1qX96GufiW+rKNZOUNo+N5l/D0 M2/lt4W94SO4NOIQOKWQD0rEvfgB9Ie9LgdqXKs+hl/o6h6zgF32Xcb78P8sEahlVfQEAwOsYp0l oEvqyhSpSh2z+aJDATBNNlk/MtRlr/5OF2X5QOJDXlknTIMGCIiYHq0BgMkMYmjNagmNUd4eKe02 +HdfDuYYEbVYvRkJA1ChO+mAzChpkw+AdGg/Z1rgm++45plqxyhkSI2ZrWoG+tjUNbI4CBTSxUyk YMQTZF1hqS8dDaa/zd/k+XqzW+yEoNGQqrJFSIAaZ7+a12zsiSApcK4DCQsCkAoV+H1/FcDk5u71 bw9oBaJ9I4QmkTKR+Ehb8zIOsKODi4xaKgEFILFm4SgKNZFWm1AUwJJ8A319H0Fs2EmPXOsi12Fh QCjWvPm0HCGcDoG/3oVlCWoEygR2I2BwkSwsaQ9hzfCwksBWKpwxwQXmAuBTNhUbyEC1WgML6Gpd IiwTMtygDZYQYAi3qXiW+ImC2S9Q6iF4BhEiXiBZCmEIRcx8K6CAHLQib5gWC5V7AMkC5tR8L14I +8ovVMEf8YiUQAkEkAjFZBigvaKQ5oFylCCzIsPyj7cA8pJJ0CPMw3suCmaY2VSSdinH+WRdhJNX MonZA128RjxL1rj2L03HpIIl2BsNIrXK/jLz2uVgbanEIOElLqPWgMkiPP5FevyQSKi9Cx0u4sOh HkPMCP5j64B7gvXmf3wOfzAjWeqRpkhUKCCE5BSnqS3uC7e3o3LZIAgsSHgUpotGEhiSQDSB9KTk pe9RCEQoZBFIkEMYIAxIvnAYSSoyRKQhIg1yOwDyC7X2htR12DEDFLwExRdvpV0h0KbPeZg4k0w6 FdqUnOVSn++E9TD5R4QmG8sJ/FqkHvhSRrZ1tEuyFYWNIrS/XcOSjiVIkEEgmEC8l0RvFF/sPuyD 5AUptAwO3Ucy5PsE0D0lsvgKvcaQSXutg3eHNLMHRLG6yWxk4R7BujUF0lnic/gM3FcaLm4hi3wF M7Dp5w1Cv3P8MwHUpmn48Mf69l30k7bOwbo+ejkh+VRDLMv9EWjsknQFipO1OGqSXJv3u2PmOMQc Lj9X6szpwBDt0LyH8xmXx4g7CgWMhDfyddyQgYT/h9p5m7zcFtbP9zgTVIJIqsIp3FIH4QH3akdh GDFSTtIUEXnIjikDkIgHeMURNiMEHByR5IlJm/oPrsT1U/dD8CJVVsFcvszqm47BP55szLeCmwRt ECniQifBMO/tZpYwiQkIEDwLk6ezX+QHsTwDw9anSpmTcfkR/LnVeo9IWL2MN6dqfuR+JEfb9Of0 rKhUUGyrV+0VLlosLqLoBUYy4D7UUQ8lQHs6deJMfUsMGqU3I+Zp9UFXIQfmZheYctAUedqkjjoL xWEBXILg6/NmjbN9r/TxV0bl7zFIObUQsPOh+5NapdrozLmCn8xbxyVOYb3XM0U+hC8Cj3p/WkDI 3c06IURITgF3UJvL7Cmr1/DcmS6Ojxd2gy6GT73FFuOtIuuko3I0CJn2QFik3xTUiMPmS7VVgc7H c2eMCKD6jeiAv2YA4oUkORq3QFsvs6B+IDjlgl3gZbUDV/Fq2wNcwzBtMTC/2rxcmRftMkXFExm+ NmKSeQqIXn1rkH3D+YraRT1ByDu2cfu9yIPB6OUapI4md6XPPkqUIF3aLbcOAZAHiSu9wPlE/Wkl yQKQJdZ6z7f3LmCTA+5/F+zvPifuj0/s+GZCO5MQ74qE96UO13li7XWAcs/hvS6G2ctSSZyYe0ie r3p3nxTuj1HQ9ngesjknHdzkW7z6Rx9IbY7DwjcnwKRsRwDg2T2c79b/D8C3+v0n5RwDiAhRDc4V aEmRfL5PQ7DYbo5oeH4vxC38dv4SaZ649Cm1drS2eHDAP5pikJDYAcg/AF4+PkLzQutMLm9ZvDjB GG5O52Jtm2eUH90fp2HK4XMIr7xXZWqcX6Ne1TDm9Og4/vV9y7RdHyRqgny2DzB33oLu2pSe2tWb MofNXefI6w0ryJ6Q6j4n5PimBuTo9oa3muUB6McYk2OWbQvMJLjnTtTzAjOcQ4Kt4vLKoAeIcjsC 1Wit3pSSsPbxQZ2IhseKdh1uw3hsNn6Pp1Sc3TJ2kaO83HIXSHUHqU7MF8eBvHaKiyCqc0VHZAQ5 h4DrkdgxPCHU2ciJ3yadS51SMGqJ6+AWGqRrMCpN4+b9Fvz0+Ftxf8om+LjF1zve35Mk6w9Y2jXE 7HBqO6lKr0ilqlKAolhGWkpF7aexmkMFBGQqWDIkBbaWqUIokUARWbkgb2E0LweszMoKCiIBu/Yn w776gfUdSCbt0qVVAmQe9iAdIW1CHo9BbxRB7KUPVFOhe5HkKnQjkXWU6i+xzjA7tTkO2ASJDhR4 QTeEAClYNXDQrZ5qQies/qTAEVbgDDISMScx0E9oH4+G4V0dQ4m4JDuG3mTXiTWlg9C+pT1J8Av4 2z3+8ufETOG8M2sMEcYUqUwQz3z1fBzIDCoYsUxHpMQKI6RsAvlBCRBTkgSCHHT1IBNB+qJS69+8 Owjq4xNxj8omg/OJEg29JktNdXPPiQveHzYVBY1uDvWYi8krbopZMUJwrCCgGAVJQgDxNw7ZJoIG uJ8z+qv3kTp4x/QEtqyp7yBFZFWONNJ+a1OciUWVaFx7kap8Uk2pJgQj9XWdw6EfSJy1ylg94WCz FIRF8EYUAeNVqzKfVyV4Dh3B8U4hzffEPmuGizNiZrN3QGcDZjLgnmy7QN6N97h+UKVXATkBG9Lw 5B1WRgmDFKElKpCi4CobwRouLLcHkQNjvjDlPnZW5eJHcc1yrvU3LuW2f2aviKXHA6Q8rn5og/L4 smvGe0OlO0DmgjyLrQ4I86T0Bcoe0Il7ct9JZTkHmAvC5hIXNHOpzAZ71vEC8JgFFiTGYKP1nuDj bEiBDr+Q9SD+VNKIPzWHfsyAxPpO8fQcbe8RWRCzRYVosoUUUUK1aKJQrkIPE4MUsA+jwR5il5Xc 8xzu4GurOLydMIFCpmSWUhp6+nNwqgilkdEpZLNAq/4Wi6k0JHycRqylbxQRIQM3z8YsDCM9QFy/ ehpHCzbwiGuRzxd9Jr0kcWCKcDSBBY0lDqgFqfMgEECQKUUI+aD3dlYh/TYllwDCClkLsTVJupBa B/0Yo5ezTI4WV2aioRrBBImnyqORm/kU0DFw3/wcGRJhDr/1upYrIOTtwPR896MsEQK8u676hz+g U53FWBrrrDVaQQwwTzQOSALUOAwcHqe8LJj3iWS4aPNzHgl61x8SLnCl6dms0xDfRNZbkp4i97GX bVMYmGkXgmHsKh5w93AkXlo+t0YLp+6v2p+TmT5rl9jMKJKQkD50jihFCwe49YWokooC0RhhENJC xEgxgrLRm8V9icinpPCepQ8vsYfSfp+rW8HYlglTelR67bGDDWbSaTa7P3UzWAKlA9k9gKGRmA6g yAzD4+R0y+WlPcKs0l6XJoDYl46IkkFD6AOiSIqgr9w8cNGOr6d5Nh+LmTgiHthb2bGS2snJ/Rcb O/x2rxfADwOdfSP5wDr4AcadUZJEiqqCxYLBUVJFkihBZFILCKoRUYLFhFILFfMSAHwwDDDyTgcY 1Kh76sR/MIxyrhHIelpwZI2T1k8ow3IEtSSVHrJ15twgwbVKQ3DPcnb4IaBpDxiSBIyMhIyEgkkA WALIKCiyCigiCyKLFkiwixRQFIiLJKDDxwPGfEB6w+odRrTyxHxhqPOtQ+GoLJtDmrTcj0Xdfcik 98RUT10pbLGMtllsstllKUtKWyy0oiMjJaFBEQQRFRFQQQQRES0lJaUtliIiKtKUpblfw5mnpHle fsF0GoiVIgyGSDOkOrDQCCAiDXUloZC0lg1YCxZLWUUrMnceR3geC/aOXnQoKc8+DlNIstCVo6i8 keBV8YFu2PuuuuT6+U7A2Qoo+3kj5fhdzlZR5j4MIenkLYMPc4sQ4ROFoJfUo8lWSO6HTGZckmBw VM1R6kssfaVNWpPDZNu6GrDbDj+4Wi88pAmE7Tb4kkJAgXvxPlxwZHWJmvTbtAiQodq/Cih3nrHB dqh1TWxAutCW/ngSOO5mc/IHX4gXGR2kpYUMSl+Z5K3qd58PIVeobL709QbFsegE1PL9nKGXywsV D7IVO476LdrOEJ33ZHS3IbUuHNfIZBhMUvxz57DDFsXyCuDksRgdiq5L4O/akdJI2J0ZVDlfrISK B5y57kEXYiAp3QxkcB4DwUNQNGuRUbQuO4WHaPJQ5yrFMRA0vg1jTwI6DQg+QhkYcXF5FBQJFwnj X8BkRIEJ7U3UdTaQKgnS3LCzdKAk92l5deOd0PpfEx3kNiSiUOibiy4azXCkkrSzXS1L7LlGBNyS 9C6FpUNd7wKk4fy7CikD5vXufX8IwPYUo85L/vE4nVDN+D7o0+ZvGo4ePhOm7rsp4WXYJJ13i6/d RC1L6gXKdqQL76S6+LKWi+LickukO8kDuXKXl2GgovSIthxAzohksH2B0cDmS1GaSPV1GX13BP6q MZpHiQicVrKAUrxKFxueopbqk4nOMoflFTNqwxcYss6YotZYskY3AEfqXy9s8A2ZahXLPkUaexHC 3RdWu1N1LsoywXqaLd+UpS0rB8BQVC6NJIb9WBaH0Dpz7irMrNahWIZ8ELxMkyVKN2UM8BXwQbSX PAWvUkXl18dUnUcoFgUAwFeQPBNMITBXRwyz8AsnMbUkFmC6kYHIMdbzwR+ySH0nntYoKoJZslyT Bmff+LDAPXQ+T/6vQrtWAMD4IKDOr+J+bAsDUFBlTKHZnYz5r8LtDUgdAZADPESRAdUUqAsn8s3m 1pn4Ulhtz2Ic/adSapNe2dyUoxi4pVIULQtFhiiEOFhHsuYTualpbSgQ+7QpuuMuuuqVLdtP6SJ7 e9JOO6PP4wvD3IMD4e1GZzWTU+cFb8WBp0mcus2PW3EYklES+hoq7UKyDIzVrWDYBvbAMYTcot/V shku2yfu+Peh3yXw5mlU2SdvnHPn9X6dBx/qNgxGKnt22kLURSoHOPmwyDpkl5aSQnDJEjkkkfdv l2rCHgMWnb70sgGrfDZJDYSpIZwL064OkNgFIvUr5jOBwcBylKJhy9Q2S666xawRqB7EubTBBJgP 2jUumFmrUgTaPCPCYJJijqyXlqB/L9JLdskus9j93BiYj8jbJ+id7OuEU3lcSjuO4/G0jaoKoXFS 1S/0Q5TtsT0ljcJYusSRGESRurnDxQuS0qkqqVVDijE6Efoh1hTwPuZZSpVSucZmF0sRL7K606Bt j3Fnj6vkj2P7uLengUG95g5Mv1q8Q3AniuQ3hPUPlyV+XvAPFR3BrBH0sMCHYa/ATHkul1rVCSTo u60wsp/73IaFXsYP7QgQCBCEhEjxw3gXc2tFfu4xwRsdvFY8OY/BIneffyhPaNx5lzjrAMH4HQii d4qZjfFXV69BtISADBCDFg/2B5L3ofuGQLaCRcYOUiPehSLwgBPVSAUSSRIxwPHiADS8zrBSwbiC hvV3JpFWfs1IFe5o1YP0ffyKYnu46wFNxWZpm5IijAPWlZUaBUNQdeYUQBLiiXPiDhzfRniZg4mp FkE5YDmXTKcxQcCIc62WBfVETECk03UOSHcjeOOJ+CWjWAEAi+sj4nmROg+fwOMdzZE9/cnaPo9B 5/kXz2qDai7+eUURI0ZFiBwEIJ5m26yE9JxJdH59brNfeOcOSeg5tp0p6xeZdiPsOvTJLqkE6Xd7 jvwnt9ae9/wKQ+l1p93h4EU7nIOPV5AekTZxZocZBqvlI2aLJOxLIUBwVlxokTw5BFKxJfRVqKjP Pcbk3IQrpymEconrs/wYQ2i+bikh6yLD3mzwOEkQuUkEsH1fWj6lSe4xS/GMH8YD3jj/a94wMB76 16IAC8Sel9qvtRBh2nnPYv1Hr7l6E9yl0PrHbJY6P9yutUjl30LCilJckeRC73+EcxpNus6PQ5Se UVxesTvPvGX114j6p4eD8D6uU5x+J43Kxd2ssopcvfZF5F6V2KbklaFwbddwEjqE0u081gaiv7zI 2Qum4+Hu9QYBm614A4v5R4c4m9K98CEGSMSEIpIgv6v8KFGWKGBAiQCByBDXDnV9dBui70hgTt/G TtkeR8ZJ7I/jrPUcmxc7Y2D0hO1PahiHSFwYq+uL4rDvTgvN5JVyMuSt6vca3h1MYfVUk0nxMpMp M3umipdFUT0Q3GWqBPCj9jPA6otDsRh6JeT0IF6xGIYLpU+pLG5TvVsG4MjDuMg409fepkHguHQg VJHqRkaexvUju0A86cgWIVmnMMHs3RDMFoovvLOIvwqr2c+kdCe14H8J+ovGE9jLbTaa5OCST2tw 9jH415yPGRvSc2cdsnkzkdXUcvInibusXdznyK6CpKnFJUmaz5QQfOnYi6A63zr0Heaa31KKm7VZ IWCqFUXpK0l2bnnYLgaJF1J20o80Dw4omLt4BqFyXihMloRFFKgR2mKWFFRuxOiVodwjEqsFYSBs ikifrF706ze5dDE9IeTukm9IeQiaIk0S55bqigoQ/KqSGQSI8wkJAQOKImF9Zk04atilgJJGawww VJq0kzcnsQzJp33oZqlLkDLuXQzzntTudg1sVWYjgmIra1RqFXpHPnsCJYBOyKNqm1IUhgZR4OGx 2xl5xOR6JwPBwOB2psg9Wh/JzkcrlkoWsiKPmP97ObyDfILglkZo8ki0DuNc07c3h2HEDuQrd9qr wOhOTsSHjJYfCTIeRc6GZrhonJyjoPOLtY+B5jzOqTrFOv5x4HUkm3j8feaJPooKdPGHajvAu8yW HZNMkaKYPBFguc2r0iSC6iNbTsHGTVJ4Z3obEkjqH0k+g+ByR8vV8nA1yTwMSe33SOt8JL4rwHgj C8dJ6uqKo4IesnYnhDwTs8ht8On4HqjznR8ObE5xL5OCvelFRRUex5cPOjVvz7D4HtkNxOl2tY9E Xru7qpVZKuvhBaytiS3CCBqjIqA2piyDGFnYGBvC5CVWwkpKT1jYTpJ1puNE4J3zzS48M6b5GRdG 2NgKw8AmQEdyS2CSFugOR22o+/1h+JfX+k+MUFUEQVIgMYfb/9oIcNJojGcJrizg22MCF4QsPy7/ +LuSKcKEh5SXgyA= --===============1831463695==--