From: Maitrayi Sabaratnam Date: February 19 2010 2:54pm Subject: bzr push into mysql-5.1-telco-7.0-mai branch (msabaratnam:3235 to 3236) List-Archive: http://lists.mysql.com/commits/100882 Message-Id: <20100219145446.6413.qmail@nanna12> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============2046976603==" --===============2046976603== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline 3236 Maitrayi Sabaratnam 2010-02-19 [merge] Merging with 7.0 added: storage/ndb/cmake/ storage/ndb/cmake/cmake_parse_arguments.cmake storage/ndb/cmake/libutils.cmake modified: .bzrignore mysql-test/suite/ndb/r/ndb_dd_alter.result mysql-test/suite/ndb/r/ndb_dd_restore_compat.result mysql-test/suite/ndb/t/show_attributes.inc storage/ndb/CMakeLists.txt storage/ndb/Makefile.am storage/ndb/config/type_ndbapitools.cmake storage/ndb/include/kernel/GlobalSignalNumbers.h storage/ndb/include/util/Parser.hpp storage/ndb/src/CMakeLists.txt storage/ndb/src/kernel/blocks/CMakeLists.txt storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp storage/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp storage/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp storage/ndb/src/kernel/blocks/suma/Suma.cpp storage/ndb/src/kernel/blocks/suma/Suma.hpp storage/ndb/src/kernel/blocks/suma/SumaInit.cpp storage/ndb/src/kernel/vm/ArrayPool.hpp storage/ndb/src/kernel/vm/ndbd_malloc_impl.cpp storage/ndb/src/mgmsrv/CMakeLists.txt storage/ndb/src/mgmsrv/MgmtSrvr.cpp storage/ndb/src/mgmsrv/MgmtSrvr.hpp storage/ndb/src/mgmsrv/Services.cpp storage/ndb/src/ndbapi/NdbDictionary.cpp storage/ndb/test/include/HugoTransactions.hpp storage/ndb/test/include/NdbRestarter.hpp storage/ndb/test/ndbapi/testMgm.cpp storage/ndb/test/ndbapi/testUpgrade.cpp storage/ndb/test/run-test/command.cpp storage/ndb/test/run-test/db.cpp storage/ndb/test/run-test/upgrade-tests.txt storage/ndb/test/src/CpcClient.cpp storage/ndb/test/src/HugoTransactions.cpp storage/ndb/test/src/NdbRestarter.cpp storage/ndb/tools/CMakeLists.txt storage/ndb/tools/desc.cpp storage/ndb/tools/restore/consumer_restore.cpp 3235 Maitrayi Sabaratnam 2010-02-11 [merge] Merging with 7.0 removed: storage/ndb/src/mgmclient/ndb_mgmclient.h added: mysql-test/suite/ndb/r/ndb_mgm.result mysql-test/suite/ndb/t/ndb_mgm.test storage/ndb/test/run-test/conf-fimafeng09.cnf storage/ndb/test/run-test/conf-loki27.cnf storage/ndb/test/run-test/conf-techra29.cnf storage/ndb/test/run-test/conf-tyr64.cnf modified: Makefile.am configure.in mysql-test/r/openssl_1.result mysql-test/std_data/cacert.pem mysql-test/std_data/client-cert.pem mysql-test/std_data/client-key.pem mysql-test/std_data/server-cert.pem mysql-test/std_data/server-key.pem mysql-test/std_data/server8k-cert.pem mysql-test/std_data/server8k-key.pem mysql-test/suite/ndb/r/ndb_auto_increment.result mysql-test/suite/ndb/r/ndb_blob.result mysql-test/suite/ndb/r/ndb_dd_basic.result mysql-test/suite/ndb/t/ndb_auto_increment.test mysql-test/suite/ndb/t/ndb_blob.test mysql-test/suite/ndb/t/ndb_dd_basic.test mysql-test/suite/ndb/t/test_mgmd.test mysql-test/suite/ndb/t/test_ndbinfo.test mysql-test/suite/ndb_team/r/rpl_ndb_dd_advance.result mysql-test/t/openssl_1.test sql/ha_ndbcluster.cc sql/ha_ndbcluster.h sql/sql_table.cc storage/ndb/docs/doxygen/predoxy.pl storage/ndb/include/kernel/AttributeHeader.hpp storage/ndb/include/kernel/kernel_types.h storage/ndb/include/kernel/signaldata/CreateFilegroup.hpp storage/ndb/include/kernel/signaldata/LqhKey.hpp storage/ndb/include/kernel/signaldata/TcKeyReq.hpp storage/ndb/include/mgmapi/mgmapi_config_parameters.h storage/ndb/include/ndb_version.h.in storage/ndb/include/ndbapi/Ndb.hpp storage/ndb/include/ndbapi/NdbBlob.hpp storage/ndb/include/ndbapi/NdbDictionary.hpp storage/ndb/include/ndbapi/NdbOperation.hpp storage/ndb/include/ndbapi/NdbTransaction.hpp storage/ndb/include/portlib/NdbThread.h storage/ndb/include/transporter/TransporterRegistry.hpp storage/ndb/src/common/debugger/signaldata/TcKeyReq.cpp storage/ndb/src/common/portlib/NdbDir.cpp storage/ndb/src/common/portlib/NdbThread.c storage/ndb/src/cw/cpcd/CPCD.hpp storage/ndb/src/cw/cpcd/Process.cpp storage/ndb/src/kernel/blocks/ERROR_codes.txt storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp storage/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp storage/ndb/src/kernel/blocks/lgman.cpp storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp storage/ndb/src/kernel/blocks/tsman.cpp storage/ndb/src/kernel/vm/Configuration.cpp storage/ndb/src/mgmclient/CommandInterpreter.cpp storage/ndb/src/mgmclient/main.cpp storage/ndb/src/mgmclient/ndb_mgmclient.hpp storage/ndb/src/mgmsrv/ConfigInfo.cpp storage/ndb/src/mgmsrv/ConfigManager.cpp storage/ndb/src/mgmsrv/MgmtSrvr.cpp storage/ndb/src/ndbapi/ClusterMgr.cpp storage/ndb/src/ndbapi/ClusterMgr.hpp storage/ndb/src/ndbapi/Ndb.cpp storage/ndb/src/ndbapi/NdbBlob.cpp storage/ndb/src/ndbapi/NdbDictionary.cpp storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp storage/ndb/src/ndbapi/NdbImpl.hpp storage/ndb/src/ndbapi/NdbOperation.cpp storage/ndb/src/ndbapi/NdbOperationDefine.cpp storage/ndb/src/ndbapi/NdbOperationExec.cpp storage/ndb/src/ndbapi/NdbScanOperation.cpp storage/ndb/src/ndbapi/NdbTransaction.cpp storage/ndb/src/ndbapi/NdbUtil.cpp storage/ndb/src/ndbapi/NdbUtil.hpp storage/ndb/src/ndbapi/Ndbif.cpp storage/ndb/src/ndbapi/Ndbinit.cpp storage/ndb/src/ndbapi/Ndblist.cpp storage/ndb/src/ndbapi/TransporterFacade.cpp storage/ndb/src/ndbapi/TransporterFacade.hpp storage/ndb/src/ndbapi/ndberror.c storage/ndb/test/include/HugoOperations.hpp storage/ndb/test/ndbapi/testBasic.cpp storage/ndb/test/ndbapi/testBlobs.cpp storage/ndb/test/ndbapi/testNdbApi.cpp storage/ndb/test/ndbapi/testNodeRestart.cpp storage/ndb/test/run-test/Makefile.am storage/ndb/test/run-test/atrt.hpp storage/ndb/test/run-test/autotest-boot.sh storage/ndb/test/run-test/autotest-run.sh storage/ndb/test/run-test/conf-fimafeng08.cnf storage/ndb/test/run-test/daily-basic-tests.txt storage/ndb/test/run-test/example.conf storage/ndb/test/run-test/files.cpp storage/ndb/test/src/HugoOperations.cpp storage/ndb/test/src/HugoTransactions.cpp === modified file '.bzrignore' --- a/.bzrignore 2009-12-17 15:43:35 +0000 +++ b/.bzrignore 2010-02-16 08:45:29 +0000 @@ -72,6 +72,7 @@ .snprj/* .vimrc 50 +target =6 BUILD/compile-pentium-maintainer BitKeeper/etc/RESYNC_TREE @@ -2748,6 +2749,7 @@ storage/ndb/src/kernel/blocks/suma/libsu storage/ndb/src/kernel/blocks/trix/libtrix.dsp storage/ndb/src/kernel/error/liberror.dsp storage/ndb/src/kernel/ndbd +storage/ndb/src/kernel/ndbmtd storage/ndb/src/kernel/ndbd.dsp storage/ndb/src/kernel/vm/libkernel.dsp storage/ndb/src/libndb.ver @@ -2763,6 +2765,7 @@ storage/ndb/src/ndbapi/libndbapi.dsp storage/ndb/src/ndbapi/ndberror_check storage/ndb/test/ndbapi/DbAsyncGenerator storage/ndb/test/ndbapi/DbCreate +storage/ndb/test/ndbapi/NdbRepStress storage/ndb/test/ndbapi/bank/bankCreator storage/ndb/test/ndbapi/bank/bankMakeGL storage/ndb/test/ndbapi/bank/bankSumAccounts @@ -2778,7 +2781,11 @@ storage/ndb/test/ndbapi/flexBench storage/ndb/test/ndbapi/flexBench.dsp storage/ndb/test/ndbapi/flexHammer storage/ndb/test/ndbapi/flexTT +storage/ndb/test/ndbapi/msa +storage/ndb/test/ndbapi/ndbapi_50compat0 +storage/ndb/test/ndbapi/ndbapi_50compat1 storage/ndb/test/ndbapi/ndbapi_slow_select +storage/ndb/test/ndbapi/reorg_tab storage/ndb/test/ndbapi/testBackup storage/ndb/test/ndbapi/testBasic storage/ndb/test/ndbapi/testBasic.dsp @@ -2793,28 +2800,37 @@ storage/ndb/test/ndbapi/testIndex storage/ndb/test/ndbapi/testIndexStat storage/ndb/test/ndbapi/testInterpreter storage/ndb/test/ndbapi/testLcp +storage/ndb/test/ndbapi/testLimits storage/ndb/test/ndbapi/testMgm +storage/ndb/test/ndbapi/testMgmd +storage/ndb/test/ndbapi/testNDBT storage/ndb/test/ndbapi/testNdbApi +storage/ndb/test/ndbapi/testNdbinfo storage/ndb/test/ndbapi/testNodeRestart storage/ndb/test/ndbapi/testOIBasic storage/ndb/test/ndbapi/testOperations storage/ndb/test/ndbapi/testPartitioning storage/ndb/test/ndbapi/testReadPerf +storage/ndb/test/ndbapi/testReconnect storage/ndb/test/ndbapi/testRestartGci storage/ndb/test/ndbapi/testSRBank storage/ndb/test/ndbapi/testScan +storage/ndb/test/ndbapi/testScanFilter storage/ndb/test/ndbapi/testScan.dsp storage/ndb/test/ndbapi/testScanInterpreter storage/ndb/test/ndbapi/testScanPerf +storage/ndb/test/ndbapi/testSingleUserMode storage/ndb/test/ndbapi/testSystemRestart storage/ndb/test/ndbapi/testTimeout storage/ndb/test/ndbapi/testTransactions +storage/ndb/test/ndbapi/testUpgrade storage/ndb/test/ndbapi/test_event storage/ndb/test/ndbapi/test_event_merge storage/ndb/test/run-test/atrt storage/ndb/test/src/libNDBT.dsp storage/ndb/test/tools/copy_tab storage/ndb/test/tools/create_index +storage/ndb/test/tools/eventlog storage/ndb/test/tools/hugoCalculator storage/ndb/test/tools/hugoFill storage/ndb/test/tools/hugoLoad @@ -2826,6 +2842,7 @@ storage/ndb/test/tools/hugoPkUpdate storage/ndb/test/tools/hugoScanRead storage/ndb/test/tools/hugoScanUpdate storage/ndb/test/tools/listen_event +storage/ndb/test/tools/ndb_connect storage/ndb/test/tools/ndb_cpcc storage/ndb/test/tools/rep_latency storage/ndb/test/tools/restart @@ -2849,6 +2866,8 @@ storage/ndb/tools/ndb_show_tables.dsp storage/ndb/tools/ndb_test_platform storage/ndb/tools/ndb_waiter storage/ndb/tools/ndb_waiter.dsp +storage/ndb/tools/ndbinfo.sql +storage/ndb/tools/ndbinfo_sql strings/*.ds? strings/*.vcproj strings/.deps/bchange.Po === modified file 'mysql-test/suite/ndb/r/ndb_dd_alter.result' --- a/mysql-test/suite/ndb/r/ndb_dd_alter.result 2009-10-23 16:30:54 +0000 +++ b/mysql-test/suite/ndb/r/ndb_dd_alter.result 2010-02-18 12:51:52 +0000 @@ -87,7 +87,7 @@ a6 Time NULL AT=FIXED ST=DISK a7 Date NULL AT=FIXED ST=DISK a8 Datetime NULL AT=FIXED ST=DISK a9 Varchar(255;latin1_swedish_ci) NULL AT=SHORT_VAR ST=DISK -a10 Blob(256,2000,0) NULL AT=MEDIUM_VAR ST=DISK BV=2 +a10 Blob(256,2000,0) NULL AT=MEDIUM_VAR ST=DISK BV=2 BT=NDB$BLOB_#_# SELECT * FROM test.t1 ORDER BY a1; a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 1 2 2000000001 aaa1 34.2 04:03:02 2006-01-01 1971-05-28 16:55:03 bbbbbbbbbbbbb1 binary data @@ -187,7 +187,7 @@ a6 Time NULL AT=FIXED ST=DISK a7 Date NULL AT=FIXED ST=DISK a8 Datetime NULL AT=FIXED ST=DISK a9 Varchar(255;latin1_swedish_ci) NULL AT=SHORT_VAR ST=DISK -a10 Blob(256,2000,0) NULL AT=MEDIUM_VAR ST=DISK BV=2 +a10 Blob(256,2000,0) NULL AT=MEDIUM_VAR ST=DISK BV=2 BT=NDB$BLOB_#_# SELECT * FROM test.t1 ORDER BY a1; a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 1 2 2000000001 aaa1 34.2 04:03:02 2006-01-01 1971-05-28 16:55:03 bbbbbbbbbbbbb1 binary data @@ -274,7 +274,7 @@ a6 Time NULL AT=FIXED ST=DISK a7 Date NULL AT=FIXED ST=DISK a8 Datetime NULL AT=FIXED ST=DISK a9 Varchar(255;latin1_swedish_ci) NULL AT=SHORT_VAR ST=DISK -a10 Blob(256,2000,0) NULL AT=MEDIUM_VAR ST=DISK BV=2 +a10 Blob(256,2000,0) NULL AT=MEDIUM_VAR ST=DISK BV=2 BT=NDB$BLOB_#_# ALTER TABLE test.t1 ENGINE=MyISAM; SHOW CREATE TABLE test.t1; Table Create Table @@ -397,11 +397,11 @@ a6 Bigint NULL AT=FIXED ST=DISK a7 Date NULL AT=FIXED ST=DISK a8 Time NULL AT=FIXED ST=DISK a9 Datetime NULL AT=FIXED ST=DISK -a10 Text(256,0,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=MEMORY BV=2 -a11 Text(256,4000,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=DISK BV=2 -a12 Text(256,8000,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=DISK BV=2 -a13 Text(256,2000,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=DISK BV=2 -a14 Blob(256,2000,0) NULL AT=MEDIUM_VAR ST=DISK BV=2 +a10 Text(256,0,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=MEMORY BV=2 BT= +a11 Text(256,4000,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=DISK BV=2 BT=NDB$BLOB_#_# +a12 Text(256,8000,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=DISK BV=2 BT=NDB$BLOB_#_# +a13 Text(256,2000,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=DISK BV=2 BT=NDB$BLOB_#_# +a14 Blob(256,2000,0) NULL AT=MEDIUM_VAR ST=DISK BV=2 BT=NDB$BLOB_#_# SELECT a1, a2,a3,hex(a4),a5,a6,a7,a8,a9,a10,a11,a12,a13 FROM test.t1 ORDER BY a1; a1 a2 a3 hex(a4) a5 a6 a7 a8 a9 a10 a11 a12 a13 1 2.2345 20000001 0 1 23457 2006-01-01 07:04:00 1971-05-28 16:55:03 abc abcdefg LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL Text Field @@ -468,11 +468,11 @@ a6 Bigint NULL AT=FIXED ST=DISK a7 Date NULL AT=FIXED ST=DISK a8 Time NULL AT=FIXED ST=DISK a9 Datetime NULL AT=FIXED ST=DISK -a10 Text(256,0,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=MEMORY BV=2 -a11 Text(256,4000,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=DISK BV=2 -a12 Text(256,8000,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=DISK BV=2 -a13 Text(256,2000,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=DISK BV=2 -a14 Blob(256,2000,0) NULL AT=MEDIUM_VAR ST=DISK BV=2 +a10 Text(256,0,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=MEMORY BV=2 BT= +a11 Text(256,4000,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=DISK BV=2 BT=NDB$BLOB_#_# +a12 Text(256,8000,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=DISK BV=2 BT=NDB$BLOB_#_# +a13 Text(256,2000,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=DISK BV=2 BT=NDB$BLOB_#_# +a14 Blob(256,2000,0) NULL AT=MEDIUM_VAR ST=DISK BV=2 BT=NDB$BLOB_#_# ALTER TABLE test.t1 DROP INDEX a2_i; SHOW CREATE TABLE test.t1; Table Create Table @@ -504,11 +504,11 @@ a6 Bigint NULL AT=FIXED ST=DISK a7 Date NULL AT=FIXED ST=DISK a8 Time NULL AT=FIXED ST=DISK a9 Datetime NULL AT=FIXED ST=DISK -a10 Text(256,0,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=MEMORY BV=2 -a11 Text(256,4000,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=DISK BV=2 -a12 Text(256,8000,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=DISK BV=2 -a13 Text(256,2000,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=DISK BV=2 -a14 Blob(256,2000,0) NULL AT=MEDIUM_VAR ST=DISK BV=2 +a10 Text(256,0,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=MEMORY BV=2 BT= +a11 Text(256,4000,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=DISK BV=2 BT=NDB$BLOB_#_# +a12 Text(256,8000,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=DISK BV=2 BT=NDB$BLOB_#_# +a13 Text(256,2000,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=DISK BV=2 BT=NDB$BLOB_#_# +a14 Blob(256,2000,0) NULL AT=MEDIUM_VAR ST=DISK BV=2 BT=NDB$BLOB_#_# TRUNCATE TABLE test.t1; SHOW CREATE TABLE test.t1; Table Create Table @@ -540,11 +540,11 @@ a6 Bigint NULL AT=FIXED ST=DISK a7 Date NULL AT=FIXED ST=DISK a8 Time NULL AT=FIXED ST=DISK a9 Datetime NULL AT=FIXED ST=DISK -a10 Text(256,0,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=MEMORY BV=2 -a11 Text(256,4000,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=DISK BV=2 -a12 Text(256,8000,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=DISK BV=2 -a13 Text(256,2000,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=DISK BV=2 -a14 Blob(256,2000,0) NULL AT=MEDIUM_VAR ST=DISK BV=2 +a10 Text(256,0,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=MEMORY BV=2 BT= +a11 Text(256,4000,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=DISK BV=2 BT=NDB$BLOB_#_# +a12 Text(256,8000,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=DISK BV=2 BT=NDB$BLOB_#_# +a13 Text(256,2000,0;latin1_swedish_ci) NULL AT=MEDIUM_VAR ST=DISK BV=2 BT=NDB$BLOB_#_# +a14 Blob(256,2000,0) NULL AT=MEDIUM_VAR ST=DISK BV=2 BT=NDB$BLOB_#_# ALTER TABLE test.t1 DROP a14; ALTER TABLE test.t1 DROP a13; ALTER TABLE test.t1 DROP a12; === modified file 'mysql-test/suite/ndb/r/ndb_dd_restore_compat.result' --- a/mysql-test/suite/ndb/r/ndb_dd_restore_compat.result 2009-07-13 13:22:46 +0000 +++ b/mysql-test/suite/ndb/r/ndb_dd_restore_compat.result 2010-02-18 12:51:52 +0000 @@ -36,7 +36,7 @@ a6 Time NULL AT=FIXED ST=DISK a7 Date NULL AT=FIXED ST=DISK a8 Datetime NULL AT=FIXED ST=DISK a9 Varchar(255;latin1_swedish_ci) NULL AT=FIXED ST=DISK -a10 Blob(256,2000,16) NULL AT=FIXED ST=DISK BV=1 +a10 Blob(256,2000,16) NULL AT=FIXED ST=DISK BV=1 BT=NDB$BLOB_#_# select * from t1 order by a1; a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 1 2 2000000001 aaa1 34.2 04:03:02 2006-01-01 1971-05-28 16:55:03 bbbbbbbbbbbbb1 binary data === modified file 'mysql-test/suite/ndb/t/show_attributes.inc' --- a/mysql-test/suite/ndb/t/show_attributes.inc 2009-07-15 20:47:18 +0000 +++ b/mysql-test/suite/ndb/t/show_attributes.inc 2010-02-18 12:51:52 +0000 @@ -14,6 +14,7 @@ eval LOAD DATA INFILE '$dump_file' INTO --remove_file $dump_file # Query the temporary table +--replace_regex /BT=NDB\$BLOB_[0-9]+_[0-9]+/BT=NDB$BLOB_#_#/ SELECT TRIM(TRAILING "\r" FROM a) as 'Attributes:' FROM test.desc WHERE a LIKE BINARY "%ST=%"; === modified file 'storage/ndb/CMakeLists.txt' --- a/storage/ndb/CMakeLists.txt 2009-12-16 10:02:54 +0000 +++ b/storage/ndb/CMakeLists.txt 2010-02-19 03:00:21 +0000 @@ -13,6 +13,8 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +INCLUDE("${CMAKE_SOURCE_DIR}/storage/ndb/cmake/libutils.cmake") + SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DVM_TRACE -DNDB_DEBUG -DERROR_INSERT -DARRAY_GUARD") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DVM_TRACE -DNDB_DEBUG -DERROR_INSERT -DARRAY_GUARD") === modified file 'storage/ndb/Makefile.am' --- a/storage/ndb/Makefile.am 2009-05-27 15:21:45 +0000 +++ b/storage/ndb/Makefile.am 2010-02-19 06:00:01 +0000 @@ -16,7 +16,7 @@ SUBDIRS = src tools . include swig @ndb_opt_subdirs@ DIST_SUBDIRS = src tools include test docs swig -EXTRA_DIST = config ndbapi-examples plug.in CMakeLists.txt +EXTRA_DIST = config cmake ndbapi-examples plug.in CMakeLists.txt DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in include $(top_srcdir)/storage/ndb/config/common.mk.am === added directory 'storage/ndb/cmake' === added file 'storage/ndb/cmake/cmake_parse_arguments.cmake' --- a/storage/ndb/cmake/cmake_parse_arguments.cmake 1970-01-01 00:00:00 +0000 +++ b/storage/ndb/cmake/cmake_parse_arguments.cmake 2010-02-18 10:45:20 +0000 @@ -0,0 +1,47 @@ + +# Copyright (C) 2007 MySQL AB, 2009 Sun Microsystems,Inc +# +# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +# Handy macro to parse macro arguments +MACRO(CMAKE_PARSE_ARGUMENTS prefix arg_names option_names) + SET(DEFAULT_ARGS) + FOREACH(arg_name ${arg_names}) + SET(${prefix}_${arg_name}) + ENDFOREACH(arg_name) + FOREACH(option ${option_names}) + SET(${prefix}_${option} FALSE) + ENDFOREACH(option) + + SET(current_arg_name DEFAULT_ARGS) + SET(current_arg_list) + FOREACH(arg ${ARGN}) + SET(larg_names ${arg_names}) + LIST(FIND larg_names "${arg}" is_arg_name) + IF (is_arg_name GREATER -1) + SET(${prefix}_${current_arg_name} ${current_arg_list}) + SET(current_arg_name ${arg}) + SET(current_arg_list) + ELSE (is_arg_name GREATER -1) + SET(loption_names ${option_names}) + LIST(FIND loption_names "${arg}" is_option) + IF (is_option GREATER -1) + SET(${prefix}_${arg} TRUE) + ELSE (is_option GREATER -1) + SET(current_arg_list ${current_arg_list} ${arg}) + ENDIF (is_option GREATER -1) + ENDIF (is_arg_name GREATER -1) + ENDFOREACH(arg) + SET(${prefix}_${current_arg_name} ${current_arg_list}) +ENDMACRO() \ No newline at end of file === added file 'storage/ndb/cmake/libutils.cmake' --- a/storage/ndb/cmake/libutils.cmake 1970-01-01 00:00:00 +0000 +++ b/storage/ndb/cmake/libutils.cmake 2010-02-18 10:45:20 +0000 @@ -0,0 +1,296 @@ +# Copyright (C) 2009 Sun Microsystems, Inc +# +# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +# This file exports macros that emulate some functionality found in GNU libtool +# on Unix systems. One such feature is convenience libraries. In this context, +# convenience library is a static library that can be linked to shared library +# On systems that force position-independent code, linking into shared library +# normally requires compilation with a special flag (often -fPIC). To enable +# linking static libraries to shared, we compile source files that come into +# static library with the PIC flag (${CMAKE_SHARED_LIBRARY_C_FLAGS} in CMake) +# Some systems, like Windows or OSX do not need special compilation (Windows +# never uses PIC and OSX always uses it). +# +# The intention behind convenience libraries is simplify the build and to reduce +# excessive recompiles. + +# Except for convenience libraries, this file provides macros to merge static +# libraries (we need it for mysqlclient) and to create shared library out of +# convenience libraries(again, for mysqlclient) + +# Following macros are exported +# - ADD_CONVENIENCE_LIBRARY(target source1...sourceN) +# This macro creates convenience library. The functionality is similar to +# ADD_LIBRARY(target STATIC source1...sourceN), the difference is that resulting +# library can always be linked to shared library +# +# - MERGE_LIBRARIES(target [STATIC|SHARED|MODULE] [linklib1 .... linklibN] +# [EXPORTS exported_func1 .... exported_func_N] +# [OUTPUT_NAME output_name] +# This macro merges several static libraries into a single one or creates a shared +# library from several convenience libraries + +# Important global flags +# - WITH_PIC : If set, it is assumed that everything is compiled as position +# independent code (that is CFLAGS/CMAKE_C_FLAGS contain -fPIC or equivalent) +# If defined, ADD_CONVENIENCE_LIBRARY does not add PIC flag to compile flags +# +# - DISABLE_SHARED: If set, it is assumed that shared libraries are not produced +# during the build. ADD_CONVENIENCE_LIBRARY does not add anything to compile flags + + +GET_FILENAME_COMPONENT(MYSQL_CMAKE_SCRIPT_DIR ${CMAKE_CURRENT_LIST_FILE} PATH) +IF(WIN32 OR CYGWIN OR APPLE OR WITH_PIC OR DISABLE_SHARED OR NOT CMAKE_SHARED_LIBRARY_C_FLAGS) + SET(_SKIP_PIC 1) +ENDIF() + +INCLUDE(${MYSQL_CMAKE_SCRIPT_DIR}/cmake_parse_arguments.cmake) +# CREATE_EXPORT_FILE (VAR target api_functions) +# Internal macro, used to create source file for shared libraries that +# otherwise consists entirely of "convenience" libraries. On Windows, +# also exports API functions as dllexport. On unix, creates a dummy file +# that references all exports and this prevents linker from creating an +# empty library(there are unportable alternatives, --whole-archive) +MACRO(CREATE_EXPORT_FILE VAR TARGET API_FUNCTIONS) + IF(WIN32) + SET(DUMMY ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_dummy.c) + SET(EXPORTS ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_exports.def) + CONFIGURE_FILE_CONTENT("" ${DUMMY}) + SET(CONTENT "EXPORTS\n") + FOREACH(FUNC ${API_FUNCTIONS}) + SET(CONTENT "${CONTENT} ${FUNC}\n") + ENDFOREACH() + CONFIGURE_FILE_CONTENT(${CONTENT} ${EXPORTS}) + SET(${VAR} ${DUMMY} ${EXPORTS}) + ELSE() + SET(EXPORTS ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_exports_file.cc) + SET(CONTENT) + FOREACH(FUNC ${API_FUNCTIONS}) + SET(CONTENT "${CONTENT} extern void* ${FUNC}\;\n") + ENDFOREACH() + SET(CONTENT "${CONTENT} void *${TARGET}_api_funcs[] = {\n") + FOREACH(FUNC ${API_FUNCTIONS}) + SET(CONTENT "${CONTENT} &${FUNC},\n") + ENDFOREACH() + SET(CONTENT "${CONTENT} (void *)0\n}\;") + CONFIGURE_FILE_CONTENT(${CONTENT} ${EXPORTS}) + SET(${VAR} ${EXPORTS}) + ENDIF() +ENDMACRO() + + +# MYSQL_ADD_CONVENIENCE_LIBRARY(name source1...sourceN) +# Create static library that can be linked to shared library. +# On systems that force position-independent code, adds -fPIC or +# equivalent flag to compile flags. +MACRO(ADD_CONVENIENCE_LIBRARY) + SET(TARGET ${ARGV0}) + SET(SOURCES ${ARGN}) + LIST(REMOVE_AT SOURCES 0) + ADD_LIBRARY(${TARGET} STATIC ${SOURCES}) + IF(NOT _SKIP_PIC) + SET_TARGET_PROPERTIES(${TARGET} PROPERTIES COMPILE_FLAGS + "${CMAKE_SHARED_LIBRARY_C_FLAGS}") + ENDIF() +ENDMACRO() + + +# Write content to file, using CONFIGURE_FILE +# The advantage compared to FILE(WRITE) is that timestamp +# does not change if file already has the same content +MACRO(CONFIGURE_FILE_CONTENT content file) + SET(CMAKE_CONFIGURABLE_FILE_CONTENT + "${content}\n") + CONFIGURE_FILE( + ${MYSQL_CMAKE_SCRIPT_DIR}/configurable_file_content.in + ${file} + @ONLY) +ENDMACRO() + +# Merge static libraries into a big static lib. The resulting library +# should not not have dependencies on other static libraries. +# We use it in MySQL to merge mysys,dbug,vio etc into mysqlclient + +MACRO(MERGE_STATIC_LIBS TARGET OUTPUT_NAME LIBS_TO_MERGE) + # To produce a library we need at least one source file. + # It is created by ADD_CUSTOM_COMMAND below and will helps + # also help to track dependencies. + SET(SOURCE_FILE ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_depends.c) + ADD_LIBRARY(${TARGET} STATIC ${SOURCE_FILE}) + SET_TARGET_PROPERTIES(${TARGET} PROPERTIES OUTPUT_NAME ${OUTPUT_NAME}) + + SET(OSLIBS) + FOREACH(LIB ${LIBS_TO_MERGE}) + GET_TARGET_PROPERTY(LIB_LOCATION ${LIB} LOCATION) + GET_TARGET_PROPERTY(LIB_TYPE ${LIB} TYPE) + IF(NOT LIB_LOCATION) + # 3rd party library like libz.so. Make sure that everything + # that links to our library links to this one as well. + LIST(APPEND OSLIBS ${LIB}) + ELSE() + # This is a target in current project + # (can be a static or shared lib) + IF(LIB_TYPE STREQUAL "STATIC_LIBRARY") + SET(STATIC_LIBS ${STATIC_LIBS} ${LIB_LOCATION}) + ADD_DEPENDENCIES(${TARGET} ${LIB}) + # Extract dependend OS libraries + GET_DEPENDEND_OS_LIBS(${LIB} LIB_OSLIBS) + LIST(APPEND OSLIBS ${LIB_OSLIBS}) + ELSE() + # This is a shared library our static lib depends on. + LIST(APPEND OSLIBS ${LIB}) + ENDIF() + ENDIF() + ENDFOREACH() + IF(OSLIBS) + LIST(REMOVE_DUPLICATES OSLIBS) + TARGET_LINK_LIBRARIES(${TARGET} ${OSLIBS}) + ENDIF() + + # Make the generated dummy source file depended on all static input + # libs. If input lib changes,the source file is touched + # which causes the desired effect (relink). + ADD_CUSTOM_COMMAND( + OUTPUT ${SOURCE_FILE} + COMMAND ${CMAKE_COMMAND} -E touch ${SOURCE_FILE} + DEPENDS ${STATIC_LIBS}) + + IF(MSVC) + # To merge libs, just pass them to lib.exe command line. + SET(LINKER_EXTRA_FLAGS "") + FOREACH(LIB ${STATIC_LIBS}) + SET(LINKER_EXTRA_FLAGS "${LINKER_EXTRA_FLAGS} ${LIB}") + ENDFOREACH() + SET_TARGET_PROPERTIES(${TARGET} PROPERTIES STATIC_LIBRARY_FLAGS + "${LINKER_EXTRA_FLAGS}") + ELSE() + GET_TARGET_PROPERTY(TARGET_LOCATION ${TARGET} LOCATION) + IF(APPLE) + # Use OSX's libtool to merge archives (ihandles universal + # binaries properly) + ADD_CUSTOM_COMMAND(TARGET ${TARGET} POST_BUILD + COMMAND rm ${TARGET_LOCATION} + COMMAND /usr/bin/libtool -static -o ${TARGET_LOCATION} + ${STATIC_LIBS} + ) + ELSE() + # Generic Unix, Cygwin or MinGW. In post-build step, call + # script, that extracts objects from archives with "ar x" + # and repacks them with "ar r" + SET(TARGET ${TARGET}) + CONFIGURE_FILE( + ${MYSQL_CMAKE_SCRIPT_DIR}/merge_archives_unix.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/merge_archives_${TARGET}.cmake + @ONLY + ) + ADD_CUSTOM_COMMAND(TARGET ${TARGET} POST_BUILD + COMMAND rm ${TARGET_LOCATION} + COMMAND ${CMAKE_COMMAND} -P + ${CMAKE_CURRENT_BINARY_DIR}/merge_archives_${TARGET}.cmake + ) + ENDIF() + ENDIF() +ENDMACRO() + +# Create libs from libs. +# Merges static libraries, creates shared libraries out of convenience libraries. +# MERGE_LIBRARIES(target [STATIC|SHARED|MODULE] +# [linklib1 .... linklibN] +# [EXPORTS exported_func1 .... exportedFuncN] +# [OUTPUT_NAME output_name] +#) +MACRO(MERGE_LIBRARIES) + CMAKE_PARSE_ARGUMENTS(ARG + "EXPORTS;OUTPUT_NAME" + "STATIC;SHARED;MODULE;NOINSTALL" + ${ARGN} + ) + LIST(GET ARG_DEFAULT_ARGS 0 TARGET) + SET(LIBS ${ARG_DEFAULT_ARGS}) + LIST(REMOVE_AT LIBS 0) + IF(ARG_STATIC) + IF (NOT ARG_OUTPUT_NAME) + SET(ARG_OUTPUT_NAME ${TARGET}) + ENDIF() + MERGE_STATIC_LIBS(${TARGET} ${ARG_OUTPUT_NAME} "${LIBS}") + ELSEIF(ARG_SHARED OR ARG_MODULE) + IF(ARG_SHARED) + SET(LIBTYPE SHARED) + ELSE() + SET(LIBTYPE MODULE) + ENDIF() + # check for non-PIC libraries + IF(NOT _SKIP_PIC) + FOREACH(LIB ${LIBS}) + GET_TARGET_PROPERTY(${LIB} TYPE LIBTYPE) + IF(LIBTYPE STREQUAL "STATIC_LIBRARY") + GET_TARGET_PROPERTY(LIB COMPILE_FLAGS LIB_COMPILE_FLAGS) + STRING(REPLACE "${CMAKE_SHARED_LIBRARY_C_FLAGS}" + "" LIB_COMPILE_FLAGS ${LIB_COMPILE_FLAG}) + IF(NOT LIB_COMPILE_FLAGS MATCHES "") + MESSAGE(FATAL_ERROR + "Attempted to link non-PIC static library ${LIB} to shared library ${TARGET}\n" + "Please use ADD_CONVENIENCE_LIBRARY, instead of ADD_LIBRARY for ${LIB}" + ) + ENDIF() + ENDIF() + ENDFOREACH() + ENDIF() + CREATE_EXPORT_FILE(SRC ${TARGET} "${ARG_EXPORTS}") + ADD_LIBRARY(${TARGET} ${LIBTYPE} ${SRC}) + TARGET_LINK_LIBRARIES(${TARGET} ${LIBS}) + IF(ARG_OUTPUT_NAME) + SET_TARGET_PROPERTIES(${TARGET} PROPERTIES OUTPUT_NAME "${ARG_OUTPUT_NAME}") + ENDIF() + ELSE() + MESSAGE(FATAL_ERROR "Unknown library type") + ENDIF() + IF(NOT ARG_NOINSTALL) + MYSQL_INSTALL_TARGETS(${TARGET} DESTINATION "${INSTALL_LIBDIR}") + ENDIF() + SET_TARGET_PROPERTIES(${TARGET} PROPERTIES LINK_INTERFACE_LIBRARIES "") +ENDMACRO() + +FUNCTION(GET_DEPENDEND_OS_LIBS target result) + SET(deps ${${target}_LIB_DEPENDS}) + IF(deps) + FOREACH(lib ${deps}) + # Filter out keywords for used for debug vs optimized builds + IF(NOT lib MATCHES "general" AND NOT lib MATCHES "debug" AND NOT lib MATCHES "optimized") + GET_TARGET_PROPERTY(lib_location ${lib} LOCATION) + IF(NOT lib_location) + SET(ret ${ret} ${lib}) + ENDIF() + ENDIF() + ENDFOREACH() + ENDIF() + SET(${result} ${ret} PARENT_SCOPE) +ENDFUNCTION() + +MACRO(RESTRICT_SYMBOL_EXPORTS target) + IF(CMAKE_COMPILER_IS_GNUCXX AND UNIX) + CHECK_C_COMPILER_FLAG("-fvisibility=hidden" HAVE_VISIBILITY_HIDDEN) + IF(HAVE_VISIBILITY_HIDDEN) + GET_TARGET_PROPERTY(COMPILE_FLAGS ${target} COMPILE_FLAGS) + IF(NOT COMPILE_FLAGS) + # Avoid COMPILE_FLAGS-NOTFOUND + SET(COMPILE_FLAGS) + ENDIF() + SET_TARGET_PROPERTIES(${target} PROPERTIES + COMPILE_FLAGS "${COMPILE_FLAGS} -fvisibility=hidden") + ENDIF() + ENDIF() +ENDMACRO() === modified file 'storage/ndb/config/type_ndbapitools.cmake' --- a/storage/ndb/config/type_ndbapitools.cmake 2008-08-20 13:22:09 +0000 +++ b/storage/ndb/config/type_ndbapitools.cmake 2010-02-18 10:45:20 +0000 @@ -17,7 +17,7 @@ LINK_LIBRARIES(ndbclient dbug mysys strings - ${NDB_SCI_LIBS}) + ) IF(WIN32) LINK_LIBRARIES(wsock32) ENDIF(WIN32) === modified file 'storage/ndb/include/kernel/GlobalSignalNumbers.h' --- a/storage/ndb/include/kernel/GlobalSignalNumbers.h 2009-10-15 12:36:53 +0000 +++ b/storage/ndb/include/kernel/GlobalSignalNumbers.h 2010-02-18 06:30:45 +0000 @@ -191,7 +191,7 @@ extern const GlobalSignalNumber NO_OF_SI /* 120 not unused */ #define GSN_ROUTE_ORD 121 #define GSN_NODE_VERSION_REP 122 -/* 123 unused */ +/* 123 not unused */ /* 124 unused */ #define GSN_CHECK_LCP_STOP 125 #define GSN_CLOSE_COMCONF 126 /* local */ @@ -673,6 +673,7 @@ extern const GlobalSignalNumber NO_OF_SI #define GSN_TCINDXNEXTCONF 525 #define GSN_TCINDXNEXREF 526 #define GSN_FIRE_TRIG_ORD 527 +#define GSN_FIRE_TRIG_ORD_L 123 /* local from TUP to SUMA */ /** * These are used only by kernel === modified file 'storage/ndb/include/util/Parser.hpp' --- a/storage/ndb/include/util/Parser.hpp 2009-05-26 18:53:34 +0000 +++ b/storage/ndb/include/util/Parser.hpp 2010-02-18 23:01:15 +0000 @@ -70,7 +70,8 @@ public: const ParserRow * m_currentCmd; const ParserRow * m_currentArg; char * m_currentToken; - char m_tokenBuffer[512]; + STATIC_CONST(MaxParseBytes = 512); + char m_tokenBuffer[ MaxParseBytes ]; NdbMutex *m_mutex; Vector *> m_aliasUsed; === modified file 'storage/ndb/src/CMakeLists.txt' --- a/storage/ndb/src/CMakeLists.txt 2009-10-19 11:15:38 +0000 +++ b/storage/ndb/src/CMakeLists.txt 2010-02-18 10:45:20 +0000 @@ -24,17 +24,17 @@ ADD_SUBDIRECTORY(mgmsrv) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/storage/ndb/include {CMAKE_SOURCE_DIR}/include) -IF(NOT EXISTS cmake_dummy.cpp) - FILE(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/cmake_dummy.cpp "") -ENDIF() -ADD_LIBRARY(ndbclient STATIC cmake_dummy.cpp) -TARGET_LINK_LIBRARIES(ndbclient - ndbapi - ndbtransport - ndbtrace - ndbsignaldata - ndbmgmapi - ndbmgmsrv - ndblogger - ndbportlib - ndbgeneral) +MERGE_LIBRARIES(ndbclient STATIC NOINSTALL + mysys dbug strings + ndbapi + ndbtransport + ndbtrace + ndbsignaldata + ndbmgmapi + ndbmgmsrv + ndblogger + ndbportlib + ndbgeneral + ndbconf +) +TARGET_LINK_LIBRARIES(ndbclient ws2_32) === modified file 'storage/ndb/src/kernel/blocks/CMakeLists.txt' --- a/storage/ndb/src/kernel/blocks/CMakeLists.txt 2010-01-04 00:59:59 +0000 +++ b/storage/ndb/src/kernel/blocks/CMakeLists.txt 2010-02-18 10:45:20 +0000 @@ -72,4 +72,4 @@ ADD_EXECUTABLE(ndb_print_file diskpage.cpp dbtup/tuppage.cpp ) -TARGET_LINK_LIBRARIES(ndb_print_file ndbclient dbug mysys strings) +TARGET_LINK_LIBRARIES(ndb_print_file ndbclient) === modified file 'storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp' --- a/storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp 2010-01-25 16:22:52 +0000 +++ b/storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp 2010-02-15 12:43:01 +0000 @@ -971,6 +971,7 @@ private: Page8Ptr spPageptr; Uint32 cfirstfreepage; Uint32 cpagesize; + Uint32 cpageCount; Uint32 cnoOfAllocatedPages; Uint32 cnoOfAllocatedPagesMax; /* --------------------------------------------------------------------------------- */ === modified file 'storage/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp' --- a/storage/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp 2010-01-25 16:22:52 +0000 +++ b/storage/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp 2010-02-15 12:43:01 +0000 @@ -44,7 +44,7 @@ void Dbacc::initData() scanRec = 0; tabrec = 0; - cnoOfAllocatedPagesMax = cnoOfAllocatedPages = cpagesize = 0; + cnoOfAllocatedPagesMax = cnoOfAllocatedPages = cpagesize = cpageCount = 0; // Records with constant sizes RSS_OP_COUNTER_INIT(cnoOfFreeFragrec); @@ -71,6 +71,8 @@ void Dbacc::initRecords() * 2) Add chunks to cfirstfreepage-list */ cfirstfreepage = RNIL; + cpagesize = 0; + cpageCount = 0; for (Int32 i = chunkcnt - 1; i >= 0; i--) { Ptr pagePtr; @@ -85,16 +87,12 @@ void Dbacc::initRecords() base[j].word32[0] = ptrI + j + 1; } - if (cfirstfreepage == RNIL) - { - base[cnt-1].word32[0] = RNIL; - cfirstfreepage = ptrI; - } - else - { - base[cnt-1].word32[0] = cfirstfreepage; - cfirstfreepage = ptrI; - } + base[cnt-1].word32[0] = cfirstfreepage; + cfirstfreepage = ptrI; + + cpageCount += cnt; + if (ptrI + cnt > cpagesize) + cpagesize = ptrI + cnt; } } === modified file 'storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp' --- a/storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp 2010-01-25 16:22:52 +0000 +++ b/storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp 2010-02-15 12:43:01 +0000 @@ -112,7 +112,7 @@ void Dbacc::execCONTINUEB(Signal* signal jam(); Uint32 cnt = signal->theData[1]; static int c_currentMemUsed = 0; - int now = cpagesize ? (cnoOfAllocatedPages * 100)/cpagesize : 0; + int now = cpageCount ? (cnoOfAllocatedPages * 100)/cpageCount : 0; const int thresholds[] = { 99, 90, 80, 0}; Uint32 i = 0; @@ -8255,7 +8255,7 @@ Dbacc::reportMemoryUsage(Signal* signal, signal->theData[1] = gth; signal->theData[2] = sizeof(* rpPageptr.p); signal->theData[3] = cnoOfAllocatedPages; - signal->theData[4] = cpagesize; + signal->theData[4] = cpageCount; signal->theData[5] = DBACC; sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 6, JBB); } @@ -8278,7 +8278,7 @@ void Dbacc::execDBINFO_SCANREQ(Signal *s { { "Index memory", cnoOfAllocatedPages, - cpagesize, + cpageCount, sizeof(page8), cnoOfAllocatedPagesMax = 0, { CFG_DB_INDEX_MEM,0,0,0 }}, === modified file 'storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp' --- a/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp 2010-01-28 15:16:46 +0000 +++ b/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp 2010-02-15 13:30:39 +0000 @@ -2751,6 +2751,7 @@ private: LogPageRecordPtr logPagePtr; UintR cfirstfreeLogPage; UintR clogPageFileSize; + Uint32 clogPageCount; #define ZPAGE_REF_FILE_SIZE 20 PageRefRecord *pageRefRecord; === modified file 'storage/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp' --- a/storage/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp 2010-01-28 15:16:46 +0000 +++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp 2010-02-15 13:30:39 +0000 @@ -137,6 +137,8 @@ void Dblqh::initRecords() } cfirstfreeLogPage = RNIL; + clogPageFileSize = 0; + clogPageCount = 0; for (Int32 i = chunkcnt - 1; i >= 0; i--) { const Uint32 cnt = chunks[i].cnt; @@ -156,18 +158,14 @@ void Dblqh::initRecords() base[j].logPageWord[ZPOS_IN_WRITING]= 0; } - if (cfirstfreeLogPage == RNIL) - { - base[cnt-1].logPageWord[ZNEXT_PAGE] = RNIL; - cfirstfreeLogPage = ptrI; - } - else - { - base[cnt-1].logPageWord[ZNEXT_PAGE] = cfirstfreeLogPage; - cfirstfreeLogPage = ptrI; - } + base[cnt-1].logPageWord[ZNEXT_PAGE] = cfirstfreeLogPage; + cfirstfreeLogPage = ptrI; + + clogPageCount += cnt; + if (ptrI + cnt > clogPageFileSize) + clogPageFileSize = ptrI + cnt; } - cnoOfLogPages = clogPageFileSize; + cnoOfLogPages = clogPageCount; } #ifndef NO_REDO_PAGE_CACHE === modified file 'storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp' --- a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp 2010-02-04 21:15:23 +0000 +++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp 2010-02-18 06:30:45 +0000 @@ -13752,8 +13752,9 @@ void Dblqh::execSUB_GCP_COMPLETE_REP(Signal* signal) { jamEntry(); - sendSignal(SUMA_REF, GSN_SUB_GCP_COMPLETE_REP, signal, - signal->getLength(), JBB); + Uint32 len = signal->getLength(); + EXECUTE_DIRECT(DBTUP, GSN_SUB_GCP_COMPLETE_REP, signal, len); + sendSignal(SUMA_REF, GSN_SUB_GCP_COMPLETE_REP, signal, len, JBB); } /* ------------------------------------------------------------------------- */ @@ -21932,8 +21933,8 @@ void Dblqh::execDBINFO_SCANREQ(Signal *s case Ndbinfo::LOGBUFFERS_TABLEID: { const size_t entry_size = sizeof(LogPageRecord); - const Uint64 free = cnoOfLogPages; - const Uint64 total = clogPageFileSize; + const Uint64 free = cnoOfLogPages; + const Uint64 total = clogPageCount; const Uint64 high = 0; // TODO Ndbinfo::Row row(signal, req); === modified file 'storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp' --- a/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp 2010-01-26 14:26:03 +0000 +++ b/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp 2010-02-19 14:44:11 +0000 @@ -1849,6 +1849,7 @@ private: void execFSREMOVECONF(Signal*); void execDBINFO_SCANREQ(Signal*); + void execSUB_GCP_COMPLETE_REP(Signal*); //------------------------------------------------------------------ //------------------------------------------------------------------ @@ -2693,15 +2694,6 @@ private: Uint32 noOfAttributes, Uint32* inBuffer); - void sendFireTrigOrd(Signal* signal, - KeyReqStruct *req_struct, - Operationrec * regOperPtr, - TupTriggerData* trigPtr, - Uint32 fragmentId, - Uint32 noPrimKeySignals, - Uint32 noBeforeSignals, - Uint32 noAfterSignals); - bool primaryKey(Tablerec* const, Uint32); // these set terrorCode and return non-zero on error @@ -2740,6 +2732,18 @@ private: void removeTuxEntries(Signal* signal, Tablerec* regTabPtr); + void ndbmtd_buffer_suma_trigger(Signal* signal, Uint32 len, + LinearSectionPtr ptr[]); + void flush_ndbmtd_suma_buffer(Signal*); + + struct SumaTriggerBuffer + { + SumaTriggerBuffer() { m_out_of_memory = 0;m_pageId = RNIL; m_freeWords = 0;} + Uint32 m_out_of_memory; + Uint32 m_pageId; + Uint32 m_freeWords; + } m_suma_trigger_buffer; + // ***************************************************************** // Error Handling routines. // ***************************************************************** === modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp' --- a/storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp 2010-01-15 13:55:03 +0000 +++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp 2010-02-19 14:44:11 +0000 @@ -125,6 +125,7 @@ Dbtup::Dbtup(Block_context& ctx, Uint32 addRecSignal(GSN_FSREMOVECONF, &Dbtup::execFSREMOVECONF, true); addRecSignal(GSN_DROP_FRAG_REQ, &Dbtup::execDROP_FRAG_REQ); + addRecSignal(GSN_SUB_GCP_COMPLETE_REP, &Dbtup::execSUB_GCP_COMPLETE_REP); fragoperrec = 0; fragrecord = 0; === modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp' --- a/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp 2009-12-14 22:14:34 +0000 +++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp 2010-02-18 06:30:45 +0000 @@ -197,7 +197,16 @@ Dbtup::execDROP_TRIG_IMPL_REQ(Signal* si // Drop trigger Uint32 r = dropTrigger(tabPtr.p, req, refToBlock(receiverRef)); - if (r == 0){ + if (r == 0) + { + /** + * make sure that any trigger data is sent before DROP_TRIG_CONF + * NOTE: This is only needed for SUMA triggers + * (which are the only buffered ones) but it shouldn't + * be too bad to do it for all triggers... + */ + flush_ndbmtd_suma_buffer(signal); + // Send conf DropTrigImplConf* conf = (DropTrigImplConf*)signal->getDataPtrSend(); conf->senderRef = reference(); @@ -939,6 +948,7 @@ out: jam(); return; } + //-------------------------------------------------------------------- // Now all data for this trigger has been read. It is now time to send // the trigger information consisting of two or three sets of TRIG_ @@ -1090,7 +1100,7 @@ out: if (executeDirect) { jam(); - EXECUTE_DIRECT(refToMain(trigPtr->m_receiverRef), + EXECUTE_DIRECT(refToMain(ref), GSN_FIRE_TRIG_ORD, signal, FireTrigOrd::SignalLengthSuma); @@ -1106,8 +1116,17 @@ out: ptr[1].sz = noBeforeWords; ptr[2].p = afterBuffer; ptr[2].sz = noAfterWords; - sendSignal(trigPtr->m_receiverRef, GSN_FIRE_TRIG_ORD, - signal, FireTrigOrd::SignalLengthSuma, JBB, ptr, 3); + if (refToMain(ref) == SUMA && (refToInstance(ref) != instance())) + { + jam(); + ndbmtd_buffer_suma_trigger(signal, FireTrigOrd::SignalLengthSuma, ptr); + } + else + { + jam(); + sendSignal(ref, GSN_FIRE_TRIG_ORD, + signal, FireTrigOrd::SignalLengthSuma, JBB, ptr, 3); + } } break; case (TriggerType::SUBSCRIPTION): @@ -1119,7 +1138,7 @@ out: if (executeDirect) { jam(); - EXECUTE_DIRECT(refToMain(trigPtr->m_receiverRef), + EXECUTE_DIRECT(refToMain(ref), GSN_FIRE_TRIG_ORD, signal, FireTrigOrd::SignalWithGCILength); @@ -1137,7 +1156,7 @@ out: ptr[1].sz = noBeforeWords; ptr[2].p = afterBuffer; ptr[2].sz = noAfterWords; - sendSignal(trigPtr->m_receiverRef, GSN_FIRE_TRIG_ORD, + sendSignal(ref, GSN_FIRE_TRIG_ORD, signal, FireTrigOrd::SignalWithGCILength, JBB, ptr, 3); } break; @@ -1370,17 +1389,6 @@ void Dbtup::sendTrigAttrInfo(Signal* sig } while (dataLen != dataIndex); } -void Dbtup::sendFireTrigOrd(Signal* signal, - KeyReqStruct *req_struct, - Operationrec * const regOperPtr, - TupTriggerData* const trigPtr, - Uint32 fragmentId, - Uint32 noPrimKeyWords, - Uint32 noBeforeValueWords, - Uint32 noAfterValueWords) -{ -} - /* * Ordered index triggers. * @@ -1583,3 +1591,119 @@ Dbtup::removeTuxEntries(Signal* signal, triggerList.next(triggerPtr); } } + +void +Dbtup::ndbmtd_buffer_suma_trigger(Signal * signal, + Uint32 len, + LinearSectionPtr sec[3]) +{ + jam(); + Uint32 tot = len + 5; + for (Uint32 i = 0; i<3; i++) + tot += sec[i].sz; + + Uint32 * ptr = 0; + Uint32 free = m_suma_trigger_buffer.m_freeWords; + Uint32 pageId = m_suma_trigger_buffer.m_pageId; + Uint32 oom = m_suma_trigger_buffer.m_out_of_memory; + if (free < tot) + { + jam(); + if (pageId != RNIL) + { + flush_ndbmtd_suma_buffer(signal); + } + if (oom == 0) + { + jam(); + ndbassert(m_suma_trigger_buffer.m_pageId == RNIL); + void * vptr = m_ctx.m_mm.alloc_page(RT_DBTUP_PAGE, + &m_suma_trigger_buffer.m_pageId, + Ndbd_mem_manager::NDB_ZONE_ANY); + ptr = reinterpret_cast(vptr); + free = GLOBAL_PAGE_SIZE_WORDS - tot; + } + } + else + { + jam(); + ptr = reinterpret_cast(c_page_pool.getPtr(pageId)); + ptr += (GLOBAL_PAGE_SIZE_WORDS - free); + free -= tot; + } + + if (likely(ptr != 0)) + { + jam(); + * ptr++ = tot; + * ptr++ = len; + * ptr++ = sec[0].sz; + * ptr++ = sec[1].sz; + * ptr++ = sec[2].sz; + memcpy(ptr, signal->getDataPtrSend(), 4 * len); + ptr += len; + for (Uint32 i = 0; i<3; i++) + { + memcpy(ptr, sec[i].p, 4 * sec[i].sz); + ptr += sec[i].sz; + } + + m_suma_trigger_buffer.m_freeWords = free; + if (free < (len + 5)) + { + flush_ndbmtd_suma_buffer(signal); + } + } + else + { + jam(); + m_suma_trigger_buffer.m_out_of_memory = 1; + } +} + +void +Dbtup::flush_ndbmtd_suma_buffer(Signal* signal) +{ + jam(); + + Uint32 pageId = m_suma_trigger_buffer.m_pageId; + Uint32 free = m_suma_trigger_buffer.m_freeWords; + Uint32 oom = m_suma_trigger_buffer.m_out_of_memory; + + if (pageId != RNIL) + { + jam(); + Uint32 save[2]; + save[0] = signal->theData[0]; + save[1] = signal->theData[1]; + signal->theData[0] = pageId; + signal->theData[1] = GLOBAL_PAGE_SIZE_WORDS - free; + sendSignal(SUMA_REF, GSN_FIRE_TRIG_ORD_L, signal, 2, JBB); + + signal->theData[0] = save[0]; + signal->theData[1] = save[1]; + } + else if (oom) + { + jam(); + Uint32 save[2]; + save[0] = signal->theData[0]; + save[1] = signal->theData[1]; + signal->theData[0] = RNIL; + signal->theData[1] = 0; + sendSignal(SUMA_REF, GSN_FIRE_TRIG_ORD_L, signal, 2, JBB); + + signal->theData[0] = save[0]; + signal->theData[1] = save[1]; + } + + m_suma_trigger_buffer.m_pageId = RNIL; + m_suma_trigger_buffer.m_freeWords = 0; + m_suma_trigger_buffer.m_out_of_memory = 0; +} + +void +Dbtup::execSUB_GCP_COMPLETE_REP(Signal* signal) +{ + flush_ndbmtd_suma_buffer(signal); +} === modified file 'storage/ndb/src/kernel/blocks/suma/Suma.cpp' --- a/storage/ndb/src/kernel/blocks/suma/Suma.cpp 2010-01-26 14:03:52 +0000 +++ b/storage/ndb/src/kernel/blocks/suma/Suma.cpp 2010-02-18 06:30:45 +0000 @@ -3984,6 +3984,67 @@ reformat(Signal* signal, LinearSectionPt return sz_2 > 0 ? 3 : 2; } +/** + * Pass entire pages with SUMA-trigger-data from + * TUP to SUMA to avoid extensive LongSignalMessage buffer contention + */ +void +Suma::execFIRE_TRIG_ORD_L(Signal* signal) +{ + jamEntry(); + + ndbassert(signal->getNoOfSections() == 0); + Uint32 pageId = signal->theData[0]; + Uint32 len = signal->theData[1]; + + if (pageId == RNIL && len == 0) + { + jam(); + /** + * Out of memory + */ + out_of_buffer(signal); + return; + } + + Uint32 * ptr = reinterpret_cast(c_page_pool.getPtr(pageId)); + while (len) + { + Uint32 * save = ptr; + Uint32 msglen = * ptr++; + Uint32 siglen = * ptr++; + Uint32 sec0len = * ptr++; + Uint32 sec1len = * ptr++; + Uint32 sec2len = * ptr++; + + /** + * Copy value directly into local buffers + */ + Uint32 trigId = ((FireTrigOrd*)ptr)->getTriggerId(); + memcpy(signal->theData, ptr, 4 * siglen); // signal + ptr += siglen; + memcpy(f_buffer, ptr, 4*sec0len); + ptr += sec0len; + memcpy(b_buffer, ptr, 4*sec1len); + ptr += sec1len; + memcpy(f_buffer + sec0len, ptr, 4*sec2len); + ptr += sec2len; + + f_trigBufferSize = sec0len + sec2len; + b_trigBufferSize = sec1len; + f_bufferLock = trigId; + b_bufferLock = trigId; + + execFIRE_TRIG_ORD(signal); + + ndbrequire(ptr == save + msglen); + ndbrequire(len >= msglen); + len -= msglen; + } + + m_ctx.m_mm.release_page(RT_DBTUP_PAGE, pageId); +} + void Suma::execFIRE_TRIG_ORD(Signal* signal) { @@ -4054,7 +4115,8 @@ Suma::execFIRE_TRIG_ORD(Signal* signal) LinearSectionPtr ptr[3]; const Uint32 nptr= reformat(signal, ptr, - f_buffer, sz, b_buffer, b_trigBufferSize); + f_buffer, f_trigBufferSize, + b_buffer, b_trigBufferSize); Uint32 ptrLen= 0; for(Uint32 i =0; i < nptr; i++) ptrLen+= ptr[i].sz; === modified file 'storage/ndb/src/kernel/blocks/suma/Suma.hpp' --- a/storage/ndb/src/kernel/blocks/suma/Suma.hpp 2010-01-26 14:03:52 +0000 +++ b/storage/ndb/src/kernel/blocks/suma/Suma.hpp 2010-02-18 06:30:45 +0000 @@ -87,6 +87,7 @@ public: */ void execTRIG_ATTRINFO(Signal* signal); void execFIRE_TRIG_ORD(Signal* signal); + void execFIRE_TRIG_ORD_L(Signal* signal); void execSUB_GCP_COMPLETE_REP(Signal* signal); /** === modified file 'storage/ndb/src/kernel/blocks/suma/SumaInit.cpp' --- a/storage/ndb/src/kernel/blocks/suma/SumaInit.cpp 2009-05-27 15:21:45 +0000 +++ b/storage/ndb/src/kernel/blocks/suma/SumaInit.cpp 2010-02-18 06:30:45 +0000 @@ -115,6 +115,7 @@ Suma::Suma(Block_context& ctx) : */ addRecSignal(GSN_TRIG_ATTRINFO, &Suma::execTRIG_ATTRINFO); addRecSignal(GSN_FIRE_TRIG_ORD, &Suma::execFIRE_TRIG_ORD); + addRecSignal(GSN_FIRE_TRIG_ORD_L, &Suma::execFIRE_TRIG_ORD_L); addRecSignal(GSN_CREATE_TRIG_IMPL_REF, &Suma::execCREATE_TRIG_IMPL_REF); addRecSignal(GSN_CREATE_TRIG_IMPL_CONF, &Suma::execCREATE_TRIG_IMPL_CONF); === modified file 'storage/ndb/src/kernel/vm/ArrayPool.hpp' --- a/storage/ndb/src/kernel/vm/ArrayPool.hpp 2009-11-12 22:29:56 +0000 +++ b/storage/ndb/src/kernel/vm/ArrayPool.hpp 2010-02-18 06:30:45 +0000 @@ -83,7 +83,7 @@ public: } inline void decNoFree(Uint32 cnt) { - assert(noOfFree > cnt); + assert(noOfFree >= cnt); noOfFree -= cnt; updateFreeMin(); } === modified file 'storage/ndb/src/kernel/vm/ndbd_malloc_impl.cpp' --- a/storage/ndb/src/kernel/vm/ndbd_malloc_impl.cpp 2010-01-23 10:08:15 +0000 +++ b/storage/ndb/src/kernel/vm/ndbd_malloc_impl.cpp 2010-02-18 00:06:17 +0000 @@ -185,6 +185,8 @@ retry: Uint32 Ndbd_mem_manager::ndb_log2(Uint32 input) { + if (input > 65535) + return 16; input = input | (input >> 8); input = input | (input >> 4); input = input | (input >> 2); === modified file 'storage/ndb/src/mgmsrv/CMakeLists.txt' --- a/storage/ndb/src/mgmsrv/CMakeLists.txt 2010-01-03 23:42:21 +0000 +++ b/storage/ndb/src/mgmsrv/CMakeLists.txt 2010-02-18 10:45:20 +0000 @@ -22,14 +22,7 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/ ${CMAKE_SOURCE_DIR}/storage/ndb/src/mgmclient ${CMAKE_SOURCE_DIR}/sql) -LINK_LIBRARIES(ndbmgmclient - ndbclient - dbug - mysys - strings - ndbgeneral - ndbportlib) - +LINK_LIBRARIES(ndbmgmclient ndbclient) ADD_LIBRARY(ndbconf Config.cpp ConfigInfo.cpp === modified file 'storage/ndb/src/mgmsrv/MgmtSrvr.cpp' --- a/storage/ndb/src/mgmsrv/MgmtSrvr.cpp 2010-02-01 10:03:20 +0000 +++ b/storage/ndb/src/mgmsrv/MgmtSrvr.cpp 2010-02-18 13:40:02 +0000 @@ -238,7 +238,8 @@ MgmtSrvr::MgmtSrvr(const MgmtOpts& opts, _logLevelThreadSleep(500), m_event_listner(this), m_master_node(0), - _logLevelThread(NULL) + _logLevelThread(NULL), + m_version_string(ndbGetOwnVersionString()) { DBUG_ENTER("MgmtSrvr::MgmtSrvr"); === modified file 'storage/ndb/src/mgmsrv/MgmtSrvr.hpp' --- a/storage/ndb/src/mgmsrv/MgmtSrvr.hpp 2009-11-13 11:24:05 +0000 +++ b/storage/ndb/src/mgmsrv/MgmtSrvr.hpp 2010-02-18 13:40:02 +0000 @@ -554,6 +554,12 @@ public: int match_hostname(const struct sockaddr *, const char *) const; int try_alloc(unsigned id, const char *, enum ndb_mgm_node_type type, const struct sockaddr *client_addr, Uint32 timeout_ms); + + BaseString m_version_string; + const char* get_version_string(void) const { + return m_version_string.c_str(); + } + }; #endif // MgmtSrvr_H === modified file 'storage/ndb/src/mgmsrv/Services.cpp' --- a/storage/ndb/src/mgmsrv/Services.cpp 2010-01-19 08:24:03 +0000 +++ b/storage/ndb/src/mgmsrv/Services.cpp 2010-02-18 13:40:02 +0000 @@ -677,14 +677,14 @@ void MgmApiSession::getVersion(Parser::Context &, Properties const &) { m_output->println("version"); - m_output->println("id: %d", NDB_VERSION); - m_output->println("major: %d", getMajor(NDB_VERSION)); - m_output->println("minor: %d", getMinor(NDB_VERSION)); - m_output->println("build: %d", getBuild(NDB_VERSION)); - m_output->println("string: %s", NDB_VERSION_STRING); - m_output->println("mysql_major: %d", getMajor(NDB_MYSQL_VERSION_D)); - m_output->println("mysql_minor: %d", getMinor(NDB_MYSQL_VERSION_D)); - m_output->println("mysql_build: %d", getBuild(NDB_MYSQL_VERSION_D)); + m_output->println("id: %d", NDB_VERSION_D); + m_output->println("major: %d", NDB_VERSION_MAJOR); + m_output->println("minor: %d", NDB_VERSION_MINOR); + m_output->println("build: %d", NDB_VERSION_BUILD); + m_output->println("string: %s", m_mgmsrv.get_version_string()); + m_output->println("mysql_major: %d", NDB_MYSQL_VERSION_MAJOR); + m_output->println("mysql_minor: %d", NDB_MYSQL_VERSION_MINOR); + m_output->println("mysql_build: %d", NDB_MYSQL_VERSION_BUILD); m_output->println("%s", ""); } === modified file 'storage/ndb/src/ndbapi/NdbDictionary.cpp' --- a/storage/ndb/src/ndbapi/NdbDictionary.cpp 2010-02-11 15:52:35 +0000 +++ b/storage/ndb/src/ndbapi/NdbDictionary.cpp 2010-02-19 14:44:11 +0000 @@ -2785,6 +2785,7 @@ operator<<(NdbOut& out, const NdbDiction case NdbDictionary::Column::Blob: case NdbDictionary::Column::Text: out << " BV=" << col.getBlobVersion(); + out << " BT=" << ((col.getBlobTable() != 0) ? col.getBlobTable()->getName() : ""); break; default: break; === modified file 'storage/ndb/test/include/HugoTransactions.hpp' --- a/storage/ndb/test/include/HugoTransactions.hpp 2009-05-27 12:11:46 +0000 +++ b/storage/ndb/test/include/HugoTransactions.hpp 2010-02-18 23:50:31 +0000 @@ -70,6 +70,11 @@ public: NdbOperation::LockMode = NdbOperation::LM_Read, int rand = 0); + int pkReadUnlockRecords(Ndb*, + int records, + int batchsize = 1, + NdbOperation::LockMode = NdbOperation::LM_Read); + int scanUpdateRecords(Ndb*, NdbScanOperation::ScanFlag, int records, int abort = 0, === modified file 'storage/ndb/test/include/NdbRestarter.hpp' --- a/storage/ndb/test/include/NdbRestarter.hpp 2009-08-11 08:10:20 +0000 +++ b/storage/ndb/test/include/NdbRestarter.hpp 2010-02-18 23:50:31 +0000 @@ -92,6 +92,9 @@ public: int getRandomNodeSameNodeGroup(int nodeId, int randomNumber); int getRandomNodeOtherNodeGroup(int nodeId, int randomNumber); int getRandomNotMasterNodeId(int randomNumber); + + int getMasterNodeVersion(int& version); + int getNodeTypeVersionRange(ndb_mgm_node_type type, int& minVer, int& maxVer); NdbMgmHandle handle; === modified file 'storage/ndb/test/ndbapi/testMgm.cpp' --- a/storage/ndb/test/ndbapi/testMgm.cpp 2009-11-08 12:52:27 +0000 +++ b/storage/ndb/test/ndbapi/testMgm.cpp 2010-02-18 13:40:02 +0000 @@ -1131,47 +1131,6 @@ int runSleepAndStop(NDBT_Context* ctx, N static bool -get_version(NdbMgmd& mgmd, - Properties& reply) -{ - Properties args; - if (!mgmd.call("get version", args, - "version", reply)) - { - g_err << "get_version: mgmd.call failed" << endl; - return false; - } - - //reply.print(); - return true; -} - -int runTestGetVersion(NDBT_Context* ctx, NDBT_Step* step) -{ - NdbMgmd mgmd; - - if (!mgmd.connect()) - return NDBT_FAILED; - - Properties reply; - if (!get_version(mgmd, reply)) - return NDBT_FAILED; - - return NDBT_OK; -} - -int runTestGetVersionUntilStopped(NDBT_Context* ctx, NDBT_Step* step) -{ - int result= NDBT_OK; - while(!ctx->isTestStopped() && - (result= runTestGetVersion(ctx, step)) == NDBT_OK) - ; - return result; -} - - - -static bool check_connection(NdbMgmd& mgmd) { Properties args, reply; @@ -2322,6 +2281,94 @@ int runTestBug45497(NDBT_Context* ctx, N } +static int +runTestGetVersion(NDBT_Context* ctx, NDBT_Step* step) +{ + + NdbMgmd mgmd; + + if (!mgmd.connect()) + return NDBT_FAILED; + + char verStr[64]; + int major, minor, build; + if (ndb_mgm_get_version(mgmd.handle(), + &major, &minor, &build, + sizeof(verStr), verStr) != 1) + { + g_err << "ndb_mgm_get_version failed," + << "error: " << ndb_mgm_get_latest_error_msg(mgmd.handle()) + << "desc: " << ndb_mgm_get_latest_error_desc(mgmd.handle()) << endl; + return NDBT_FAILED; + } + + g_info << "Using major: " << major + << " minor: " << minor + << " build: " << build + << " string: " << verStr << endl; + + int l = 0; + int loops = ctx->getNumLoops(); + while(l < loops) + { + char verStr2[64]; + int major2, minor2, build2; + if (ndb_mgm_get_version(mgmd.handle(), + &major2, &minor2, &build2, + sizeof(verStr2), verStr2) != 1) + { + g_err << "ndb_mgm_get_version failed," + << "error: " << ndb_mgm_get_latest_error_msg(mgmd.handle()) + << "desc: " << ndb_mgm_get_latest_error_desc(mgmd.handle()) << endl; + return NDBT_FAILED; + } + + if (major != major2) + { + g_err << "Got different major: " << major2 + << " excpected: " << major << endl; + return NDBT_FAILED; + } + + if (minor != minor2) + { + g_err << "Got different minor: " << minor2 + << " excpected: " << minor << endl; + return NDBT_FAILED; + } + + if (build != build2) + { + g_err << "Got different build: " << build2 + << " excpected: " << build << endl; + return NDBT_FAILED; + } + + if (strcmp(verStr, verStr2) != 0) + { + g_err << "Got different verStr: " << verStr2 + << " excpected: " << verStr << endl; + return NDBT_FAILED; + } + + l++; + } + + return NDBT_OK; +} + + +static int +runTestGetVersionUntilStopped(NDBT_Context* ctx, NDBT_Step* step) +{ + int result= NDBT_OK; + while(!ctx->isTestStopped() && + (result= runTestGetVersion(ctx, step)) == NDBT_OK) + ; + return result; +} + + NDBT_TESTSUITE(testMgm); DRIVER(DummyDriver); /* turn off use of NdbApi */ TESTCASE("ApiSessionFailure", @@ -2396,10 +2443,9 @@ TESTCASE("TestGetNodeId", "Test 'get nodeid'"){ INITIALIZER(runTestGetNodeId); } - TESTCASE("TestGetVersion", - "Test 'get version'"){ - INITIALIZER(runTestGetVersion); + "Test 'get version' and 'ndb_mgm_get_version'"){ + STEPS(runTestGetVersion, 20); } TESTCASE("TestTransporterConnect", "Test 'transporter connect'"){ @@ -2430,7 +2476,7 @@ TESTCASE("Stress", STEP(runSetConfigUntilStopped); STEPS(runGetConfigUntilStopped, 10); STEPS(runTestStatusUntilStopped, 10); -// STEPS(runTestGetVersionUntilStopped, 5); + STEPS(runTestGetVersionUntilStopped, 5); STEP(runSleepAndStop); } TESTCASE("Stress2", @@ -2439,7 +2485,7 @@ TESTCASE("Stress2", STEPS(runTestSetConfigParallelUntilStopped, 5); STEPS(runGetConfigUntilStopped, 10); STEPS(runTestStatusUntilStopped, 10); -// STEPS(runTestGetVersionUntilStopped, 5); + STEPS(runTestGetVersionUntilStopped, 5); STEP(runSleepAndStop); } TESTCASE("Bug45497", === modified file 'storage/ndb/test/ndbapi/testUpgrade.cpp' --- a/storage/ndb/test/ndbapi/testUpgrade.cpp 2009-10-30 08:17:03 +0000 +++ b/storage/ndb/test/ndbapi/testUpgrade.cpp 2010-02-18 23:50:31 +0000 @@ -24,6 +24,7 @@ #include #include #include +#include static Vector table_list; @@ -131,30 +132,74 @@ createDropEvent(NDBT_Context* ctx, NDBT_ Ndb* pNdb = GETNDB(step); NdbDictionary::Dictionary *myDict = pNdb->getDictionary(); - for (unsigned i = 0; igetProperty("NoDDL", Uint32(0)) == 0) { - int res = NDBT_OK; - const NdbDictionary::Table* tab = myDict->getTable(table_list[i].c_str()); - if (tab == 0) - { - continue; - } - if ((res = createEvent(pNdb, *tab) != NDBT_OK)) - { - return res; - } - - - - if ((res = dropEvent(pNdb, *tab)) != NDBT_OK) + for (unsigned i = 0; igetTable(table_list[i].c_str()); + if (tab == 0) + { + continue; + } + if ((res = createEvent(pNdb, *tab) != NDBT_OK)) + { + return res; + } + + + + if ((res = dropEvent(pNdb, *tab)) != NDBT_OK) + { + return res; + } } } return NDBT_OK; } +/* An enum for expressing how many of the multiple nodes + * of a given type an action should be applied to + */ +enum NodeSet +{ + All = 0, + NotAll = 1, /* less than All, or None if there's only 1 */ + None = 2 +}; + +uint getNodeCount(NodeSet set, uint numNodes) +{ + switch(set) + { + case All: + return numNodes; + case NotAll: + { + if (numNodes < 2) + return 0; + + if (numNodes == 2) + return 1; + + uint range = numNodes - 2; + + /* At least 1, at most numNodes - 1 */ + return (1 + (rand() % (range + 1))); + } + case None: + { + return 0; + } + default: + g_err << "Unknown set type : " << set << endl; + abort(); + return 0; + } +}; + + /** Test that one node at a time can be upgraded */ @@ -162,6 +207,9 @@ createDropEvent(NDBT_Context* ctx, NDBT_ int runUpgrade_NR1(NDBT_Context* ctx, NDBT_Step* step){ AtrtClient atrt; + NodeSet mgmdNodeSet = (NodeSet) ctx->getProperty("MgmdNodeSet", Uint32(0)); + NodeSet ndbdNodeSet = (NodeSet) ctx->getProperty("NdbdNodeSet", Uint32(0)); + SqlResultSet clusters; if (!atrt.getClusters(clusters)) return NDBT_FAILED; @@ -185,51 +233,65 @@ int runUpgrade_NR1(NDBT_Context* ctx, ND SqlResultSet mgmds; if (!atrt.getMgmds(clusterId, mgmds)) return NDBT_FAILED; - - while (mgmds.next()) + + uint mgmdCount = mgmds.numRows(); + uint restartCount = getNodeCount(mgmdNodeSet, mgmdCount); + + ndbout << "Restarting " + << restartCount << " of " << mgmdCount + << " mgmds" << endl; + + while (mgmds.next() && restartCount --) { ndbout << "Restart mgmd " << mgmds.columnAsInt("node_id") << endl; if (!atrt.changeVersion(mgmds.columnAsInt("id"), "")) return NDBT_FAILED; - + if (restarter.waitConnected()) return NDBT_FAILED; ndbout << "Connected to mgmd"<< endl; } - + ndbout << "Waiting for started"<< endl; if (restarter.waitClusterStarted()) return NDBT_FAILED; ndbout << "Started"<< endl; - + // Restart ndbd(s) SqlResultSet ndbds; if (!atrt.getNdbds(clusterId, ndbds)) return NDBT_FAILED; - while(ndbds.next()) + uint ndbdCount = ndbds.numRows(); + restartCount = getNodeCount(ndbdNodeSet, ndbdCount); + + ndbout << "Restarting " + << restartCount << " of " << ndbdCount + << " ndbds" << endl; + + while(ndbds.next() && restartCount --) { int nodeId = ndbds.columnAsInt("node_id"); int processId = ndbds.columnAsInt("id"); ndbout << "Restart node " << nodeId << endl; - + if (!atrt.changeVersion(processId, "")) return NDBT_FAILED; - + if (restarter.waitNodesNoStart(&nodeId, 1)) return NDBT_FAILED; - + if (restarter.startNodes(&nodeId, 1)) return NDBT_FAILED; - + if (restarter.waitNodesStarted(&nodeId, 1)) return NDBT_FAILED; - + if (createDropEvent(ctx, step)) return NDBT_FAILED; } } - + ctx->stopTest(); return NDBT_OK; } @@ -259,6 +321,9 @@ runUpgrade_Half(NDBT_Context* ctx, NDBT_ args = "--initial=0"; } + NodeSet mgmdNodeSet = (NodeSet) ctx->getProperty("MgmdNodeSet", Uint32(0)); + NodeSet ndbdNodeSet = (NodeSet) ctx->getProperty("NdbdNodeSet", Uint32(0)); + SqlResultSet clusters; if (!atrt.getClusters(clusters)) return NDBT_FAILED; @@ -283,7 +348,14 @@ runUpgrade_Half(NDBT_Context* ctx, NDBT_ if (!atrt.getMgmds(clusterId, mgmds)) return NDBT_FAILED; - while (mgmds.next()) + uint mgmdCount = mgmds.numRows(); + uint restartCount = getNodeCount(mgmdNodeSet, mgmdCount); + + ndbout << "Restarting " + << restartCount << " of " << mgmdCount + << " mgmds" << endl; + + while (mgmds.next() && restartCount --) { ndbout << "Restart mgmd" << mgmds.columnAsInt("node_id") << endl; if (!atrt.changeVersion(mgmds.columnAsInt("id"), "")) @@ -310,12 +382,19 @@ runUpgrade_Half(NDBT_Context* ctx, NDBT_ nodes.push_back(n); } + uint ndbdCount = ndbds.numRows(); + restartCount = getNodeCount(ndbdNodeSet, ndbdCount); + + ndbout << "Restarting " + << restartCount << " of " << ndbdCount + << " ndbds" << endl; + int nodesarray[256]; int cnt= 0; Bitmask<4> seen_groups; Bitmask<4> restarted_nodes; - for (Uint32 i = 0; isetProperty("MgmdNodeSet", (Uint32) NodeSet(None)); + int res = runUpgrade_Half(ctx, step); + ctx->stopTest(); + return res; +} + +/** + Test that we can upgrade the Ndbds first, then + the MGMDs +*/ +int runUpgrade_NdbdFirst(NDBT_Context* ctx, NDBT_Step* step) +{ + ctx->setProperty("MgmdNodeSet", (Uint32) NodeSet(None)); + int res = runUpgrade_Half(ctx, step); + if (res == NDBT_OK) + { + ctx->setProperty("MgmdNodeSet", (Uint32) NodeSet(All)); + ctx->setProperty("NdbdNodeSet", (Uint32) NodeSet(None)); + res = runUpgrade_Half(ctx, step); + } + ctx->stopTest(); + return res; +} + +/** + Upgrade some of the MGMDs +*/ +int runUpgrade_NotAllMGMD(NDBT_Context* ctx, NDBT_Step* step) +{ + ctx->setProperty("MgmdNodeSet", (Uint32) NodeSet(NotAll)); + ctx->setProperty("NdbdNodeSet", (Uint32) NodeSet(None)); + int res = runUpgrade_Half(ctx, step); + ctx->stopTest(); + return res; +} + int runCheckStarted(NDBT_Context* ctx, NDBT_Step* step){ // Check cluster is started @@ -494,6 +616,27 @@ runCreateOneTable(NDBT_Context* ctx, NDB return NDBT_OK; } +int runGetTableList(NDBT_Context* ctx, NDBT_Step* step) +{ + table_list.clear(); + ndbout << "Looking for tables ... "; + for (int i = 0; igetDictionary() + ->getTable(NDBT_Tables::getTable(i) + ->getName()); + if (tab != NULL) + { + ndbout << tab->getName() << " "; + table_list.push_back(BaseString(tab->getName())); + } + } + ndbout << endl; + + return NDBT_OK; +} + int runLoadAll(NDBT_Context* ctx, NDBT_Step* step) { @@ -513,6 +656,27 @@ runLoadAll(NDBT_Context* ctx, NDBT_Step* return result; } +int +runClearAll(NDBT_Context* ctx, NDBT_Step* step) +{ + Ndb* pNdb = GETNDB(step); + NdbDictionary::Dictionary * pDict = pNdb->getDictionary(); + int records = ctx->getNumRecords(); + int result = NDBT_OK; + + for (unsigned i = 0; igetTable(table_list[i].c_str()); + if (tab) + { + HugoTransactions trans(* tab); + trans.clearTable(pNdb, records); + } + } + + return result; +} + int runBasic(NDBT_Context* ctx, NDBT_Step* step) @@ -525,7 +689,6 @@ runBasic(NDBT_Context* ctx, NDBT_Step* s int l = 0; while (!ctx->isTestStopped()) { - l++; for (unsigned i = 0; igetTable(table_list[i].c_str()); @@ -535,6 +698,7 @@ runBasic(NDBT_Context* ctx, NDBT_Step* s trans.loadTable(pNdb, records); trans.scanUpdateRecords(pNdb, records); trans.pkUpdateRecords(pNdb, records); + trans.pkReadUnlockRecords(pNdb, records); break; case 1: trans.scanUpdateRecords(pNdb, records); @@ -558,6 +722,7 @@ runBasic(NDBT_Context* ctx, NDBT_Step* s break; } } + l++; } return result; @@ -611,6 +776,15 @@ startPostUpgradeChecks(NDBT_Context* ctx * This will restart *self* in new version */ + BaseString extraArgs; + if (ctx->getProperty("RestartNoDDL", Uint32(0))) + { + /* Ask post-upgrade steps not to perform DDL + * (e.g. for 6.3->7.0 upgrade) + */ + extraArgs.append(" --noddl "); + } + /** * mysql-getopt works so that passing "-n X -n Y" is ok * and is interpreted as "-n Y" @@ -620,7 +794,9 @@ startPostUpgradeChecks(NDBT_Context* ctx * this will restart it as "testUpgrade -n X -n X--post-upgrade" */ BaseString tc; - tc.assfmt("-n %s--post-upgrade", ctx->getCase()->getName()); + tc.assfmt("-n %s--post-upgrade %s", + ctx->getCase()->getName(), + extraArgs.c_str()); ndbout << "About to restart self with extra arg: " << tc.c_str() << endl; @@ -641,6 +817,18 @@ startPostUpgradeChecks(NDBT_Context* ctx } int +startPostUpgradeChecksApiFirst(NDBT_Context* ctx, NDBT_Step* step) +{ + /* If Api is upgraded before all NDBDs then it may not + * be possible to use DDL from the upgraded API + * The upgraded Api will decide, but we pass NoDDL + * in + */ + ctx->setProperty("RestartNoDDL", 1); + return startPostUpgradeChecks(ctx, step); +} + +int runPostUpgradeChecks(NDBT_Context* ctx, NDBT_Step* step) { /** @@ -659,56 +847,116 @@ runPostUpgradeChecks(NDBT_Context* ctx, ndbout << "done" << endl; - /** - * Bug48227 - * - */ - Ndb* pNdb = GETNDB(step); - NdbDictionary::Dictionary *pDict = pNdb->getDictionary(); + if (ctx->getProperty("NoDDL", Uint32(0)) == 0) { - NdbDictionary::Dictionary::List l; - pDict->listObjects(l); - for (Uint32 i = 0; igetDictionary(); + { + NdbDictionary::Dictionary::List l; + pDict->listObjects(l); + for (Uint32 i = 0; idropTable("I3"); + if (NDBT_Tables::createTable(pNdb, "I3")) + { + ndbout_c("Failed to create table!"); + ndbout << pDict->getNdbError() << endl; + return NDBT_FAILED; + } + + { + NdbDictionary::Dictionary::List l; + pDict->listObjects(l); + for (Uint32 i = 0; igetTable("I3") == 0) + { + ndbout_c("Table disappered"); + return NDBT_FAILED; + } } - pDict->dropTable("I3"); - if (NDBT_Tables::createTable(pNdb, "I3")) - { - ndbout_c("Failed to create table!"); - ndbout << pDict->getNdbError() << endl; - return NDBT_FAILED; - } + return NDBT_OK; +} - { - NdbDictionary::Dictionary::List l; - pDict->listObjects(l); - for (Uint32 i = 0; igetProperty("WaitSeconds", Uint32(30)); + while (waitSeconds && + !ctx->isTestStopped()) + { + NdbSleep_MilliSleep(1000); + waitSeconds --; } + ctx->stopTest(); + return NDBT_OK; +} + +int runPostUpgradeDecideDDL(NDBT_Context* ctx, NDBT_Step* step) +{ + /* We are running post-upgrade, now examine the versions + * of connected nodes and update the 'NoDDL' variable + * accordingly + */ + /* DDL should be ok as long as + * 1) All data nodes have the same version + * 2) We are at the same version as the data nodes + */ + bool useDDL = true; - NdbRestarter res; - if (res.restartAll() != 0) + NdbRestarter restarter; + int minNdbVer = 0; + int maxNdbVer = 0; + int myVer = NDB_VERSION; + + if (restarter.getNodeTypeVersionRange(NDB_MGM_NODE_TYPE_NDB, + minNdbVer, + maxNdbVer) == -1) { - ndbout_c("restartAll() failed"); + g_err << "getNodeTypeVersionRange call failed" << endl; return NDBT_FAILED; } - if (res.waitClusterStarted() != 0) + if (minNdbVer != maxNdbVer) { - ndbout_c("waitClusterStarted() failed"); - return NDBT_FAILED; + useDDL = false; + ndbout << "Ndbd nodes have mixed versions, DDL not supported" << endl; } - - if (pDict->getTable("I3") == 0) + if (myVer != minNdbVer) { - ndbout_c("Table disappered"); - return NDBT_FAILED; + useDDL = false; + ndbout << "Api has different version to Ndbd nodes, DDL not supported" << endl; } + ctx->setProperty("NoDDL", useDDL?0:1); + return NDBT_OK; } + NDBT_TESTSUITE(testUpgrade); TESTCASE("Upgrade_NR1", "Test that one node at a time can be upgraded"){ @@ -817,6 +1065,80 @@ POSTUPGRADE("Upgrade_Traffic_FS_one") INITIALIZER(runCheckStarted); INITIALIZER(runPostUpgradeChecks); } +TESTCASE("Upgrade_Api_Only", + "Test that upgrading the Api node only works") +{ + INITIALIZER(runCheckStarted); + INITIALIZER(runCreateAllTables); + VERIFIER(startPostUpgradeChecksApiFirst); +} +POSTUPGRADE("Upgrade_Api_Only") +{ + INITIALIZER(runCheckStarted); + INITIALIZER(runPostUpgradeDecideDDL); + INITIALIZER(runGetTableList); + TC_PROPERTY("WaitSeconds", 30); + STEP(runBasic); + STEP(runPostUpgradeChecks); + STEP(runWait); + FINALIZER(runClearAll); +} +TESTCASE("Upgrade_Api_Before_NR1", + "Test that upgrading the Api node before the kernel works") +{ + /* Api, then MGMD(s), then NDBDs */ + INITIALIZER(runCheckStarted); + INITIALIZER(runCreateAllTables); + VERIFIER(startPostUpgradeChecksApiFirst); +} +POSTUPGRADE("Upgrade_Api_Before_NR1") +{ + INITIALIZER(runCheckStarted); + INITIALIZER(runPostUpgradeDecideDDL); + INITIALIZER(runGetTableList); + STEP(runBasic); + STEP(runUpgrade_NR1); /* Upgrade kernel nodes using NR1 */ + FINALIZER(runPostUpgradeChecks); + FINALIZER(runClearAll); +} +TESTCASE("Upgrade_Api_NDBD_MGMD", + "Test that updating in reverse order works") +{ + INITIALIZER(runCheckStarted); + INITIALIZER(runCreateAllTables); + VERIFIER(startPostUpgradeChecksApiFirst); +} +POSTUPGRADE("Upgrade_Api_NDBD_MGMD") +{ + INITIALIZER(runCheckStarted); + INITIALIZER(runPostUpgradeDecideDDL); + INITIALIZER(runGetTableList); + STEP(runBasic); + STEP(runUpgrade_NdbdFirst); + FINALIZER(runPostUpgradeChecks); + FINALIZER(runClearAll); +} +TESTCASE("Upgrade_Mixed_MGMD_API_NDBD", + "Test that upgrading MGMD/API partially before data nodes works") +{ + INITIALIZER(runCheckStarted); + INITIALIZER(runCreateAllTables); + STEP(runUpgrade_NotAllMGMD); /* Upgrade an MGMD */ + STEP(runBasic); + VERIFIER(startPostUpgradeChecksApiFirst); /* Upgrade Api */ +} +POSTUPGRADE("Upgrade_Mixed_MGMD_API_NDBD") +{ + INITIALIZER(runCheckStarted); + INITIALIZER(runPostUpgradeDecideDDL); + INITIALIZER(runGetTableList); + INITIALIZER(runClearAll); /* Clear rows from old-ver basic run */ + STEP(runBasic); + STEP(runUpgrade_NdbdFirst); /* Upgrade all Ndbds, then MGMDs finally */ + FINALIZER(runPostUpgradeChecks); + FINALIZER(runClearAll); +} + NDBT_TESTSUITE_END(testUpgrade); int main(int argc, const char** argv){ === modified file 'storage/ndb/test/run-test/command.cpp' --- a/storage/ndb/test/run-test/command.cpp 2009-11-13 04:54:11 +0000 +++ b/storage/ndb/test/run-test/command.cpp 2010-02-18 23:50:31 +0000 @@ -63,6 +63,46 @@ ack_command(AtrtClient& atrtdb, int comm } +BaseString +set_env_var(const BaseString& existing, + const BaseString& name, + const BaseString& value) +{ + /* Split existing on space + * (may have issues with env vars with spaces) + * Split assignments on = + * Where name == name, output new value + */ + BaseString newEnv; + Vector assignments; + int assignmentCount = existing.split(assignments, BaseString(" ")); + + for (int i=0; i < assignmentCount; i++) + { + Vector terms; + int termCount = assignments[i].split(terms, BaseString("=")); + + if (termCount) + { + if (strcmp(name.c_str(), terms[0].c_str()) == 0) + { + /* Found element */ + newEnv.append(name); + newEnv.append('='); + newEnv.append(value); + } + else + { + newEnv.append(assignments[i]); + } + } + newEnv.append(' '); + } + + return newEnv; +} + + Vector g_saved_procs; static @@ -85,6 +125,29 @@ do_change_version(atrt_config& config, S } atrt_process& proc= *config.m_processes[process_id]; + const char* new_prefix= g_prefix1 ? g_prefix1 : g_prefix; + const char* old_prefix= g_prefix; + const char *start= strstr(proc.m_proc.m_path.c_str(), old_prefix); + if (!start){ + /* Process path does not contain old prefix. + * Perhaps it contains the new prefix - e.g. is already + * upgraded? + */ + if (strstr(proc.m_proc.m_path.c_str(), new_prefix)) + { + /* Process is already upgraded, *assume* that this + * is ok + * Alternatives could be - error, or downgrade. + */ + g_logger.info("Process already upgraded"); + return true; + } + + g_logger.critical("Could not find '%s' in '%s'", + old_prefix, proc.m_proc.m_path.c_str()); + return false; + } + // Save current proc state if (proc.m_save.m_saved == false) { @@ -95,20 +158,15 @@ do_change_version(atrt_config& config, S g_logger.info("stopping process..."); if (!stop_process(proc)) return false; - - const char* new_prefix= g_prefix1 ? g_prefix1 : g_prefix; - const char* old_prefix= g_prefix; - proc.m_proc.m_env.appfmt(" MYSQL_BASE_DIR=%s", new_prefix); - const char *start= strstr(proc.m_proc.m_path.c_str(), old_prefix); - if (!start){ - g_logger.critical("Could not find '%s' in '%s'", - old_prefix, proc.m_proc.m_path.c_str()); - return false; - } + BaseString newEnv = set_env_var(proc.m_proc.m_env, + BaseString("MYSQL_BASE_DIR"), + BaseString(new_prefix)); + proc.m_proc.m_env.assign(newEnv); BaseString suffix(proc.m_proc.m_path.substr(strlen(old_prefix))); proc.m_proc.m_path.assign(new_prefix).append(suffix); if (process_args && strlen(process_args)) { + /* Beware too long args */ proc.m_proc.m_args.append(" "); proc.m_proc.m_args.append(process_args); } === modified file 'storage/ndb/test/run-test/db.cpp' --- a/storage/ndb/test/run-test/db.cpp 2009-11-13 04:54:11 +0000 +++ b/storage/ndb/test/run-test/db.cpp 2010-02-18 23:50:31 +0000 @@ -195,13 +195,13 @@ connect_mysqld(atrt_process* proc) return false; } - if (port) - { - mysql_protocol_type val = MYSQL_PROTOCOL_TCP; - mysql_options(&proc->m_mysql, MYSQL_OPT_PROTOCOL, &val); - } for (size_t i = 0; i<20; i++) { + if (port) + { + mysql_protocol_type val = MYSQL_PROTOCOL_TCP; + mysql_options(&proc->m_mysql, MYSQL_OPT_PROTOCOL, &val); + } if (mysql_real_connect(&proc->m_mysql, proc->m_host->m_hostname.c_str(), "root", "", "test", === modified file 'storage/ndb/test/run-test/upgrade-tests.txt' --- a/storage/ndb/test/run-test/upgrade-tests.txt 2009-05-25 19:53:07 +0000 +++ b/storage/ndb/test/run-test/upgrade-tests.txt 2010-02-18 23:01:15 +0000 @@ -22,3 +22,19 @@ cmd: testUpgrade args: -n Upgrade_Traffic_FS T1 max-time: 1200 +cmd: testUpgrade +args: -n Upgrade_Api_Only T1 +max-time: 1200 + +cmd: testUpgrade +args: -n Upgrade_Api_Before_NR1 T2 +max-time: 1200 + +cmd: testUpgrade +args: -n Upgrade_Api_NDBD_MGMD T1 +max-time: 1200 + +cmd: testUpgrade +args: -n Upgrade_Mixed_MGMD_API_NDBD T2 +max-time: 1200 + === modified file 'storage/ndb/test/src/CpcClient.cpp' --- a/storage/ndb/test/src/CpcClient.cpp 2010-01-18 19:20:01 +0000 +++ b/storage/ndb/test/src/CpcClient.cpp 2010-02-18 23:50:31 +0000 @@ -441,6 +441,15 @@ SimpleCpcClient::cpc_send(const char *cm break; case PropertiesType_char: args.get(name, val_s); + if (strlen(val_s.c_str()) > Parser_t::Context::MaxParseBytes) + { + ndbout << "Argument " << name << " at " + << strlen(val_s.c_str()) + << " longer than max of " + << Parser_t::Context::MaxParseBytes + << endl; + abort(); + } cpc_out.println("%s: %s", name, val_s.c_str()); break; default: === modified file 'storage/ndb/test/src/HugoTransactions.cpp' --- a/storage/ndb/test/src/HugoTransactions.cpp 2010-01-28 15:16:46 +0000 +++ b/storage/ndb/test/src/HugoTransactions.cpp 2010-02-18 23:50:31 +0000 @@ -1501,6 +1501,144 @@ HugoTransactions::pkDelRecords(Ndb* pNdb return NDBT_OK; } +int +HugoTransactions::pkReadUnlockRecords(Ndb* pNdb, + int records, + int batch, + NdbOperation::LockMode lm) +{ + int reads = 0; + int r = 0; + int retryAttempt = 0; + int check; + + if (batch == 0) { + g_info << "ERROR: Argument batch == 0 in pkReadRecords(). Not allowed." << endl; + return NDBT_FAILED; + } + + if (idx != NULL) { + g_info << "ERROR: Cannot call pkReadUnlockRecords for index" << endl; + return NDBT_FAILED; + } + + while (r < records){ + if(r + batch > records) + batch = records - r; + + if (retryAttempt >= m_retryMax){ + g_info << "ERROR: has retried this operation " << retryAttempt + << " times, failing!" << endl; + return NDBT_FAILED; + } + + pTrans = pNdb->startTransaction(); + if (pTrans == NULL) { + const NdbError err = pNdb->getNdbError(); + + if (err.status == NdbError::TemporaryError){ + ERR(err); + NdbSleep_MilliSleep(50); + retryAttempt++; + continue; + } + ERR(err); + return NDBT_FAILED; + } + + MicroSecondTimer timer_start; + MicroSecondTimer timer_stop; + bool timer_active = + m_stats_latency != 0 && + r >= batch && // first batch is "warmup" + r + batch != records; // last batch is usually partial + + if (timer_active) + NdbTick_getMicroTimer(&timer_start); + + Vector lockHandles; + + NdbOperation::LockMode lmused; + if(pkReadRecordLockHandle(pNdb, lockHandles, r, batch, lm, &lmused) != NDBT_OK) + { + ERR(pTrans->getNdbError()); + closeTransaction(pNdb); + return NDBT_FAILED; + } + + check = pTrans->execute(NoCommit, AbortOnError); + + if( check == -1 ) { + const NdbError err = pTrans->getNdbError(); + + if (err.status == NdbError::TemporaryError){ + ERR(err); + closeTransaction(pNdb); + NdbSleep_MilliSleep(50); + retryAttempt++; + continue; + } + switch(err.code){ + case 626: // Tuple did not exist + g_info << r << ": " << err.code << " " << err.message << endl; + r++; + break; + + default: + ERR(err); + closeTransaction(pNdb); + return NDBT_FAILED; + } + } else { + /* Execute succeeded ok */ + for (int b=0; (bexecute(Commit, AbortOnError); + + if (check == -1 ) + { + const NdbError err = pTrans->getNdbError(); + + if (err.status == NdbError::TemporaryError){ + ERR(err); + closeTransaction(pNdb); + NdbSleep_MilliSleep(50); + retryAttempt++; + continue; + } + ERR(err); + closeTransaction(pNdb); + return NDBT_FAILED; + } + } + + closeTransaction(pNdb); + + if (timer_active) { + NdbTick_getMicroTimer(&timer_stop); + NDB_TICKS ticks = NdbTick_getMicrosPassed(timer_start, timer_stop); + m_stats_latency->addObservation((double)ticks); + } + } + deallocRows(); + g_info << reads << " records read" << endl; + return NDBT_OK; +} + int HugoTransactions::lockRecords(Ndb* pNdb, === modified file 'storage/ndb/test/src/NdbRestarter.cpp' --- a/storage/ndb/test/src/NdbRestarter.cpp 2009-08-11 08:10:20 +0000 +++ b/storage/ndb/test/src/NdbRestarter.cpp 2010-02-18 23:50:31 +0000 @@ -898,4 +898,77 @@ loop: return 0; } +int +NdbRestarter::getMasterNodeVersion(int& version) +{ + int masterNodeId = getMasterNodeId(); + if (masterNodeId != -1) + { + for(size_t i = 0; i < ndbNodes.size(); i++) + { + if (ndbNodes[i].node_id == masterNodeId) + { + version = ndbNodes[i].version; + return 0; + } + } + } + + g_err << "Could not find node info for master node id " + << masterNodeId << endl; + return -1; +} + +int +NdbRestarter::getNodeTypeVersionRange(ndb_mgm_node_type type, + int& minVer, + int& maxVer) +{ + if (!isConnected()) + return -1; + + if (getStatus() != 0) + return -1; + + Vector* nodeVec = NULL; + + switch (type) + { + case NDB_MGM_NODE_TYPE_API: + nodeVec = &apiNodes; + break; + case NDB_MGM_NODE_TYPE_NDB: + nodeVec = &ndbNodes; + break; + case NDB_MGM_NODE_TYPE_MGM: + nodeVec = &mgmNodes; + break; + default: + g_err << "Bad node type : " << type << endl; + return -1; + } + + if (nodeVec->size() == 0) + { + g_err << "No nodes of type " << type << " online" << endl; + return -1; + } + + minVer = 0; + maxVer = 0; + + for(size_t i = 0; i < nodeVec->size(); i++) + { + int nodeVer = (*nodeVec)[i].version; + if ((minVer == 0) || + (nodeVer < minVer)) + minVer = nodeVer; + + if (nodeVer > maxVer) + maxVer = nodeVer; + } + + return 0; +} + template class Vector; === modified file 'storage/ndb/tools/CMakeLists.txt' --- a/storage/ndb/tools/CMakeLists.txt 2010-01-04 00:00:52 +0000 +++ b/storage/ndb/tools/CMakeLists.txt 2010-02-18 10:45:20 +0000 @@ -56,6 +56,7 @@ SET_TARGET_PROPERTIES(ndb_config PROPERT # Build ndbinfo_sql and run it to create ndbinfo.sql ADD_EXECUTABLE(ndbinfo_sql ndbinfo_sql.cpp) +TARGET_LINK_LIBRARIES(ndbinfo_sql ndbclient) GET_TARGET_PROPERTY(NDBINFO_SQL_EXE ndbinfo_sql LOCATION) ADD_CUSTOM_COMMAND(OUTPUT ${PROJECT_SOURCE_DIR}/storage/ndb/tools/ndbinfo.sql COMMAND ${NDBINFO_SQL_EXE} ARGS > ndbinfo.sql === modified file 'storage/ndb/tools/desc.cpp' --- a/storage/ndb/tools/desc.cpp 2009-09-04 11:33:38 +0000 +++ b/storage/ndb/tools/desc.cpp 2010-02-18 16:37:48 +0000 @@ -33,6 +33,7 @@ int desc_hashmap(Ndb_cluster_connection static const char* _dbname = "TEST_DB"; static int _unqualified = 0; static int _partinfo = 0; +static int _blobinfo = 0; const char *load_default_groups[]= { "mysql_cluster",0 }; @@ -53,6 +54,9 @@ static struct my_option my_long_options[ { "retries", 'r', "Retry every second for # retries", (uchar**) &_retries, (uchar**) &_retries, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "blob-info", 'b', "Show information for hidden blob tables (requires -p)", + (uchar**) &_blobinfo, (uchar**) &_blobinfo, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -281,7 +285,24 @@ int desc_table(Ndb *myndb, char* name) ndbout << endl; if (_partinfo) + { print_part_info(myndb, pTab); + ndbout << endl; + if (_blobinfo) + { + int noOfAttributes = pTab->getNoOfColumns(); + for (int i = 0; i < noOfAttributes; i++) + { + const NdbDictionary::Column* column = pTab->getColumn(i); + if ((column->getType() == NdbDictionary::Column::Blob) || + (column->getType() == NdbDictionary::Column::Text)) + { + print_part_info(myndb, (NDBT_Table*) column->getBlobTable()); + ndbout << endl; + } + } + } + } return 1; } @@ -309,7 +330,12 @@ void print_part_info(Ndb* pNdb, NDBT_Tab { 0, 0, 0 } }; - ndbout << "-- Per partition info -- " << endl; + ndbout << "-- Per partition info"; + + if (_blobinfo && _partinfo) + ndbout << " for " << pTab->getName(); + + ndbout << " -- " << endl; const Uint32 codeWords= 1; Uint32 codeSpace[ codeWords ]; @@ -380,7 +406,6 @@ void print_part_info(Ndb* pNdb, NDBT_Tab printf("\n"); } } while(0); - pTrans->close(); } @@ -406,6 +431,5 @@ int desc_hashmap(Ndb_cluster_connection delete [] tmp; return 1; } - return 0; } === modified file 'storage/ndb/tools/restore/consumer_restore.cpp' --- a/storage/ndb/tools/restore/consumer_restore.cpp 2010-01-27 10:43:41 +0000 +++ b/storage/ndb/tools/restore/consumer_restore.cpp 2010-02-15 13:53:40 +0000 @@ -1483,7 +1483,7 @@ BackupRestore::endOfTables(){ return false; } - err << "Successfully created index `" << split_idx[3].c_str() + info << "Successfully created index `" << split_idx[3].c_str() << "` on `" << split[2].c_str() << "`" << endl; } else if (m_disable_indexes) --===============2046976603== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/msabaratnam@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: msabaratnam@stripped # target_branch: file:///export/home/tmp/maitrayi/mysql-src/mysql-5.1-\ # telco-7.0-mai-test/ # testament_sha1: 90a9717e3669c6f29af5a7293faa2922a34742a4 # timestamp: 2010-02-19 15:54:46 +0100 # source_branch: file:///export/home2/tmp/maitrayi/mysql-src/mysql-\ # 5.1-telco-7.0/ # base_revision_id: msabaratnam@stripped\ # o6u8b50uug0yhyap # # Begin bundle IyBCYXphYXIgcmV2aXNpb24gYnVuZGxlIHY0CiMKQlpoOTFBWSZTWbhjL+MAjHB/gH9/g0V///// /////v////5grv94723tDsi6d0+xz3a4WxQDenLBJVgpwegC9gORn119KPqgaPoHdc5PGDvb13bp r7fHw9R3BSbfLAB6Bxd99wTSegNPt18eLfYX193pj47bZgVSQ0C9z0+9vtZU3Da4bPq7O2r69BcX cdFLsMrtiAefcrn16110HcxQI97nu3q6zXfc94NBY+9veg0tVKsANj3vdds9Ve7u2AH2Xnada849 cFBPQ31vpqtLAPde3UT0enAO8J3y1z7e6KUJVAfWqNsWzIzvuU7zBEBR7YHQvcbju7r2aO1layyU bRb2AGlaLtz2wp07j3XcKOQEr2bzUHoBid7Z7u7Ts3egN01sV3YFN76hPe8l5YXfE4LvXDtN9nfa jkyB70BQGutW27tTq0tlrUCVppcw66VVVmZQqzaTN7vd6dO7nalrQrJlPY6k6q2ibTCZttTQSUHv b0XecHKO7097ZmxQarSjn0dd6TtoMV1ld94B3XrQbGbVjWlUA0zJldaqCqLkwdAxvvCUIEAAIAEA mg0NJlM0T1FPaExEGyRp6jyniTT1NGnlMNCZGQEgKeiYQTJqekaNNM1ABoaAAAA0AAAJTQIIgImh RoU/U9pMTKnpqbFA2moGgbUD1AGjQaAAAk0ohARohHoAJoaI8mip+hqeqZpig9NNJ+mogabU9Q09 TRiGnqCJQggCNDIAAQaAgZEwEyammmhNkYqaep5BNA9TeoFSiACaAIAmgBNBBNMpkGKnlDQ/SJ6E 9QwCP1AEZ0iT4FEj5xPmgfSxBNikG1CJAZSyDDLKxEDN/yPo98n96GoD/CfJs7/8LoGnJJWtUEP3 2iTPv+m45tHRRRjBnvaDFET6s9r9vLrwmxp+Ll+Lr4KnfX8WMdJrt1rqpyFFPeiA2oyTdJHkWjGc mSy/pLkaj2P7y+D6I3bj24j1PRengum9JiqIHm3qLenoWJFjCsyrewaJNrt38O2mtxnJtab7sbNn 8ckDz932fb3UxO0iqdF7TkJsTH+teroC9ulvJOESUGBZCwRFMwDhBIfB3Wcmf73/r53cuR/F3WaH ZldYZuGBVW7GDPyeM5lmZtY+Wbxvw7yZcDTNADfi7JAqTS7ms3+Lx+bz7pJ5AqqvJM/9SX8T/829 m/88dht6z/Th/Or+h4fz/qqsdhT4QgjOZ3+kaJrSg/1FnFk8zcu8bRV3MtbL/QYJuDKmsyP6YRxh mS2lOX9XWLVqOwkajSE54GB/SKryKSA7dNA2BMcqYW7CA1dbK3qHD71XyPaVmogwvVxXVy1Vb8du xi53PvO8V0dUqhwh6mmxOGvvZhOoSEX+M+pfSj5cfJjUdIolKWIjIm+l/f/X9PujuNYe/38OmOrS 7pxQX6GQN4wqHlOFDdu97cmuhUD67Ts4uLHCA1Go6JmjL5eZIkTvVu70R4p/57pDOFpCrMrSk9U5 eoIhJ765Ih3dmeYSA5EWHqPO+GwbwawN9aCdjkpxDJ8QwaEE+/PhtybHnv1mdo4oQSHNIqowd3X8 /9f7vvnc+2zr1fkaVuYLATRmhJxrmhIOfuf2o3IGCCJYSoYl7yFy5ZMKB6EnjHGTr8VMFOJjAnjZ SXGgYcnLHlx685D/hnhht/hZLBDn/VsamYS8bNMh2J3lUeJAVAbz92/eQgk3n+xrbLbB8qz6DnOq ZKoMVKsyHeIM/wzRKod/ZzaaBU9EBz9gfpPq4azt+RPpGlVlRRSDyAdIjnNOQWCQCmDXx7m6vb5/ X77+FbqrBCpRFUSnc4/dyndbH0PaUJz0pqjZGPDtmddNzlv6b+Kp5Uwz5y7vu6cbg0wGqVJQbRL7 QbI1aUs95Qu3W2LfSHTW1iGyfiHodnNJoTSmM03fFFHKfFkQyqVUCEglzFJDuoh0Rf1SRPzqFh7g Pd+eYRpDpIdN4TDhGY/MgI8O7GuSOESmIock0wbzrwZ4OrMHSfChPak6DWG41hxZBUVBURZ/DxeP 7fFv7u7lfL19WPmNvDmdXLt2N78sH/wBce8hR06jQxsAaGfzxEgYsv7YaVpVKjJKAnYSfhoqW4c5 UtCnlQKGbiNW/jKuiSSuTHvPxVAPLsUZJKUPOomAClKAW2QkZIAYopAQKDiVar9PF2duTJ9OW6u7 KYXlKeEyZOfNdfsV8VNZKw9RmM1y2ucSaxCgnjiLyGeBaoUSwzzT51riMNq9bfMRBAjE7dSVqrtI RJGEXdwtPSrNVdPnENgOdnGKhjKZsd2fDBx0DvEEaf73nzZZysYSYozP0AuKys0JUxAdg5DlBycY XggGeIbJriFYVimyGWK5yFoHfdXLUgVJorhk7yQNMXPOzRJU3jGcQQgpNa0rTD5dgwgtSsoyicTM sx6oMpsraLQCh2JQxhGEMGUzD6p9LCy83GsVcJZsesxjGn2sCIW4pydFPiUxtkbQAE+TcbObeG+x iZCssu7QOGZJpGGMNZqVCdLRK2TAQ/CE2EI5is4TRCzBuI0SOFFTKfet6l6mXKIHlqMUVGJrQ8gk wkCREmc6mQVFQErLmoIU4KuoxE5FjOMstStXywzCG1JQmE+9J5IW6T6aYm6fGN5jNZEqU09UVjeC saqszNbxN1paMZNbp5je2izWNOSVOKzettqdwoWHeeW0TS0uLGfLpXVvuUtu+KohJNhGX6c4S6Oc QtrOxn06V1b8Slt3xVEJJsIy/oH6Jq2Nfl3BXudmf5n8h59mM8VOtA2xLRpjwCqqYEBw/KtU9MPr +TR7NH+dW2Xsm+R/PwcpGe5vz9by0Ds7+yHsYKPDw93r7LJ7fTS+T53eepUAHzPO75v2qBFQAfdA QoFpuoUUJAUU6/0ogCF8ZFS0QPjloA6AgE3wGAaiBYJEe5opJ5aB6j0ancZIefagskF0QArJA6DZ fjMAGEnkh5aKgeFqInoIgUhjAAoQQS3LsXki/H8sEc8Pv3vXq6By2fuD4p+5F7qxkiKkVAYqNjqV CcQTYb/kNxQ/ze7vNdvqnCh3KTngUKhksyoHUOG7DxY2HeNnSwMoMuNAMjrnCbESLDv4pCFjY/Ya fe8thmod6/xVVgq7JurfCAtywtdmz4E/3HshTeULVjpSvJjst5uWMHW9nJEnVJdhH6oz5N6sTqch Z1KrB4MckWcrN4+w1KSIcAcf3qZchJ/8cNDIUxZ2how7qpTfNOrR9fIZzDQZP091g7BuHpz4B6fk o++fpHxg2JvTKmfRSqLjnFJ2GQTNQRl+H8P4M7KsZBIqdWRadkI9Lz4MjmYT8bN0+43ILA280mXu o7MKSl8l4+6H4ltPzZZUMT40GW8/MLUtNBAkNBmOyMIM7XzkH4ZPxa+wuy1DXRD/6fh+J65gjuH5 8T5CKZCXbec7xvMPo86RbeEzvWrAhn6qZLaQETj7jp16UVPlRDRBZBCQkUhSSCKqMiAiIjGIIsWL BFVVQFEYCiMWDEGJIKRRVGJFIDFIMBiCxRQFYwUixYKoqyCMERQkiwBURFVUWd2TmMCjIUUh28zn lawrSiEYAdgip+XLQA92/n6b4faYVuwF5f5fk7CHCAHakYWAiMkUFEkYsVWAqiCoIIxIcz7fj7Pd 3zQ48ufF9/LCdH8v4g+jHqRGlLp4JTprVr7rfTvlaVpq1Ue6JgafeE84znBy8XOuU43A0THKKl6U O5fLmImSs50+zVQ7y5OHKw9IxT0mMJ9xmcmU4aFpXb4Uo3t79/GInOnxFmZLfitlQrTrKbhYzjGa ZssyNpkUPtHHbgAkw5xxPO4e98RMltkRUe0nHjwD2zcaDA/QEVVyY2dBkHKSyEzQ9IgqnHT34clO nnAooeVCWq8RlVOsXmyXzBSKh3t9J41h6Iea0zNbmiHGZkCVOxYQ5pGJxCpU2pkyhOaIxqcJpWk7 1DYp07hhFwOEIeIhod5WVKy7zdqHROagnTlzojEuTRWcmh7Defj+JoZiNc41W76WqB8GwarfmHan KIq3DVdCCDoQoeeI2ikbcgg0+q3Sy8JnWKfdZg+zck62+41U7sXLbw7amZd7EkSZ55TkhWn4dy8l mcZvL5jSUxGsFoFxOWHPhyB8Pnc4x7k6M8u77jqiVC7W8q+3RR2SWKHbOiCq06eDjt6fQgNHqYUq 1kXv1TR7A5g0TRyCgjUsRkirlovet8WpfK70LZcqqo5Rs9Q5eu4qvau597dF12d8SaQWI8IeU+/D 1LmFdubncPLgsrNcXoxGXiYeHdiqUmVaNptLEjmKHJ2OVOYSxLkqbzCiNS9PdvG21Kziacu8zMrD 7WpH1GYa6KiVtQpNKiB6VkBCIl2qMkDidZl6d2lSpRQsunpQhEjs7KIfSqrap0qWlhUh8DmHsgMo ClKw47U+2xmp3uG2p3iITEu6zUwW8RQ6HVocS/H3Pd+08/PNc/X8HBz+d37gqSl2xNETvwQo0aFq w+aGlzgNRLKZwBnD3OMaGcEJU1EKwzqeH2/oH+ptb0E/Qhdo5E1bE/R6Q6+vuwyi6h46Dzicc1HT oW5GPtv+BH+G7ZsfrH1DHy5yfqKKOqKKiCMegj9BBxhj5Q1BIScN+vMnDuTo6Q57+F1R1XRTwc6t VFBUpGUrfY9Roq90lhq8z1Fvp3un2S+Snr4n1bTDH7K32qqloCOKLsLfeLQWslT/NR+nUTYZaicy Pun0pBu/y/wKSHI8p0cecPu/Yota3b78e/kr/h9b8N/x1S1cN1mwV5apf1azv8Xo2uZ0MKqHViBZ VMsnPROZ9hYcDVPMXcm88wh+Q2aGTulU3Ch/gTO5cCZBEod3aDdbidLnjBu+hS2C5NUjJrEuSYh4 JQ7dgdPPiV035OLer/xC93+IPlr6pmy09sVMyEGqlkVHKHv5faannsw3AJMEOoYGYRkVhupmakr0 wo65goEV8tHN99vqwbZ3snBqJnHN5TuFLkQ6+n0FdPJwHIfZ9mPYEdw8i48R6IMicG9wZ1TQcxwY K4GXmTTx+V/6Zhsw2ZHUWfM6Ynryx8q8+sZi1h4fMJg6gu6Kt7JL2MI9TK2CId6oigYmXroCDk61 uKOEBPMnIaT+CzLtock4TClPMcO/GfM6dDsJjt+NdbyXYz1q9V1JDIn9rohPOWcZjeKOYQGjn8rC D3x48ez6+tVtfZOmyD33jSZ6tad9URypzVtFbZlprpdEj863Fax8l8vZMfGifVF/eqsunyLMhkxv k7oEl3puKScse1Tn29jBRodnRYuyl2yWIqaxq1bHDVe2MrTg9wT+p0nLK5j6DzAR33cZrB9wn1yH fquxdpMXcp7OVMVXgKopPBT8+vccTYeJHvmOOCCINhu6I7g62PL0Rxs/B8bSFy21W2bX1QcuIsLg 2im3FGgdONMG79aISMgUzRC/UTtgrqoQgxhE78+LkGCZq7WcjelfYauv2k5K2/PZsn7HuMU+MKLO iIgRqNVrYTWhIrnoIqeqXoCogQPLB3/DqFo3vsnYw8Kecoch+Zbfpa5+Hb05ePdQmbCt8CIpAQzE UW675KevjCko+29ZnDly34VHFwfCkpmmUoxFd0cRhepVLr2s/Y0q2I2iCIVu+neSMtq681fYqWFH lBx+a0MXFNgoL4SZ617eHyrgtmw+ttmOJUa/qQ0KQUVSge9BB8PA1aDMQhlQqR65dfRdSL8vw4bu eHxjTc/XRB315w4fYePdv5dHlgKKgDEx9x8sDdK6YnQRCHDRpL2r1PKp1xd2kWZH6vfvjV2Vul4r 2Ebjr74JLfw3v2nDHia4OO6jamuflIlarwU+S+lTp3ns3ScK8nf70l1Zro+Pr8tJSIMMyqKu1ydb 2gQ5ZvIG3m0HxTrm+m5+UvhNhiRSUp/cQnjBZZu+Dp8b5/Lfs5eW9qv0OcAsGUVRVPbtdTuwtMej 3FpK5qWguXbVF8XVOdNn0KYdbdhrUUGspvsz3XFI4U2DYIezaBiYNUnPxVJLAeynR/UeKNIxucLc 8TuREHcikRTXfr4m+lUPZ2ZS00cl5Q4CGYyGU15FgTx4uazaQpXd4GGA/sNCHHZOmR1R4nMxLwcE lf00jt38PBlCKviJIR+UR8NH2xn3Lwvbdck/T8Qiuir2FCUmD8JEQXGvv/GvS3jgc86fXGLmVh+C G+z9B08Tb16HeSxt1W7FooU+Y/LjqZFEYUR1ySdVoYggJU7jpZ7qU6jXLulgfbS7PqaBIG3w6cIV eyueyjtzaexoiKpRsNSGExhjVC+Kn0zXup701ZXv+zZcleh0hEN3fdNzYcwx2+pthQ5TlCOub8Mz V2Bgb5ISEyFFFFFGCMRREURERRRRRRRiIiiiiiiiIooooiMRREURFFEEUU8Rtv9HCdIKlcAdkocC /k53gzKKrKlGcnF2GGGBbHlHvpg5rQfcxPwd8xsJ4imF1fuZDAVUciYWln1WWqG0VCruf58Jo6iG 13Xq3Oc1j6Z46NiiGIlcNK+FVuUUswGHEhvRUEh59ZCLF6n23dhCmR14Z04fgD8HfmIgCZVXo1Sm 4UbVW4ca1Vn6NeJdEuXWyjryc6xLFkm+csndSZrS4Bw05aosqqE8uyQcxT5PsIQlOwq7XYXDdNdX DbJOHCCKZK5h9p2FtULfue3ibJMt/FbR4WNl90Jth8FhrK2gPb+5zKKO8Oy/1r8+h7prV2zyN2mT rl43ZLcQmg+aieVJHlD9eKPokxoVX9H5zTYla3GOPwqx9wh2VXt83/mvJlUnsWH1igOQmLLXsvDv B+PTbtmKErvangacS9GCDKPVGfK3uDVpMYv1PMcRGacn2Foy0DQIDtIpaF9WiTo56NUT74AVO/Xh YF+7/SBn7T3bhY9tEfD++Bku3m5yHm5itfWo36kxFFQVBTq9nqc9WTqIF/D+v+BfsV1dxDzmc4zE Z/ZJeVnVacvUmqiHJTOJReg33fF3ozdxrq7u7ZpbvXGUr/defbR3fsl+zT0+vK6iCrU+yWuFFuvb t1ZyYZ+VdWxvjCNOELFXHc6+uyEtnp4ov9rJmeP4+wwsf9Sreo/1Imntofx8/31H45Sh8qKeKKb/ GiIekwiHd4dick28zcYintRyfEKz0lFe7b46z7BUPEtfDZlprx5T4yG82cj7/76ebHV+HdZ4Q7Py E/R+k+FqE23VIyAkiEg7kLQTDv28m/KV5TlN3pt73kxnNTGNO/1X8Pf48bnp4xPitWtqKxej5MMs 8jv3zqRSu0dTQ1RSa+be+14vlZ41dXsetXyPB9Lo/A+54PqV5O50dnqdleDya8XLh2csHg+h2Msn g0O5+G3PFe7npvL0R373ofZXtbxjsHc6c6dJhRFtj8w1XtWd374Xf377DEcDrZGnKUpw8t8sjmu1 a5uljnOQcXnaanv6+AXj1l29k+/k/Bpbn7IqXddu+xxV1Od696BMpm86oHxl1GsUzS4rN7NfIaum PGZnQXzmaoR1tTRdZyt2OfsNLdlmrZq45w3wyxeu7hC7jOsKcIcNdmzjs+4+/avd287ySXVvTBnQ 1YTObT5CfWZLE0Vmg3CPI8t6H6GZA9LMnUeHo7kYVPd2fhPXCSkY8g/ssXhHQr8/y1P99oecvxFv 3FZZZb4HcJ9Y6pEZHA4GpS8NQogCINIVP2qP58vZz9jpu+Pjr74rbL1eXp8vLV5WT+ymueFFVuuz yj69FebD1evhqil6Kcxyk/lSiEipA9cOerQIWtCW2SJGBUGgoNzjAiGUyMZin5QtEBTBCUYQRhIV gQqCkiwQQjBgUSQpWFJIBVYQYkALEbQISKAsjafwA/MCESH0oftf7EjvsMobIKBnFJnOMSWlMMGs SsLo1l/5IdlmSMY/fLIl1p/FE/rUcsD61Sch6sAjCk4pVSYVkpblMMKyYIxkTeP6fuDJgyalFlEj glj99kmIGidAUokodaFkX9r96//sE7YpSKUhXKBcKmT/t/3qFmT5wy/JQ5bvYX0X84av8/H7cjd+ 4+P53WDT7P+cjrqh5zDfERNqj5IH5HWPFEWDNVSf8pTMMoCYAvAD7Ow6zcHBn/w/cg/2al/9qnNa KnTDpIITJFoN/Nxyj0ZxtopBNT6RdEw44hJMiU0QO1/Ocwzh2Raoyi8DkzDn9NTnGI12C3QqPSfr kxT8+oeaRBQNMTIdPBOzwWhL4RHPjqZlRFpZDQU0Tk2ufWURSiKOYVigZjVX0mZ2bcdTVJcUMqI/ Qe+CgqEKQ4VxHGC1pr/wW4UZ9gt9aCVE7PULFwC2516n9gqTLmn3lufQKopWJZM79AnJkrFTmdEp Gv1uICCiojVFTnLjkz5MkxOTjx6VqdRiJPnyoihWLySgcxTB8PaolosAJ5oi3LDFU0NGIOGyioxB UHTpvHGYqZChY5qNyFQCKoXgyG7XayoXXMSDzShEyvNKhXzrOpkvvFDIdnqV9PBj5aixf0lDVqL2 sjf3J3p83nwPd/JT9sy/par9s3+E/uze5ZS5PD7/CMFev4mTuV/uhXqfNBekTygjC+vYrp1fH1mv P8qmpdW2t1aSylpQM9XSk9MK7C9c+x71eqX4ZZ4PdReTzE+pnqK9/p9F2ZfpmM+L27bLa6VVanX8 7ysoHpP3pw7Mp+7bV9u2HnU+KUNVNDQN4T1ElmbJ5jHrrd3jGUH2zmOM6ml0BcVfJ/x5VX7RmjTi 65dcYOdf+rS1yZLRl75/8fyeyKvVkRRPhhlse/964O3tN6O/O4KKb+tTctjreuvd2+MxzVD8gbqP L0DoBOSRip2ajhVChrZUfrcieAA5E6rrS9wUnThiUdjl3xfA4Dk8P1ezPTP0WkyOpalRlWlhl0Ya c6mML53BEg9HWRhHWYRSeDKpz0v1WwR33YO3z7I5KOGtxW+eL/iUIZ0fsx+uL69hNnrt9ttlul0T CIbPcj2rjmSD5OJ0Dum+c6Od0+BdBX1o4iSCYmN/3fuvhjtQL2/v5/HjrD/IeP25IVdTxE+PVCPm DoCDzkzR9AYHjMNNWSd0/ueWX6viiE8R6uHxvKA+dcHUV263LcigpXVVc8pQu3Z5kW63WXnvkB/I Plnbafz/0MMKg4aVUjOh0kOONXQ1/LieSJ/qig7FKd0jlOtMbm8sVvb9BuNLpilG6kH5GGTtaGef 3MHYkEiuVOsXNTYTVE3Vr0YIJMINHgcPeTOTam4UPrwfKzpzu27X6Tz8TKE18V8PbRfROYYem+qZ uw9PfZh5szqCQon2k7ijS4gKB+UkXGhlW/HtcFZIT9Y23QtInoZJ3kx5n3mpY2mgvyUlVSiFyJqH sBv4S13lKwyxpsgv0n9z5siNZOWDoWbotImLGNJTwbllsV5bXWOyNQ2IlVaubumZ+DnGHC6MyyiQ 50OD4BRAgJl7od33viJGCh8lGjqY5omZwiJ5VzLyvp6PouJStCoHzl52IU5hQsmdYC+kpWA7Po+K Qn2UJa9lSebkns+UyBjiTuAsUV/yI1giC3BcQ6hGqApEIoaTcHEUNhyc6zbwFrhLvJaG+kMRYXQf 6m/h4IrCerB/xJHCUHU5RM80LU13l0vhQYrWCFUcYaqxMfdPJd6d3g9Hy6np9Dju8CP+UOLGIQi7 Zif1ovISQfhQDsVYVMA19rf8LMXkj6I849/7MpzPKfyejvh4vBdJFhRraYdMBdDOAs04zKC1Cb6G LM+9iRKxoidUwSWGHvuJznv+VeD3GMB7pCxgkz1UOyPSLx7TqkxJwjEtkTE5IscXMskxZVvTRG6a FVknQ0XTBFnWMd7EXyW8C7hC/e0SFBik3Min2nPmcC2JgiZGnjEjik6d+0kZ2msNy51a1C80GGgv 70NWFyu8LwK3onPN7RMob654TdvkJamS2QveFp2ob/U5nh/zWycjzcDxm/oTejec/rFsh0840cpj EtU5nRPseNx4Pg7H0knkbdTzMpmSGG6eyKVcT/6fodJnG9fKL91beMZCiktIHA1eJUOCccV2gB1b UG1KWwu5bdNsA+GYzgqmCIYZJwzcLLyTE3+GLzNqcxXCunjP4FsYejfd70psmIlRFdnhur9BJCHj k3Tlu9wwPR8Zy9QisGMgqiIsPY0ZFjEGIEigCRAgRJBgEBCACEIwEh4E3fO5VUZqmS7h6ocTvHp4 Lv1phXoYGZcUJRLVGihmjAtMyqpiMRoaFTQvtLbVZfR0u1wTXJxn0ZZUmNJcXJcXr1xeod4OjXh0 qiS+XvjC/VgO+MCw1Yl6yQgaG0UOuQlvDtuuEsoXv29rox0YtBxUz0KT4friL9acge85/sYe/9tK VogKDwY/y/EyAgh8/o3yU8/ma+3gMzIMzMzaZ9ovafVdttgLaB6jGMQLbbYW22yW22hbbbbS2ltt sC2+HFmlyuC2hbQtVVpbtP2wkMYzbbbbytxLbbbbbbaW22222222whr54TQpv9JukgBlhIez8Hx6 +C+HX14+zH3d/+NNUJo3+Ps9017rnC33qqqq3szLTW5ZKq7p+lVMZ1TwA6CqxKGcYMwj1I0kvHrC fn4AlIi6ABxiXGcQA+pV5YfUfVBkgzt73JuMDce0lGJJHe34U8W5gtDr3p1BOJp3y1TBMfpa325r Kb08MzMzFKSBxYob9KHByzgkk3sNGQ2Q0ZKkLoN0MscsRxxo2gjgrFkckQtAckUKyTchxeDlCTCT DIb0M4sCbnZnBJiMBiSG5IcEKk0zZA1SbOAGGFcoNpghwdBy6E2GaDF4h9S4/U6988fueLLuISz+ fWXLxePB0Hma/TpCYSZgOwB/IkzJv1M215rweHerlDNimZIGQIDyWMfylmQQw3UmSS9baVkpKomV tt1zC+bbt7epRqgYY41jlQppx6UhG7GIukogVvkxOhWK0gL4UWE97thC2qQqtSYSJMrl2MksLlQi CqH1kwEykogBnoJiILUhyUROzTlgcA0G3Jlm0SDsw2HOCCUMPuvbmql1meLLOud2dFFqLYSqBIqk G4UI5iq3KGQpQTOEULm9wRaYECMuAN8OTEaxRZ8xopgMGmSUdRzZiugYOpDdCgHHWw6GBz0y1M07 FeEzM+Wai6oZvD/rqTuUiJIZDDc4qtEXd2y2aGrBgquYtdea5s5P9En9sT2ROjPfXkqrlwzs3lqL Vb16TCFIRfJGF/JbTFG5Z3LlZMWxVGj+RUa3rrGaMmSzmpO9o0WpskZQUYOjv0UqyWmTJ5QbZbZ2 OFL1G6t0XQFuzcsiSSxuUd2rLIRMb2dbKrTQ3yJciIo5FfJR1MBJ5OpJ4HGck/Lbl4vg7qYqKt3z XB4zcuXLlIXMlGMjmrJzUwmFzOaqLhAGZlkhrHOTuZNlnGr2JbdRoApmGg5OSrMZqqqEyiTBZcxZ Z0zxaMDizastzDc3uSxstXsFz6pG+NrsWdvBY1oVvNjoI6A4+KEcm9mhzI4dhuDHfnglKW4oAwBZ TM7AaIHHpyEt0wHcyaCkDA0zhopeVbmDcZMF0LW6zXQyjpbVeZMyYtm9k1bksePjxYTjlRSxXjWz jdJosWwtoim0lZJrhevRUasLi9ikZNm9oYEkuztWKs2bdusLtVWDFi0WpzcFVkf9tIIX+ZH+MJFO sAhm4mQH3dgubYThOIzm8cIaQ6FXJemS50d7wZtFjq3MWWOFNHguYQlq69oqxar3czZMWa+S9msY Lk+w8fHRs1VZsXBsvWNVyhsuVYqLHZgo5rIzb2isuXsnFaxZMWixcxYqNVxc5Mnp8GDRdkWz1lH4 wxswbmi04LGjU4uKh3WNGQdzuUL1XQ3LHNyXrTczZMCp9Mkc5J+Wykm9y6+/1Aw1JtR9CjhwGTeF 4BbsyDs2h46au1DihZp4Igjj1hIxD+vJBO0558jisMrheG0fwf/AfupqAbCGG/vIMnLjAB8LxRVH KAOlOPSjFaKcp2akkmV3fW8hQSgtS+Toztpf4jRvWiTicrzGvu7jxmIEnN58N5gUo8OdxaaYujnW evTMPbDEYcCLmpxl1OTvGa74eMPaGtC27GE1w7JNhSh0DXUanCCM6IYhAkN9tnawNRXEYxTebNuI Zf1vW8XaK3jbOJCvAbg+eBkRihgeeXRzIZCRdapebyGgWJZGFyD6FC4Yphq8tjtVsNec3FLQPXp4 AppEd2bnHrtgCRywvgNy/Wl6QsldZ9r7MF6z9pMFezdMGGAtxBQqSy2EvAzFb241FwjYw14uskvi aVqpmvZLJ2X2rUShotxO9kyYMomntvxDtPiOyH4B8Y7egNx33o5c5cYcZ98neWGksC2GnImcYUBB JXY5cg6neb9fN7ycJEN7Uc+GSmCPBXAqpjODEulq2JKcUitsMMTIwJpF6m5IYwywRbVw/ZgA5PRi Q8KlFqrm3NdtzwojTEp0NuGGllUUzqxOEG9raxMzlZIUly7DFzWctlr+y/UMzTk24GxyVQcwQWaz KWMihkUimcwbrI4IoqJAQoUMVQ0YJJkSSkKqCE9r8rJuxXlGF5cJHveLixWfMiikrKdmWx5sp5jf E5Xhp3Na4ywrp52yq0Fk1fV76REaLmKVlDrmmb2S9mnrF5mb6rRUW4e9RekU1dGzqJytS4rO6mQI hxLkZFYAxAmKjgk4bjm4VlU5UspFK4bG2nTszOmMkZ2b2zKWFxmJqL0CQhhdGQ0IFDNRXQWMFcGw zo3ulkTiIwssiZw3tzZhN11qkxlEXqzsK2XU4cODsdBBo9DQPcgsQ42H47rYLvPQIEAw0SwDB0Bq jvgW427MGrIvCcvSxUggo2MdpbNibR3LGgzkcOPcSX94xG8nYc6HYPYtgruMyKKKPx446s+8vCGT v312nGGCLmJnbsl8bCli9a0m9VcoCZYijfCTNJaXeWONIukMsAoxjNcuiyuUnLFVgts0Lzoubr93 9X8GVIa9mKybmLGmkhzbmyjURwvEQlYlSitc5B8z35v8ohkhVIYQwJlJVZGPCFJcl7SqS23xx0ZU J0b1V5iZLHFtpLAYrGocjTLIc5wRbUZETmiek3GMkoW1nMUvZWjxMbBl2E0FlsNZLnCAaY9xAYKM GpDtxpiS5ZaZS+k1UcMe5swblW44snnDScNTKjZXfZddc0GnW52F1CuSSOFEIuogpBQ3xIItiKEg lWAjiZl3t/ApQvGbociKIYHOd4nI9Y15L6H2wN4IOp1ODRRYq8kmkl1Buom/ffmSWu5ohtjbVKwH aRjJttgYx1LYk9OpRbe4yMTECOTA9sywSFizNizWF9Ipy8bNlzVHV5o68yJs0Rdxqu4Age4mVYfS Aado6iFPCbHkO+WKLWy9zdGLK2lGR0f1SGbhJdf2dxYaNxRRxWTDzWOJpKqkiARIGvXeRKS02mB5 IlTlL3BvcFW9am9kTetZN++1iwVauD8ockkNeSnRqybFji22pToxZOLc4OBc+8hviaObxdHVwxc1 HNVouYs5JEm9el7FeqvYNy9k4LXZazNnSH6DOH6pP2nnElsSbHCm6H7uOaOD9uKJ6HJJkkeHPtej uhjBFJi8sPJCnnMPse2bP3ZuFTY6KTCY1oyPUCbXKiqfbkKuHPMuUpjDBN0xwrw84Zojwik+MflL DhkkLOG02McXxwuE5T6i9rWiHiLtoxVVgHsyZzbZxUzMi+1mY1lhMwcCGbWrH00Hum4KiAmekW3V WLUIY4loo9niK5zke4eKW4ECshREhDmA7iGkkoG+umem+pOlNZN2SjFJMrWVLz5Rh9ycpAv5KoSa qJyX1gUUQUy+uFskSIzgt3bQXMJZktUb9kdUX44OGKrgryVqvVyCtyiuBPhmzZuhR3OT8h9IzVvx 46C6z4rhgkJTXDIRgQxIVLaGy2DcHdt3dbMecnF/LdqRu0WayEjpvKwv33LIliglhYZG9VbIRHFQ krFy9m/ekpys9669Y7Xd2+/BmjlM7YOWltwFkvxzoR1Oh6kbblHQoaXg4NnETBoICy9axWsFP7of k7E2+2W9TRo3KOir63qPxaXNzZRjws6nK3lruMMWMSYL2AXu54t60xpmP7JjzJBB0Abb8YB+WZiE Do9jqa6lUW6R42R6onC0q2SxVBzUkhEoS1GAiWhCFY8Xi9t5erYTmoSX0WUHRREvR0uZQlLUUolK yoqpJm6NptnhmuY9uSvZekrwr2bd/F80cnNgo4pObRSlrpXndZWnFHPLrizYKpJWiKpTBxXZ6LWe /Z3q9smbfSfuEqaacG7a0PWz4E7MCOgjnwyrXRA/Nd+MMwbwMzcx8BvYljWRzhtkg4xZOih2CaTe Pb6y7wWDOmGmzo4LbHYrgwrN6k1WbnFycXZszZrZK9W7W0Ho7RHMko+8VIB2ZgzBjBAYPVyRie7k rOY0dL0OrHaPYazmMnaMJwOFko5HHYWUZLF6xybmzNq3Kt5vZff2fm6rnDBWijk6O5B4Adq8HYc6 Gn6i6iMG2dkCsGUJeR8I2JvIvQQErAmKQ3QLOh1IPU45rEwSpK1HTLBizsUeDLthMI9TjqihAuTR slj4yThaZMIb3Vstat0kkjPnWVnH5/pPW5gyYuDq2dZE2WsHYxYLG9nFro+6rNY6pt4GGxNy5Vs3 LjcvZMei5e3tzcdV7NVgsUXLx4lozUYMnVYov230UpNDVvZLlF7cvWrV7BYqoqvfg5pgpa3s2TVu X9/pVwUZKMVWpffucHNhHvSGO5QzVYLxllqzP0afqKHxk0fq++qbe9xXI5YHX4v1eSR9TST5o8ZL HqrE9Ds0h1bn7R8D17Iwi+Ot6h8urjDkF3HAMEe85b8gtFiSgvHwCPKrmAMijuNaY4dG8tg8N3Pu Js0YdkLdyMwpvnkO/XChigwCF9XPAujiSyxB0ikhIG4EhOHzSbHTajNSq1rUNFfZe9mY3p30Mi7a dyO4YiuA3dSanWM8CiyXhDZxBWTQrkT3RN22LbAcIHYMjRQPS2i1nWeU+61AHMhXXaqqzfwJm4cK j3SA7gvUcYTMt7f1TIPNWzELW0B3njpn14+6uSTHCsL/Aqqy2hKRJesqwjaDGRLVkvoiy59r+5YH RXdTZkzfpo3JCxIya4MMVNCAUjhxYPFIDBr4J6yqmsIsFzwEseuivtQGrEtc2PK7f4a8uWUmKwzL lMVKKbPmkU8xLNjQa1O8zBpM+OE87Sl3+FkE/1pRDYYI3HXI2Z53IcXSrHG7JSxRvRj03mrhowWN Wq8E2+qNFZtLy4OlxShSqa01qrmJ0RnoBXaKyXKa4KVDw37mlHXcXLhNTq4MHNoXOzzeYxyclK+5 2OxCO3VsdwgWAbDM3wKIc9CopqMVUmblUpwfrElttLaxL1zmdyre6OzRabTyR1QwyjoxNUKFtAAU IhKQm+XwuE1GF9cKSRxYODpldkooZO/IlguScV79UfRuw5M3Rhk+DuY4jRS9fR6bqtG3pg8VF6jJ 2tdHC/ZhNlym1Zz1kFYwdz46Ldxn4k1J4Yrd2aOXVa6aX3t/BizyZs2rFctZlHlO8eExMNMuhajJ Izpa23XONy9uMCZLuObuZde5sxayyceExcQeUW2lNLykoMS82mIJfSlbXXKmwfzLdkYvv1gkYrV1 y3k4ltmRggoPJ7rg0ZEQbPR+B+B0WYGc7mCTyeTko6dl4OjqOEjiUgoarblm5heq3NWLJuUhVnss ZLO1Gbhf0wdWm45LVWzJeuXpfCT+xqnCk/dMcFGCnFVwZrrHNzUanZ1YODM7k0YPYo7mCTy5J1Oh J6+uDkwWMi7uyNHvNhyN5NFpM1Tg4qtlz9ov5NW/f3Lt5o4Kvkjg6uK5wVODi2fg6nHnorX0jjT3 M17J3Ji3O5m4OTi4qLOU/ODaLejqYNnJmv4tWLqq5OSw4JqyWOTu7tVzVFzoHI950k+O6yH7p5Hw dHmfsZbpWzZJs9Gcc3w8NjhJV6Rl4Jt1LZk/SQ/IPaTvTii5HugsM3rrPX3YKb77uOp4Nj6TCPxO 2yHwnTU/pL5e0nh97niGwFppexRboHMvauc2nIRqY0xhU040+tbJes70Ykqp270taqCINFRnG5wX jczvNOpKmAzeUhIUDwApTdqta4IgSkZELNfnTHVS4KqwmGFTKJmS5KBEAINVgVYGbC3fUxrhfTS7 bIlcf4GNskpMsCxlvukbLIueq9g+eAibSzCxXJVFnwfBa9zLCaCJSUvw6LIIeiFBoYk4UlI8PaIc ayGbaWVgQHMg5zr6ytyzTiaTYFQt5AsiAoIMLZAYs9LArctRrfidQDAaESqSrnorkok2UJMnBuZN nxh367mWdY5eG+Zju4HwwJeDBR6SNHSYPTiMEnUQYKPKxI3MMaRFFjO9UaKXOT1WmjU+EfOTk2Tx 1du4vd0KfrR3m6VsDe0HQRPgpI2II9JfiSIRCkqHBMmhWchIjzAgdgmswuoSpcNTUqvmxyxrGLHB qKVsxC8l+8iep3PeOOUeh4aLnOJOFldG/VbbfIli1JSZ72+1VYtOTgwRKr4XOvpWZcpMGSrJwXnJ s1VYSqnJznLycgOPaYhVK+3GxicZZ6bsnXhBByPvJDybI0o0sLF1kkyStX8NKtWzmbnJ6Rzbr21d d7esqzNAlZzJera41wJXuHC1oHcQECDweDiJKOPeAQ8iSeqHZ3Ytpn5b9SIztPZT0p2o87PDGQ6q mL76BmsJzQrApJ9rxja+LoKbQSvQnkcTZtCjaUEREsKBleYIevFe5joryk4hSVChAvIHVzKOh7jq cZ8N64YNiRx4UDNPzlE1o66xzYxuC35L+rC/NXZmq1cWDNg6nweDVyRfCpbBDY/LVlzdFdyaKqPy RR1atnVzWsFzRs0Yqt65e1e/PGyUrzUUZNzQzNXRRFxNi9mtZNk0cGKWL2K4zZsVixayYNG8eaPy RssLn6WNTgtWKGTesZqLXye42E5xiYDycrBGOnSwyMyJv6u+vcVFYxsMjM2Bo4uPHeStb3A+SL+i jJsvqpjjmvJ5KNzvdVyxxaL2q9xYsGTszXOL7Hz8oT5ndj0k1PJiHc9dro+j3fSs5ql+9FA7Phwk D3uyPqrrdGD1PcaxPj6RJmyHmfhb5otfpMekmLR5RuufiOBuSW80eyPijcbj3kvRqbRypxa8qoKm psjyYTTxZTOp1RUOTJ71GZnlEgxMFvNO+6hglkMhkJIEMzvOYM4glix3Vo1CuikklsTYrazS3mkR szpGI1iIyOPjWpJetaE+Zwoy5ei7u3vVUSQlNZUTS1k0Y7e5FNJqol8UDTEw7ZfM5L9b3moVgFQi HYmsshDAXgdRDMoanekPvZN4iiJlVnnXCyzR5eH3P85oGH+5+xcdxb0apmYcZnRTFV8mK21+j68F eKzJZrF6xw38W9ssTWTmeWl5rKBR5vIp7hTEKo0DVM4ycz8ixwiXCJXxvZZOUrJSW4smWV4jR39r 8LhGUdfy7deG/XOZQa0SJautsSdRONzssS1DhjfV4uS5fvRqbKMWW+rQo1VfNE9yLGknPibkdols h/DNalES4tuUQ59HTDJiv72hUqucVZ3zCq5pwLtbkxV5ctYfiROzi6uDk4LyO+Oa5l4XTyfu+Y6W aBwa+smTwNzocyxwxivsGaRnbMJf6KYZuiyTqxXv1I0/Lp1sstxsWLD6fSlUUpJkyZtGrk4Oiqij k+Rzc+OGEmFJjWWVe6rZse4yIgx74aCdGuxg5Newr2Y+k8G99y2KYHAYeFprGLA5lwh4CmE17nXp KggFkbZEexQjyYDI8vMffhuBHCEVwZHPcewxr2JMWWEkSpNQxmhsMSs1GZUxWPJyQ41JnXa9ldjZ DhrvavvFANlmlThPdAjB0PGDXg6n2SWZMRXoUD3FmYtamIpEmJT1FmSrvBbyo2FxcTFZy5Umb0QU rtc5+OL8CCVrMtoguCZkEmL0oHEJikDENTQWQdZ4BrbBtvBw+OTxRZdh9wZDyQki4Y7y8KZ0RMCA 0XYOU2isYJhjcT2lQ8pIGDRBkrHJzunHQ+MM1MMzP4JaxgxR7z5hGmVVq5xb2bNJs2UZ9dmFq+1x VLKJm3MFG5erDhwb2i5zckbnXtyWtmqiqrgvvxWr3BzcVjVmtZrWzcTesbLViw+K9qo5KL2S3KPz cluiR+uyjcxZOziscHBi3li1s3L165R9OZunsdLlNnbtknFk5tWDmsXuDLK9i5NFVGTinvTJzaXt y12W86TF6nVk40ZrHJkubFWzcxb1Sjm7NlzhKt68u0Uyfoo7ixa0auDt23uCjgjdWA9Ej2N6dm+P GfnN/gYyOCOFx1X+BvvkLGJlV8JPidn1WL4vOLvPc9KIzb27ynoka+Gxr3numUTobDYIajnOxZdz U3tCG0vSYwUjzJMUO2uV8KaJpUiEpvVYe1dMkNqzFCnOYMjmKnPGqbDPcmiJmGfTYN5V6eTBp8WZ qIyZlZxeM5rMznUkEZbOZm8LBrg+U1GeM1mfPG4T4xoAM8ADoQoBeCYU0B5PR6alIQkRy6NfcVJn 0BnV1xZItxojqQKMA5wO+dxQTcfEw133sM27OMWS9cq5qMpFyotaFGaYsHhCZHkwZDIaPkM0GzHK dhLtXr16CKEzk8vXGHtvx6+jTNa4NWFJxfro3N5L25zxXcGz6eE+UpDXNMhA0ed10q+DA9chFwXK ZzUGwx3lNZv0ueCEw3I43qjIeRM0uYJcsq8wUM1HvLMnZ8BrcseCj4PGSZr2ibUbON2/dwkSzffc X2qqULmq0l7v7mBMb2jc3K5yrNqTktOJwhvamYGtg0lH2lrdBqhItmSvgicbDDMmMyqpvomZzdGj W7o4vKzFTVSP2cXU1OL1N3Lug0X54VxVdVxEQsmFDJBJ2GFxgxAzGSUSpzHr9+LfymZm45XN69xc GDucF6rZiyYOrmaPLv2m8nKtLtFShRVHpA1RIDx5YDbjXiQEZUFHA1k1Eh1jMJMDO8doJznM3GhT iUNBmbsAfkOm8YdCN9GUuL0LPboOKzl/FkHclzKrexZqmTBV+H2ia5+G2TpSvfpbFrorRRuJhhjY MkTDA2mJjqeZFhKqggVX2kBRyldVpWi0Rxx2PcWFYPBHfiSTqbhgO4kdTJZZo4urg9SYYjehCm7o w0vqrWtS1YsWvzMlVxvXr1qrqUdFy1wdx704ryjJnJo5LnLe4rGzFqUUXNlXF1UXOvrctUMmbe0W sm5Vo1TJa5rGLIqsLG5RYtZMW98+K1xZqujVubMmj3WL1zVxaNDNgtWsmLZk0cX3HY+hzN2+qrBZ XN7atWrk8YDk6LWLk7NxoXaGcSep710+kPu9bY0fQ+qeQ7Sw7Rr0h4yfNLx0R+JmYtWh9e82iexd 2RpMz6nAKRwkiyNJPZO35x7o+HgeW81dtIWMG7yR4URZHmkel86HVDaNA6d59nSXV1NJuw5jtySH 3n52mh85zhbHWVHMWWbGpSBZg0slRO7q7uCQyPTst5k3qN6rWMvWpkfAUVN0+XxDid80sQUmzOYn FYfWcZ1ZQ+cOaUaVvOA/Z5GEddd9RqdzNMJZWEGwIpAggQEQMk3BGQOh+b8N7w2/2+3ORysTDgxR BhuZTCKCeDlzPBzrMbTk5054wSB8+DB0HMk7TO74rn45spoxZ0XzsvjJY6tHm3MHctZzGuKnK67B pBiBbxUXGzAMDY841TO99O5TGhj4bo0w4vc1jioWbL1y0051uXNy84qGrkyeGytNa6X37cWTNjwx M8BNpZOLZ0c2C9RswmjVkk6HQ2OYNHCvodoOs89Oz6g5mruz009EH7rAF7FRL29ivcHBUz1TdCvM o4L2hm3vyBFxgt9iqYfKbHDYBjiJLQQXEIOeQoqgiA4QUZOeVs5E1bWuThDmvbPuOhgTk3KNzcuB Jq1otL5SXRxRfCYlaaj1mbzSSkFGK00FSCCii1CmAq1glehcWgmiF5mJgUEEqaC2Pre93aJOCWRj 9wM2I7AnNBZ7Hg0efWywadNyy26TenSo2ZNxPsPQrTeovBtmlgTI1qDyctjoZIPU5DweAnUZZ+Dv 6dZxUDHYRWLRsJJGTqORp1zMkyJyHcM5FKDOoqIdgmhcB4OTggkwdDkM9k+3cq3e8ydelDv2pupy F61a2blY38q20uUb2jZyXvkjBo3n5b0kTokkijn0aq8jJyWFrm6LGirxaGbiwe9I8j5p1tU3r3xo 3uDq7OrFY8YztcldFGLe0NF7oXMHFi+UnZeuVb2irZm1c3AybLn1/STuNWb09OboLlz78FjiuXKr 291aJZJ5HRBAizuN49GwJ0hyTJI4eSgaSyzhqzUNVHkzaOPHBaXM2qP2ydzBVxUYqLXFppVvcmTR vXNmON7NijtPxFr80nnyPE3t0eJvNbnKh3PhLVv5j7OLob4YxPze97z4o5nl0dDiesMWEB8UYo6x JyalvI+C1SSNo0T1J+j4bOOPw7W9LMcL/gw7+zi0xn0mriT64+PwhpR1vEyRTM0E2okd09HXJCSS oTY6DmVeHnGiLNTJWySsu8YzNrOHtXTkbalBR5NRZRI4WcACgSFZp2yZpiuU7PLFFfuXbXaKYxfj vNV26mzYBkYyUUDIClLIO2c68SJGF5587q3Sl9zP7wQDBhDCDA9sgBq7HUoiuwDujsnYzQiKESOz Q0QOZZhuTvQQzWwFM3Jk6HJ7HEc/YRa4l368x85LdCRgHdks++5Gy5bIYlIkrZtdhy7W2ce2ObNI y4NLFdFSoFL7C0CLUvLVFqra1qzUSlkbmVXqYrJHN9Ppa5PjD1asZrw3N9KqNd90Giw6tUnuRZOg YaBCJNahIGBpZsXjI8IaYhOYkornSkwaKjyREgUGrwLa7ZSFFLQptY1jnoR1KFgkGRugwXHwPJwI G0YMvRhiyyBHY5MkCIEDmdS7KTAieDoHtwc+8miwoyV33tNySrSFC6KLDeosLFGSxsscPJybPwjH rXTCNS1sxxbt0xfPJ1LhXQzd24tLmgYtlVjTwXLb+1RewYrFdm5vVcVA6FHIx9bMGMrbA9Q+O6ni dTxXMT1PQ7ZBuDAYyXEeyE7FQ5KyscTCjE21hmpMgujfSLVO1Tx2Lgsx0wdS8A2H4PQNjnB16ydW MkznvygEPXMEKDCjGMclHRuomu5JO46O/g6iHIGiZlJAqsrmV19rloraEMAeVF5MSGKCGWGGRics sm/fnwdJRVkqmLcZLF18kviRbWiZq8CxmxSWLGjBieJLWTi378nNk1ZsGjJs0XN7Fc2XOrgVdH2L 2bNguZt5cqVaNGjcwZLGChvWslq5aqqwVbL2xRisdmrNRovWsGbFc2XLFjRXaWvV6unTeuZZKaMG JRub2LFyYsksOKq9s68OCmi9kvWqFijkvXm9eq3NV7Jc8vZDOm76j9vaHAPgSfWVNVtsO09vFJwe 8Mkbefr07rKd91bukhNOkDinjwYtY61UqQ5KDetg0kogaRrJmiVXBhkkLNYht1GNvDmyFLNp8zJM No0atrHQIgQIDCAdHDNQIJtMSiKB2hmt53fzPxXB3mwxuyzLotnFKi4YoVRLxa2FvBAslaaL7O13 qesbcenNM3J94mtng5P3JYOhks0WyBkhdCmdhZQ3q8T1WsHo2TfmsbJxWL13GeGbtFb8SLJDNbAA mKbkdiENkt+8X2JeVt6Nlpzxw9W9RtqtRg3OVg0blGqx7096aH2h9kZ5udMatqFLHKvS3dhswcFV 5Z04tDkyHVpa0UkMJZR0WrHFsomruxZqa3sowciLOCzYQIy7cHc00DmjRgyVJyWQUUcnWRwU06se pvpyTjD1yYI6HqEngw3sTn4niWlXerCFBsJpsiJaXmQxuRM3hnlnFs8ouZqUog+BR3YbBnx4PY0e 8nKHIhyDuzfbx0NjEmMmRmDlDMeRzsdToQHkKH3kzxrh67useCjFZZm+JgwWUa6B1hyzwTIjXYgs ycBk5ct4LiICC4QY2tZiG5kLDIktMU9kedARAYIi0ObLKNN0FEnk9t+OPHJ6B5DJybKONdej9rdy PQ4LPUn1OCjZ6miSOT1ObNmj1I6HOrKOgmrNwb29sYOe+prRMplXa61WVURTdjM01b169s4LKM1i cVd1y5eruc3Nc3pxaL3BzWuakrDinsvcFJg5LlGbdu3NlrBvZqnFcq2S9Rq3sV7VHN8ceSm5c0Mn zDm5M29g6rWyaNm9i4vwvb161k1WFxixaGDexdYn2SYtnl79m5s2bsHR65ZV2aOrV3KqMlzkq1Kp 1Rt1UtWuDBVa3snRawWpkznP5pM0b9SfNbzkOJKxNEozR2h9JfhX6M0+r9/T0b1sp6lTq7mUVdQK Dzm9yuVhRRh0wZOmD6Sn3/2VyBzChxRBOE7x4CBSEaGm8s0bGjoPO2KlJ4oBkE1gQDtQ6UKC2gjA iE6QVgXeBZICjcdSCQilkBCJrBG+4ABl96Ahf3KqmP2H4QhzUfvjrV9rZYsHM9Db/a37JdDb+j8N 0kVT/euiirnxGVUWdiIemIrmxYodJyKjMdUjTe+GLobNcFiJCE+rMgOXLKZx2DNZ/F8Wvl08iSs+ HWC0Z8xBhur5Mj/SmCBiDsHDSnw8KaB3yb6WKOts7HeIZHw4sMifdiFEZBE7mdbuedw9vDQR2SY6 WYM1BSCEAHXPXUKRvye8j6paPo6w1fB8rbS77XwUAmbDFyiqnvVDNUxxgpmptfS2dU2cm3rXNTO6 2FWnWJeVSgkuJUM0wzjUMnYR8kKSWhpZvuPO8f3mswRT/aO96P0/jdcIZkCIPvQp+sRD2EkVSQZA kUjEkUkH10++78/jzbvNjtknB9GOL2X8SMx48hlEqj1CC63CNQECIQnZnSKdjoc/jshdPNYh8Dt9 ZDRRiiE/tthmP6h7M38f+kHP4/2RLmQL91kk/boqrYaoQFhP6UmWSbAhmWg8hk9hneC2hAQuIilL 6n7wwuEU/sRTawCTQ1kPoYGx/aqqIjBVFbIAiFYNi04NMVkRo2LuxSXQsh400QNEy6JMZaJj34z+ myB9iTVm9DRhuUjCSL3kxj2Spq6kONIJ8UUi0hIJIMUUWRisWQBEGRiBwISFliMEUBYIrBIjJEGM kQ7xUgrCMFJAih6GomTwIxIVagUayKZhIYJGgkJSCMQYQuAGICaDYDFkYMFjIgsQQUFiMRixgMUy yUQQYghEZFixSMTEglYLFBYiCxYpFixSqRVFgyH8+Lh/x9ZFTSGoQIKB9BrVD+ACkHbRFKop6EUo DZFM6KVSQxERAVViJBBFWCwRRVgaUUqGJ9MP4wp6i1mYhtiGKKYBZQs5sqSEQLAiANAjBAO3J9fo uxxgelEOP7TruHj35ShAkApEKwUlRKJUIp6ComduCiBZBUuBGonwFEMl7lIAQaIXo1EYoRFCqhzn 7A0MkOAlNx+dxv/z+AJgLgfwn+Mf8zbT745gyuY/EaAOcBzKv/U/QD9AiEYGtLofubI+4cHOwD/m aCpvx75Sf9GgcDWajzIOIO9a80oLi0GYwhaShHKp/QwCiBpGZT9aa8plAd41huG+kz2kNLUVS8xT e1TKZv5c4r86UfDlWsWKvmD/EKnnP9CjSD2ppR8za0geYaYFSEecPWBPDH9t/6nPskQBjJEihCLI oRFUkjAZGLFSMEYwZFgoMikEYggIpEGTTE5f5BgDck3FMks3n/Apw2LhRvuBewo1SIAdFpcNAGuV EuTtGNVhIQWuvTeh/wbv2npTPnDEwEP4nIlDlP2/MGToS6ENwb4ncw6oD4R3iHck4RPo88IUxTOp Fj8Yl2PWp92iknnXPuKWlHdJ1H6zl7TZGTW3di2ld1IX3OdZkpEHSSj69V57Bl+Fwb4ut1jN5yqU evJWzEgmavNxgbhK0GH3Ng6B8To3vRnUuMXj9wZzKEgQPlolQqNaBUrIMuuIaAmo59j4+j3la1oU I8RI3GPpZS0uBtR10NejnJrTSBMmsCHbsVEjJnzpvlaopJVO8O9Qo97HLCv5M5Wect2BZQKprilj 7QShrVMRW9bpvsxTL1GOwMVMFiZAzBkNe2K7RD0/94Uap9o+2HmNp/JJKM16jivI5Hjz5L82C/GX BhjT7WnaaKqqsnymDH3kps+bYxrtfZgwXX4YSbz4Px4n1/vlCRvVJmVIhgGTr8uto0peF7eYeA01 DjjHFNFK1rUqT1U/OqXLct5ge0d5TbNJpAosIpAuSUCEH+oLpC4rAMA/Y6dWqncc7eBsR4HNrO48 ldqEcm9ZHLlf4Sd0iKZpSSSqUQduL6P+tz5qfUpNzwxsOGrSvTc6us50wwgJ4bwW7eYRaB2dhlsE NpsljIKEEEVSIhiExsTy/egdYHkeCMno9GaWGN7MWtlvQB8Hf5Nypl5i4LwwAuW6CRbj5KsY1PVR Q5ItTcvc06qUrJCc2Rp0YB0urA4njpjD9fvIEZJ1RJHwYH5+J783DnHqLRGHqKhUpjONiP9FjxSl /nvaWUcYEY4YnOAxctnoCo3rWLCNG+EhQavKBOD/KtUgkA/xeswXswT3Id8Z+pHrR+RMdrI4Lih9 f8Iv7+uitj+jr/aUNI04Qh8sOoYBCmRZFWNfAzAhPoPOT84YNEHsaRA8h8h0SQp8z0H0aYH0ZwmL shiGYCKZ90HsGwFVSayJEYHyh+DRaDryhUyZUTkHgU7T4PosZEN0CKwMQ97tTMJBfeREzISY36g2 ImBcFBvVJWoLld4DyD64BzwaSR3xP9o/h7j9j9lh4uQ7QdAJUAqOsIqVewqu/vQ4bz1Vf63ANFKY xgDQuFZbgLviZzM9/wSE85mBhhStISkpYedhEQ+YNxJHql6IUL5sCuLbmZwxzjGFokN1KYzD0ev+ 59fr1l14h3oSdQDCJD7NR9DBS8xJIHmQvmAbg3G4bjdTdKspWj6v5HZnAr+RrO1HuPn99mx9Bj2e /SbbHAPavQu4vHaqetTAMH58ihuQ+KjYuMmWh2nTb/CmIVukI8lJCgRg6VMjWv6f/h1LeKZteHBX wdFjK3mAaB3g6tKpmQ9D5HkFcxtQp1sD8/s6dmFP9/0SsZOPryvZJmG+BtLNTaEgd31NQ6Ycb6Y8 5DOSVKRcULRou5qtAoJypVhUidcIfZNTeiIoJz8EhYBGfqdcFQ9ydQyDtzoDmNOc/Ggmm4fgtFHX FLGsM3fSxpLRJJJ98LQgXlyRyI5yihWpUivaBeo4y8bnjMeuyfMMEjxKfcJy5MpUHmSq22jjWwmb /tVfxS6gPiR/bP6ui/7B8khYzPhnBfxQ3StOvJcov7LM5sPXC/iBDNIUlChkMn1w2n7KFDAwCMmc wfNuOWEOsX2Ih3H0h7kjbfyq+zIfVRxGIBA7hPs89kP6lqRiDFC8plBMkfuN8dH7pLNz+ti3gmdX WGNCPDLqT4WGzUyi5DHzIfsPDAwn9p7Khm0OY4TlOrIfSLAqTELToD72wN3u9771ZDjxG+EaH2Ad O5vSgJVMA+QcXFyfcSpT6DYreBlzFRyT9yvMeQ1Yx3VTUMz4HC13ROSbl0u6SO1KKU/Y+mR+uJT6 +P3BEiVsVQKkPzqPaLrM5ooNF2CMleFbABYOlY73kFx50XhHLchiUwQDAeFyuYHifFzrWo1zEzLe JmvZEFixUuilAoDiHm1LQXnRPwzpQymK5Ci0SqgUUJsSg1VmlC0S1Oht/pTs8XdYyr7WTjhDtkKg KH03zB9thrBNhcKqiobsRzBrrHOPGYwoYuh4HD+qmkwkWHhBMGsW2+VDTxAcTgd0PqOqCBzH2z7D urX/Xf9+azLGlbMtUVMXFxht9Bu3mifQh/pOZqAYlCFJrDhD4Y/e5ZWeT9iWWdxlJ2oYiVihj68Y VxsYh7ig5EuVm0KFP1ahz9Dg3jlfXe25cKnMYPb7yJ9J77FN8/FCsQaGjSehKL+B7/qzYmUkP1B5 BnD7Y3pC49gFeFSGRsD+GVT3QN79ZD3/jarop9DYdwcFGRjsZRRlXp74Ph1qJAPa4Y6B+FLafaa0 GZA1iQ/GhYwxaxJMDh5luQoRiJQqkXKxY9i6ePBzlv3lsSijgK4BXDw0ZVC9W8aTIn4Gtq6Rwpig xM/0ViUJnWcFChQwl7Bil5irE4pZIZhdNh0WndmhvFAjgbgoCzOLHTpwVH5wg3DkMhcpiVPlCqpV raJdAzg3K56o4XaS5SyMTnHj6qdqUOjqoeDvlE+ftCrZyHDQozK/Ef2LQuUDDWfd+a2fmZybt4uI 1+ktfAsG+cDAhFIQSL+w4xpzBy7UNx3pci9AYId5Z6VT7gevX4gXQvshF6jMthvKBW4o5RojUGx4 xPEY/sqFEgyRDBP5ZQ9J7fKHqn8njk1ijAPnuxbS2joGLYskrPOzl3ifOSLt34eHilpcHSdVX+Os l3RT1/Zk/Ng7MuHNyLitcHeBEQtnZsPQocZbjfLJstQxWfuPVseruZAHo7fo7g4yPYZShQjBgXWp UvyURwBspQzFTKq/Hf9kPN/dHePZ8amBglspUfGY024k9e7DuHxjDes/53Y9f/YPu/N48Vv58YaD mP4lqT+kakIbf/bw+6v/MsX2C+LSm6rQ38rVy1SWVf90RziOjhGGT4b39R+z4FhROcN1BOAMAqHY F53TQHyjTylomcYsD9tPzDPIck2Nab3UNQojT6h5Taz5g0khRERkXeTHExu3VQwgtaVvzBwJ5tTs DoTn18dS1y2ZGJXMRpIwKOQicGoc8kZqNhjiH0Li5yrP8xwMiYuR1ORjfHzomEk5WozblYxjsvvm iz/FRanKgu7pem62plSlB+vuWraG+hUHGIzTxGe8SpAuTKqVviSSDZJ/Seh4ndwPoA6AhQPmfy2G wh+Qfcg/d7WR8qqbJKV2l2sMw1l7/C2yptEWpvozi0WQvP2IxCpL8LhyvQfW1QLfUBD6hZiSiCyK iSgqEFSAkVUh2oR0GcaFrAsVVMxVCzUY3HBQ11dA5ibw1QDhJnROgOwHAeSqIs4kkDaGQvYTbaWy bjKxJhhWSqpc3LbHVrZHzxsbiC+rMcQnXN2OfKG8ySh0BBYoIqRBEQRUFUVijIiEWLFBViwUFGKK hFUWQCfoGG+BDfOGpZ1yNYvmk1S6XpP0DFla41gupDlRTtBe35afyM4GExkL3gPVvN2THTetiEhG AYz6zB93+39Cz+X+Tvq+NZcqVlm8scgV0fIZpxSg0My0Ky0S0iWrlFrwO5YzWKrErxf3jNcVLFDz YS23drOmm+7bMyZqnrBDAvZOLZzn/zlKZLmIQ5snBxed6z/I/yVcGL/J3PaSZry5VwYOTstWOqf9 0l6WyJyLXF80cXvl7cwPJivXODP5pwXMm95PH2jCWno6L03OTe4KcFhNlrJGZnSdK3r3to3uKjg4 nBwRk0XrmC9smrdKHB5PcY2rWhZ0NFrN4Nzg3N7F0KsF/BSwzc2i5qtV6HNkvbj2TZuUXKlHAxas G9aTBG9i4l7Ve1Zqs5kqtaLl65ixbMWDBkuTBVg0YtWzRq3nu91reOA3t4kISchzNuOEVipYyZMA 0la8NxsOI1HN2WOLs4rlpiovXu6PKTimnfU/ZSUOyy3wc1GresWtWrnzucXg8HRgsUdn7+cGzqZB nz6Cx5vHieKMEIROWiFoVA0KH7P4eceh1PjJ5O93PI7nJ4PB4sGK13sGT1boZEwUE8NOd/EVpztI Ok5BAacB83EQPzI7yvJ+1kSw5Cvi7nz717uYKKjqnc4P+CjN3K2UcJJM1CJjRNykdlh8BfU4tnuU WNGDc4lj/5KPJ5VXMXz+drozYuT2ap/vRuSruauLq0UcS8pWFZWTg8fvYEwDl73/Lo3fuZwrAg9z hBEGosGMYwBwQgBTHxGADyaBnSjD8kPkiSaH7+R+ZOZ/A78PI/x74cjWfwol6Sz2/6ESFu5dYcxg LR3xOQKreQCRGAQJBOhfbu4+OU3aqjyX0mFb7SRW+CFUIoXiCpJhyz9YQPP1CS2ndH6Y6Swfs6W2 c/muGkncblZ+6U2P+qsv4xr8SUdjAtXQXUH8t9aH1qUUUOEYJfHz8dhUp1p2mn3w3UjCEjw4GVFK ZFL0PGtELUGhhywAhI/8j2JD2BCgESgVwPzvWMEAoewT8MlUWaDbuGxouME3wrzAP1w57/FWu0K8 48tNds4HeFTy7vl42rLOayKw1Q5aN8uIb1iikKUUVHNIKqnIXDIMzF/7SxK8QNvALijC5NBrQ6Yh q0Oku0ewIMhCZwugjQiLDawoJNxN4hGMSSM5FkHoixV2xISL0oZ+X4K8BXU0qnrz6oy30zlNDtkn +8M26aXgDykJsvpKKySBIBoWoinyr+SBNAO2mU4TPDjHvXIUPCZ2DTqBUzBIBN1crQP32XLoo7n9 aRYhhMm88ppYd5qiSan6Tc6o/P4Pz6yVklO37cjSidfM7DY59FKHOKSpQft2TpKMD2nusiSfIcXL jZTAK0UlSq/hE7SJGxD5fHKDP5PpiLCJ/3KAPhosa1wIDWgqgccE4yI1IRJCb35N4VTGDIZ4IdB0 gp8yb34Dy0qPaOND5jjEEY+4qKig1imp5EL7OD97DA0khwdNKvj15iKH/UCOTBZ3Dz5cgMF68oqo tcWrJyYNmz7r7FN7Bi1aLpLGTotUVdFzo3NCqirk4WsU4KsGq0tcFqjF7LbFNGDVRLX2S1rlS9Y4 N5KqVb01WXrVzJvUasnBxcG5oueJiwXr2S1zxS42aPQ0eTsUQbLO5wQSSYLDTixgTnc7So4tVi9R wRwby5co69asXNvasFXFxWZrd84qV3s3B4TVmwXubBk4qmTFqwb1xvNlFr++ZOC5waLGjU1Ufp/8 PXjA8lEjpFBP3f1w91gbyIo0wppMxoOPjk2nKXmwoVOQyD7SBAgHtz3mY5F2Beo5hD+hhUhSb8f8 o28FO9PNVvPE5NlVpc8l7s7ds2Lg5P3n9PYvXPBqzzvPZZZ3tjk4GbNwUaLGDgq1flyh+kUkn5KT Simape3OpucXVuZwxhObiwcXZcjRG5FRuR3Q/ypPyaJucVWi0/2JMSdXFVydkzOze4uTeLX/5h/u ePipR/cqUrKKlKv4mTg6u56+DvWuTo73ZYtZOjzYvJkpimLp+pjG1p+hbJ5yerw+07q4/NFJ+xzV /vPzPo+kRXaBmYLpihhBaAZh0HQelQNKnkwYsF88c5yLQH4oAdZ2IdWlQzsjxh+u+1/tZknujAr/ J6G43Tqd7rEjukgfz1OUTMegmvWOAes5viHQGTfIN7EOUgRUnq3zy8WBNzCk0wUC8oX6WX9FizXt psPJQ1kPxHaJ7o+jmn83m8H2H0fI1jORKyJ0RmZXbtTB2Po6i5g/o/g+C1/ggj2pIhIijIKDIoht CoGkibYj2ZcuXLo8NkYRO/I9bnwZm4CWIeGRZahfoXj3EROsR5jOCPEiIVxWuttx1D7yoxO0yPYa HmeZMUIlx7Sg2FUb+qxmp457bq5cVqxqfFk4Pn+mDezZLrrTEJCBgM4oNAyJ58RmVayssLD23mZi XFRee4S85OijBydD4Q6cG5XA4KLFjFsxdXNgo1ZLW5ozOvWxkYtV7IKp2iC5VqzYujm4NHZVxWL2 5Y4NlGSrxVXtlTsxUVZtGpo2YsVVyq9s5s3VItaNGCr7G9xaL1XCarjRkycmz7ODZY1YOzs6ODZu UeoNwzcCEOcCDAj3FHJZyUYylsJKNlMFjNrryYs256SaLVy1kyXOJckzz3L2qjJvOJNmSqjezzva Lyj7O5smi1swdHBYub3A3uBasaM17Bgvcjq/Wcy08LbIlaw8BFPw+Ujezc285OriuWJq8GL3I8XN 3NHV2VdzlI5fdKUT/T/Oo+0uj7UsYuDZo4uzksb3i5MFq13MXVa6Oyr6I3NnlHdDxoTc8XJuauTN wb2SjZmoyZrjJm3LeSmr+GKi5iehQ9FM1rq1b250cHBwXt7TalN0c0BRXKRsGLhx0OhJIj+XfroF Z1wrYFhI1FCT3GJUCl5DMmgXjGokbwPX2aVvE4pMqLF8xOMwxtNhcYmBwNREYpMyJt2/lCs3nTmq 93jwUTUMtZO+JFv3FvuYD7wFP0UZGdn2tf/69Vf+W/Yh8k61wn3D4jkpifGPAzhZ4TkkPewdpCkn CikoxEKo0Aq9OsvX3l6KXXmDUMMECbzhD5z2X3/BcMXrDxeLSP9F+sxnJ+06j1dyVgMjczzoq+NI 3v52Sx/jSx76WqYuCfMHGHQgZQ8TJneCepY/YQNoD7mmuSHkhjQ5YNAhZRBSO+aAoqnaSdhuqB0A cFKc9oMswZGYLuH1FJb/lPwHp+FIf9cFtsOAHJvf5nHl3PoyBsnUeVgHy46D1dl6k4sqV5B4hgEP gn8fF/AYH7uio9v2fuj7R9SkpMSIdGo9QcQWPXhVar1FBrhELhRCpUuUDNcWkKAs5SHoJ6KSxP7j usUDsEzPREhgmUXSHAifBIcS7zqC3rJSlCBSHIEchcZCENqepNplDpzHVk80dEDKHPX+DdaqPzIU 5DWzlWMRKBSFqBVEDgoTCIcckKZGEMa3ODxY8k10ZkzPbjXFRtUFmWoM0oVwinDie2H097jjHp2h /9k4SqD0LxwdWLmmihdUClbtNbDYgetRuQig3VZPo3sgwb5Eqvm58m9ZP1fj6/zTwauijNioxXOR llYfgNZsIQmNZObwTMtpPNqC0sLDbfhY1jzAYoNRQwc3QzaLl724zVctXl7e1G5s0UWs6PcXunfq 7u6rJ0ZMFWzWc2WWTe9Uf1yxyYnN3t7i00q4LWDc6O5aUXuDcoblji/B74epT0XsXZmWNCx2M1W9 gte9H8b+6M3Ywdu3Vq0c2KjghC1wdmbqWOTI93PbbJit3M29o3u53v6HskkjQ3uLqwblWrujPClG iKtXNg6RIzdWbRksbnJeqxZs2LJiuXnUGJkQydMkCHL1h0nZSF0bilyggyjkISTQ2ERGGdsGBRiI JlyFOB0kQvsFnqaN61ajwmw3HPcWLh5d8sZDmtimUrXYXG02nMbPDzj8XhDSBwBQA/eSKwiRGBSN mBUjs8lDk3snk8zqvelVNOu6JNaSgQFgivkOkGiLtNRoMpYBwcxyhUaxEEUikERZRqG8hvCFgAWF Uc//1/pRhx83RZZyeLwOK4ueTkyXsHc7lpVmeS1q1YMWDB9YdX9+jRq3MFWjeo1L2jvaokms6poq 9w0WN7Fc8HFe0cS73lK/KezxwwYZE62xFFRFVBPnI1NmrZSTJ1e73dXivd7m8XJajWN0VisJKEi1 qivKzA1nBjUNdYLc6RSKLqMnOCxdovnvPjOfzkxDINQjOj3nvsd5mpTatSJphSEgmC7w+QoZ2Ci5 9YEZJdz8j0WWfB4sXqsebs83kWJmtLHm8m8fWT7pH9x3JPe9j6ny+J+XVHj/A1ghVPU7974Ve38W 0YP7fdVYhRewYn4mZr5nrE/ijB8JJJnXNem2s8EbuA5EylBd3my1OBSfTy0WbzqOEYJDY7D5x/Ew Ie89pC1Ez/0dL+lNeyyWU8O1VLKqtJUqJdC1bUkIbwvUYL6gyi4hkwKPWHyjOETRHXR7HJPc898J Dp3pFH3/1xCv1k5D1eJX0nwScH2T3zdVKuQ8TF50ftJe9Zz2+Tw5bKuuBRyHjiVAPWd0JyCl5zJQ R4Mu3w422PCtRtkmdxKjPo3piVAi6gcRicl9OhhTctADlCCDJiMGRuBrWYY7aH4U1PKieM4CSeoo RhE8ZiPsqqzfnxeusRBD+rumheReATADLzMN1Q/ATAvAoqCk56UKytJaUdYe+BAaLUADWruKge97 Ss6h76DBAonFIrOjYojrGA4k9ySlELCWyJMbXeb4E6HFMiiwGG8SsDxAeYsddbOM6mcXElwT76Ce NCewI61a7VthttgHgEvZy7BRRQaeoBcx3YUhAXI4JdE7Kg59I7OhzTjg+XN5x66I3xjBfi38BnrJ SxtM6ZVqRIieTZQhoUMXBklsxoo4yxeDA8ejJYRdLeKBVgriI3vE/P8/zfJatttO5+GD4Pi4qs1p 732rKebIxWboHBYRJ9fHdj1a/ThT2rlrrx0rL6Wo59I/Uurq4adfbhTrHtfBa8MTxKCsFFFN4pOZ nAkRFN5gWECaClLyWsj1e3tgveK23ZsuatSxuNVv4/CS6b1PuuNzJmq9NtuDiuclTe71rNazXr3F emji0UiFBOTFox1nVO6jXZTuf18dvDhu5c+huoutMXc2G3BH14FjyI9/DWBWvHur5fJr1wlTpyjn qd0OTesM1ODt1eEI9uXXTkfTnWXSGqtbdc+uN3XTt2xlZ2xPzeDHPxdOqLPTjpq4NZblKEMuE7oa cyRkdA1k5iUApzHkx0Dag5S+Mnx+NmjR7c2jvVeLZ89Sq9wZYN27hoWvZJgvv9uMma8mbi3Kt7o3 rqrnueKbXsFcDgoWs1jszcWaxg0cnxOy9ktJVqybmTNc1Vbm9e6dKsmLBq5KGi9O5ucVW9vVZkCR AgWlJgVlxEpBPDrDo/kK3QUHL1jgiF8DnVSKBCEEGgAh0lkUsnLRGCHiADgkKhIKxUFWRgkRgkWD GCyIIiMVYKScA7iGgDBkssH0gFhpmVFFgiBuh5QNxp2TUQLnFW0A0NgtBe0MmI9omBpL0TEIt7YK uJkLqICEuVVKDAKkQSQUyv0LGmG9SePc8XgUeLyLrXxwUNGC5zXHewWvNcsXNHm1cnR/xYGSqZu+ 4WvBzYKpLTXuHip9qFpFlLvGKx25qUcXJqtaPV0b2K17mDJqosYqr1qij3++5c1cn0PTV3P90lXu jcoPNyb25Y4OJgayaMhstZtni7TSaDiOsr+aU5wW35LppCEkSAcx4cNCvQUCYJI81AskhkhiLNTz NJoaXHaoKTaO7aCjtWiE9YuPJMt9nIhlYElmPSKqyZWh+coCBFCjSB3WxhScYCD3lbnRYZLN5tHH WMKdB4xsORyMLAp392tsXFJ3vVoas30fN4N5me7mHRjLK/Ggeyu6ylz7Fe58iaNXuYvCguTieJdM XRiqo8BikHdRMSrRssXt06rFirq7NxYwMd7Q0mTxTiycF/18o9ZlLSXR/iXPX4OkoQTfAgYRIoWD C+XBZvzHENQMDaxYclBE2CPRBjkAjXfEHF49RORZWfEmCMesIPq76Qepe7sKh++J3/wda6IYwKcZ lsNouSoHMROIulNVi9W8T95A7KoXZd/fQmJmJxh4x0xoFZMZIUVmqUlLNP980N8PU7PUbXbz+4IX WY7tXEk248uPsQUqEhDU5QzMM5nLwEC1SlBsIpBgqpX7bj6Ah8od4nedK+R2BlniGYAOw6ahdDyE 2IelLNMIcTlUC0fu58/YKqIWmp+uEZdN3Nx/eikxEtN5S0zijRUjzgUU0wbhGGqIhTMJZnnnBnWy hRFLKLZqX2WgQxBpi3C2oIVbi74AEZyhxDSsm8py9ZvBYsFisQTqxlyZd2OdT0mvIoHGCFk518YP C/J840kj1UqFkOLhyZoVmoQ2wYwhAhEgEQ33WiAzxIG7aF0QT5qHI7M5cEt3F2ixzFqYVswoIISN wH4INrN1rNFNl/pGUcLBw6xCj785Uy7YNTxH3FXOtq+l8INyZxL7d2MDZbphlQO11aRsXiKWsYt9 FSqAEiX4JaGPRBVKS1PQ5YJESIQSEFCwqWEO5YiIIoc5kMQhwAoFhENA4duelDEGCtQoA2giCQA5 GCBPnwFESQhFKJEiFzVqoYnJwUMms4MUAMJD3UFC9T2ieYWgoh5Zj8792kpwXPtEqqgusPuwCogR TB8OLAfb6RQ4dRsjQJo74nuuD8fhaEkP1EDmgHmJvPUIa0AAqGP5UOL6hfXlEPfpF6NiKeJdR+c+ L2m9L4BBEJ+MCUlGh84IFSoFScmBgz0fH3NfN9Pxy6ghmNC/qWRJmvVfhYnRYqzXnlHRxXKtnB8l S1aDz6umA8OwydNK9p7IkCwUHFxeXlIUFpAUVmyUUP5MFzi3NH2iv9huODNiyaLJs1bnFcsVcV7q 5Yqas3JuYt6mqnJvZmTewb29JvbLVyjk2fk/ZGDBgvUcGi5mvUbO3bgtXL2qixtAWHJe1UYMsqsn NyUf5ok55OLgoowcFhio6L1Xe/lJJXszVwZqMVrNe/BKrGjExYqujksXJgo7Hyf1TOhTFi3LXe2X tBzdyWLmqru7uLjuKZqKtGjjUJeXDjUUGg8cV1/pQTNFmD69/iysIvotCsU0N7XXorXx4OZg7FHV 4LGbo2icpuMFqq47mLsdzBY5Fq1oq3Llj9l7JzZmrNgo3PoomjVksYtzNisb+DF4uK9g5LTVwcDF rm3LHBRgtZvvJhZYtV4M2TVUzXOcELVr0Jx7u7Bwc2WL+hhhua/XCRG1EsTRObqsbnJyXvpBDL2R FUp8kh+U5j4fEbkXNhiir0FZ4FQNI7z+5SkCUftQsafWCDKqCH3wsx4Aoe+oUYxMnGJuFPaUlw/v vfIelv0/0q+v6/rAZjoiLqKTBR2hSskmIW0R4QQQ92JCQwFL8R8f1fhPJIfBxkPgk+Ja5Gf+LpH9 jdIoKiiqkAob3sNmDcRO46RhQHMnFNSedNgbO0hOcd7hEjxruNSmZ+8PqexgfwOPx+8n6k5U3g7R cobyRADsdm02BDsXqXso5yIZpMgwhWsMDUNamoeHoGCZgaAdoomVLJl/NZZS82JYbSHNc0isvF2Z YrLScXfiaRN8oLiewSntM6al2RiNOzm6woMgrfpXMRzMgGo1HsLjid/Wh7ANkAHJkHxEQOZIdnMh zqUUtpWVKSqIwh5DBvpgqEFVjFUA95RSBQA4Ovf88Ooy40QwZAQ54KZRgAMKB/SD6vcIgbvY+yYi FEzXXVsUgFSemFYt6Ba7B1/MHCLseMXxS5PEHh6wIRQ719YnhUz6OlR9KLyL8j0phHDgeyPNb6Si mKNPs2v/u0ooZK1pSB7CFJIAQYBaKUSAZVVgEUzPUoH4I75Iun0iR0qsPkWSFiSm40TvzHjA9YEy yAGYQsyAcqibVMRhggLymM/2kSpyN60L4VJJuPSQvM8Edj1Q0PKYj8WIDfJ5n5wGUbRu5u0vu+AY xBgiMVJnMyerAYRHOh8h/Pa7QIUtKHtEoilaIYYJbKLx6tooUE0heTmlJLz8w69T36D3HZs2h7+v GTk8ZIypAhRdZH1rQXpT0uhDhSHUhjDgGKLF4+kXwXRkHAgGAj+qISJIsgCnwdAWKilAPn5gf7QE SDuPUGnULaJjCQjB/YQ+ETUYA9wmGqoYq7Ady1hzpNX/9VFmhkQ70q50olJQosTsjoXIeofDxRNa pzNwHY3niKeYDsXaEDuDfgicrDo8hc/2LLJPA+ESPE4SeMnflmNzv73OK6fFw4x8ihdN4Mg6mXA/ zv5nJvjge6JVIbJ3FpaenYzjoj0XHlHzLDj9p8JIQ80MLBcXW/fuCiqS79VE86QcETop/U4O/etO yRav9za6E85E+B4PD9hfphtHleXRxV5RzUl6Wn/DJKwfhl2UVp5Xk1Qa8yUFS5GIVNVBrVAsNfyA 5B6G/Iinc4nmDjQA9y5j+xQ4BIr1C4BrDgk/aiX0n0VP67ZCE4HVOQeh4Zr34e/t3+ChA3IdwVUL AZ4sgb4imgzJ+8+r6SVILjGIlxiCi4aqILEttFaLVSQKJHYqIbwmSh/mQzZtPfKKhzJyp7AIJFij AgNTKXCrxcgPmDQHmT0nAeKAxj9Evi3gfqVRWZGad8fu+z0SNPaKSQGrAlGiiO5gghU50KFJTc+S eAVMo4GfFXRYfMERB4/PQ7kOot3eFZiZ6nZC0LKIt31ktIsKJCiGU4UC8hw6I5XST+2xCjKPrBAE dzFQ87VIV1KYjiv2qTk/hWnhkKyRIHjIYwIGRFAeGHc8Dhs9Cjn6Oc8dF0NIxcejC+tefi9N92BM p776o5JImX04VwBDkv8AqPSZEC4Xe9MtZDIZCzyhCEW/d/2rwywR5YVIQ5SpSsl191WxDAb7qyYH +yo5GvtaAUUtvB+tFMiKWFT0ejivGMZIKkhBIBBkRgJBWIsUkIDCQQREgQIQUEiRBCIJIMIBGvL7 R8luzf1JMXVt6x2MOj9JYbW2y42fTAUTy4kpRKECDAkgEE5QDL9X2G1ujLHbxFADeM6qC/le7vXd 6WECAUcA4KjYCOnApJDrrRStitbGiFZLXlG6eM7SsGfdFGp3ZafvZSqKZk9K5jLlJtnIeGu1pI4h sPghiLlOkm+h9j0k0oopSxlvtUU/ceKHsWR+D+Tij8bxJCLJCIg5CGXP8xrMnkyBvgci9e1B0o9D Lh/UrP5H9FD1ivAeBybQwok8f9Uk/zv1PxPxKAxCrCgShz+PuX3/QVe4Lsw8AHQeZO0ntQ9zC8s9 pclfin3j6o/kT4pV5x4/wqfM0w84H2h2JwCdvcJg5kM94HSpzonTFCQFih5ygMLIlI2AlIMlIlg0 iWRCglg0iWDSJYJQSwSyipSqipKQqcpNxskvuXlL26fOZI4DVPf6dDofP5n4T6jkPvJk8D4+i3wS Gc7xvhrvTseN4AyHWnVxIWA8xi92k9VaDI3WuhamxolCEuFS3CBZC+XQO0U23+gqnqKIz8T6LYxv 1dzH7Di0OiMXrN0lztOZ9Y3QpQNaL0dIQzcUYqFwkA5hiMjlE0lMqJzRPEUOld4GoUoaTMZoyCO5 zTxS4OtbgdZlb6qY0K5et+jwgLrKxeV7Rc5F1r3hmOXIqqd6V0dc1BAKVDsOQNG4Lw1EIpHieo2h wSdDKPu6ZOE4J3nSbRP7/Q7vZ3hQ7zYGco7QlVlWiLtSrzJt5lzVDaHybJO4yOCPacfkexPDiYSR 9XVOnLo7dPT4vAx3PHS9qY+rTyuREiaJ6MbJgGMbjBhPLuLhvlmnHia9DKkTMMsVf1QNNwigIycy USL7CeYhoGEjaIaKoNFDNaqiAP5tycDeMGG7aknOROn5T2fF6zvjvgT08UdNQSkVcsBzsEKD2hwc tkNyaHsA3HOK7SIcRUjyNA2iOZLG6qHGdfEBqDgaXKz19KOH0kfqFz4Ikn0xcDojaTjRnvRWXS8T IuhTjSUpcoiswvgR5i1xMK+iTmVEi960PAhAlG2mMc8GYpgBQREUo1lSW8WBCeLzxTwltTWTM2aw BCD9/TBn79m45DADlj8gGJemTKc2Td3eqmqzd8hYIqriU0w6l4eSPvmm9l1EeySBO7P9d2ePkhhY fI4vWfZR75+tr2Znz67h9CtYkfrT99QVvzmQmYczgqAoob3dAkUcKgEHZLbq73Jio/gQMEOA1noX 4kMBjqHLykMQ117gKJuCwH1QPSQ1/YM3StF4pMSFQL6sh82JDIRpJ6UUoQjvnWn5U0AXhwBymB3g 7k2j7hIETe/fComQ5VM596FA5D+tjoTBBz67+sGV1j/6MXBQ/vU+OI3PKhT1ilhmI/kjlYzDaGxO ZkSKYjYcY+cOZTlRSGBZ55zupFPeXt8iugb07fJ0incPmKoHypggB1egnTiRC0K5hDvNXTBRVUmb UrkUG7WfjWWGWMwbqnTqxMWhm5hiTB+rGIEOdCXnhwYIBEfGftclP7JOGkq73GG8dIk92p99HNI7 IzmMnLx70WaSf1v3pzP7DjFPB3Ret2kZHBxMwUGwnaAZ05lhoUMcTYRA4iU5RkWT4xA+aVjYB4KY PdmXCKgP2JUBYY+wr9EZH0eNFyZVMAgL5nShcBmQ+sT5z52hSyJQEoCFASyIUSylLKUspSwSxLKa fMHpA3m7m80Fnv37EwwJuIB3FyHDPEC/XjoK5o34KqZ2p94Q/8ThgYUuPBxn9gijd2SiOJSCxI1R gWJ6PJD1TySSK0jdHrp7rBYBQxsbOd34b1WX0dOuPtRUVUSg75MBEmvoijEY+WXqRTIN3VYuRT60 U36lwqXhSc4VRSj0Ch2Dd6w/n2b4AfIT9fSOCEIQhawHOZQOcDpbjxF6H0gF4tl3s2Y7J0Vo7CUh rjI6u/6QDxDLEUuaHoXrdJ96mAhkOlBfs9IdRoB/BEoNiUGxLKcT1wD4yCSdEJSawqgkdQkmzmIi mhciAhEN9Csbn/bzPZFg94vj8s4PvLpSh+U+djp13utJYrFJyeCO86H0ke5/VvLIsR8i6wfqONnf w0n7zd8oodB5l0IAcZtzmfYztkJB4PUg/T65GLCEYSJIgAEQAIhBIgpxvibSyHkkPGWD5CJSNkSg 2JYNIlgliWDSJQbEoNiWRsBKDYlCUdj/5v5jWLwI9Hl5Ejzd84pQ5JtN1xV03nPXxucQcrZMliYm whs5mZcIamaawkppsH7MbZd+1wxplpJCr/npuQ9mthrttrpYUTRXJbUzTduoWREWmsjCZntPdkXT 1/4fqdWL1CzaNy2h1gRdRA7oBg4FCQgyFiFAka0goVGqGssJFVSw0IDAqqIUYCSINKAF4dZ5hPgu InoTiDzMP3PzyPzX4JMpgrNxRuitJTnWpENiGpKwQ4ThtVIEQuWARilB20Kgot/QX9GVyokoxpVu Q+r1UPtR9VbFKQQskmGEIhi5qfc5nmvlHB/Q7QFXpGxDMTfJEUhitw9IVLVYrSZyBdajSJaMZAgG 4qqqVTAuD0AG9ymVHfTwCHf099uc+zUH7zJpPwZv4zEKQwfxm8PyMy7FEECvlRKwMysxrsQwKOrf HGFQLGY0i1MJpwMUXBj239PIlOsY4tgp/xOoMibsnACmcCHElFjwsTmqqG4BqHkFAA420G3LFPkp QWQInj9kD4zHYGZAOYb4TO1ydd/Eslnyl31aCoGKI/KGdCpFjGoNIoQiB1ESmtGQQCjTtHJrbChk H1SHEh/Wj5NEc0kXwxY/R3JUnf/9VH8/stj/R/n/nDVJ/RGrcYJ+h1Knc2VbS48HfdHurShQ3VeU mSO86uF0PCat7D9nnSOjg+cLB00M1V8Oxp+q+kkh2XNAfUZntqlU5BeEKpzRE1x7H6UAODImLuEa idr2IfDreJPYJ6yHnA8xD8pg/EYO0TqZgxRhiBakaVqh7hY2W2W6vUtC/61qoS6+zArKyKCwJyG4 BRAzYoFYKsioqQEEmIUimaAlCYhCekTGYKjMhMQEGF17wARKzGjelVFnc0TALAThQohiNVQCj/rQ BEKk0cjcFTjOkh0hPnL1ADR25sZIkhD9omlDMqAVMAeEK0A4vgZBT71Dl2KGw6UkOA8g0BzavqnI dp3m0806aQsgwiE5OySs+/wdWuW3ezZ1TZ/3aWZZAy8dq6Y43fa4W4DFx4jITayAegCbYhbhhTDw O6Hvc0b1y5fK/Saz8y2M52k+rqePpIeOzZj3I7jeKqSnQxOjindHAj90pEOvDMERqYtCgLB/eFGM T7EO5R2IVgTgdR93cN6YpgcMxKAShEZEEBZSTwOZ/HrJtCQ8cPhrWu/zs+XQe/sSaPc/WToPN/cH aajkIhDfo6aLsF7l83Ght+XQqdweyAXksh9zInM0xtd0eDtKDWFIaYZ8F3eFydoYKlk1sSZCzpy9 36dAaDIgZA/QIMCEPLGzFLIJSCAicc5KE8EUqJgSEk8860igiEkVWIB2iEnEfGCMtAVUP/CnuUVa mC9+NaQiciKYpW5ADca4dMLDUsuib4mhAoqFVJDwDwQSottbnId4b/KhpsUk95/fCqBqO85w38Y7 97CJ61zF5/rkvFAeYNOtrkGzd9+jzsmgt/gVnAbXvPUdCnkd50VyylUDvpWpYkkIFY0kN6Uj+gsm GBiCMM6dhaYyXCivcJTIWrZ3gYDCSE4xgSeKbTr9z/VylKK4YNGWDqMsxK1aAFAI+XhoEyZol+EQ ByWOshCAHmUMyZhUhEUjEU9JrYidLZ4gNpPj2pPXJPvNjq4CexD7wQDCMxBaYziJu3Bj4BQ/3PnD yymxQ2JxeceyF/G9SWEG4njvHIpTp5j7CAmYvaDXwGrAIedQ0GbhOfd0szFInuf5UauW5ycYQyTB JT9339wlQzihALg23i3HTn+ivPkVXnqhtDAinOR6iIHwmAquRTBd5Q5hUPnRiqLZzB9B9CJifgxt KgvTeRDkh5IXlYY5IIh+Pf0XzX8xGQ4ewJDIMoaWLmBIqgrJ8hu/sYs+QvkMbILNKQpQkCVSwnSG SwoPvRT8EU/QVkWYlGilVFFEXzkVsss+cB2PtNx/hzc1xQEPMHzhjY7VhEe4YnE5Q6Bu+oNhxrZd yHBf+sLVKigPWHkb4bFkCEhIMIEUSIQi04hOw/MSKlEolGIw4kpJM9YzLPyj7SVPbZxp+VnzOKQ1 ho4c7LNmT6GoKXnWhf6A+gnmDk6zgUpQT3zdcGeKGCoNXPgYetn4ehIHo9aKoosUFYxYsGMIIgII CRBBIIiJAQQSQRIGseQCT8DcGkOFT2HaVE6wNWk2k+tNnra2/Q/sA4ULHH+69pWT2UlSsj+8UQgf 4wPcinuEUiKXVPP38nJSkmvgO08S7ayPj7Qpir5Js2J75q+NKVt/0usAVJCJ1mDkqe9D0J4h66PY jtD4A9OwXyM46rU+U9ZnA9ihxPqHIHOLNJU8pC5/NHAxSbObdJbH5R+49yU5ub81sB2RNz3rke0S pyR+sGpojFG4I3HZRaCQ9bcepUvLbTiF7+PYLqsHOAHCFB5R2Wtec4/0jzm4ekkiDzpFhQhHSdae MWS44RJ+6TvOvmXyeTojFPdyPVxzwk6HmqnM7Pc7knv70ekzdx7GMB4tZBhkJ10befOswCCLttZw qAY93a+CJAZ2MhEhAWA/uoVMyzXFdtSiEUYiyIz0PVwuWREvvQ7YJhQPEFS6ZIJd3EtcTz07duGK aktTiYthWM4XAWi0mBConCYw4wpZmGIfew+7psamYJedoxMCv4DeXoIIJEgQIoUjHZedXejccZwI ay8zQjAncdT6RHu2R8z3NH+ueposio+klzKSL+dGA3IdGIeDFDAIEJ4SJgjIUtIFaMAqhAHsVq7I GcFSFrkVG5EgK0Usvb2opyGX7D+0yxIRCQhISaTyAwZDSaMVN1DZD8GOVGjdIk6HpJ9j1fkkWIjW NlEpqlho+dv+e4hWqjMofUUB8iAM0CjHstiPC4xTLTI3LLclJ2wG4ReymXjoVmJg0XDnnn8K74bg +vUSQIDyJiJ74GYM8im9JKu5eNIgeYEDoEt5CQr3qFHzAcinswz5zOR6iEEoCqnvyHI+dngN5d40 Z9VwmCejsvP+az3pNwl3huQx3oJMCQjaHxpkanRX2nxxzJfm6qlZWQGt8vsNwwkqUG6uU9ooZruZ FPnRSgIPCikFUKgge0EOM5igUeMB7qInyEWilaEBhZQ66/WQIwH2C+AX84cp4gXluhGclKqFaL7G JIRgB7z1FBt6qCm1T0fp7DQU+0fxj94/ci0oO+Z0NPxY46ttfRjxlqoHKJCiYZVRpI70EQ9Qcojm TEibEIUD/40oobUSIYUG237E4+Dv1YCDOARFP5bVXQNXL6eENQGw0BreH5hPmN1lW/uPQlCeCH3T RIMGMDcAhohyaskYC/aobVdPUfQGq+WMKFWlITvSiJQiEOESNBIERLCKQWolV5RrZRHvQN+4O4D0 Q7u6E+ZgVAULSlSgqI2UOhPlQ+AjmoQfuaBCB52veJ3HeWANgJvjeEKBIqkGQpA1wEqikVjVBKjV lUUrxkL+nCuJlxhieou8L+A5bGTRdUr3nH0x9NGZc3Q4yw5DJtJwRwguB1twF9DcXMMG366Zh0gh koRjBP7Vrs7drwee70mQiLIDO1jQasihAgTteDHcDDE5hNx6ezBFXancoLELOc0VUPyRpH3Tymvb 6tmdOPmYmRC7S/oj05LMT5fGPNGYf0d9LWnc277cMLPGncIOCZASQfyUJnjflV2BxP51MD47kbl1 aStB5cmwYWWG67ulNrTwW6t7L1bE2h7YMDhpeqyLa97ub8N3rAwzN0/ARvfKBI2QgRGnaGwzSgWU m+XyOig3gGGo1+Op61DiAMF8B8895wcZuvMOkJp/oKnm3fN1fAySYJPTU7ptQckLyWxrVkOJ20RS wikRS4xUVYAFyara6GTq4siXyNwYIlWgZQpVthyPktEbIbcwTx0+cpR5z+CqihVvePVo20WlZD7y UMep59XV9y7rHgaouOjw7qUpH+ux1oaZ0PgtrcLk8Xe41LXM2DYNpJoAmAeR/qjIyCXHHJDIkO/t OUv+b56Zk3oflmcfSGZwPPJ5QH+yHv/a2c5840eR5H/CebeXWlTa0IOtAQzgCGZHnLigP2fGeAWM zqHqMGsDgJAj/WlEhyhRgQNXUYGC2NbTkryJnRSIBEUjEBCAQQFgGh48epmPkLbjj9pzRlNqgO+f z/87D5j4wD4A952rndHtFVPOHFvp704dxtDo5sRcPWfLvFzjpicyhAKPWSQPUkAERkBkBBBERERE RGMYxBBERFQQVVVUREVURgwRERURVVERMQwJ7OnhOa7NSKiKexfaF523DmgCcw+jzqcgHq3Hw1QV pTywJ7woATJE8coFPJD6/MEt/ZPIQWTjYzfGJhUVPmRopwstkgTNMMMwFANYgFGQwxklLIQNI9kZ A3evwDxsqWum9LwgNTjcTjGwORi5wNJKerUGd0sDqTWaHWH8unmN8QzKqmxQatmSKqvCEPhDfIc+ w6g68+Fl3Wmm4Bt1JFR31PfV6wq3PaGLgjHSEVIVdoP9iqq+caPnExMkh8XvZKI0DPH+NOb5R/JO s9UDeqr3JUHMScLLgfX19gz/E+x7wmyZAjPX2PQVeKcc+01DX8zhi9qNjIEDaQyBw38zjaQbLcpY bKYHzcFkEmstseVMIsRSJdEOoCInDh9ZOREU9XKnaHoy4RXwgSIN25/m1uRXo1/Nqu49jaRsR1kd 00GcQ24fam0RCl0rdxsJmhOhnfMkImhslkqXwXgisJrKCoLdprx3PIDsZGFQ1+Kbjk0EAGXtGIYi 7kEhQ46KTvWuXoQZMYlh8DDksx4Z3k/UYGqzEZMs7ABo0QbZugGYTHlNQyUzjUgMSmqK6ghTbOtY H0heqPzhvD829H/Buj0e9LWLuMDy+CO5Y7p1YsR360qlx0DVgqURThCGwRS++EDKO0hUDcyNDaAr EGKAOCySlKkZAq2SaUrQglolEGIQuE3DUaoVRBvVly2FywpJcrGiQSgtRkP0oG7x62H0lGkM0cxO /8C4qmjMR1upM+lAc3qyORk/FuFewSIDPrHpPI7jVjnNEGEd8EJy7tYkQ7h+bgAvMcSiScEqVL9L J6RuTlRSYRwdhTPDITX22CkAgSoR3098YER7VxH20vM+sYS4E2qQ6stKUVjHBFKicXJCJu3bHdZr 7DsHkFGlhu0h9Mk636TNIrCm0PhBpLy6mihkaZpLkgl8SPrHo8BeY7y9jEjvTqo2p86JSqjVDnSA /6qJ3hRJd5KXWWdxXullR0zVzPqfuRL/eflA9vP9ZNQJl/txCwinBzRg3G4JsP3SlIKp2mDlAIcc DlalaOUeCxfI1olU7ShELUiYHBIQEiYhgooQFKwHXQ2hmaqo4R+1iRWMI6PUX7zKHezVhuPVFIfx ciBgkBn2HYaooooREkWKQWJ+6O2fE7JPyhgnHV8/3t7WP80tjv+5bYWrgehJwBFEQmZUA+zATl84 a19BEcQ3k4Qgb/cc4Gkg936zFSEsWBIsWtKczv6qHP81fk++nQGHJnM0D0odPKGIRz6SgtTBMIsY MEfEfBSsD8g6TG+TjfiNCnlcWiOCJiqWKoA17SUFVOIC/S3mVYKmAUCNHBIyKLMxJQriLZHxP2TV OMvmqSOgfipob74imoiB42KIp0eszJsXiZ6Ies927ZuDI91d3fGhvU7j8DpCgYwPlXYgQ8CZVfVJ 4rUl3ENxmZ+iP80ZNT9Thxf3JFiyeY5lvXP7IZgouj0j0lx4cAXV5wpwWFEO8P5IoiSd6dDzKrsq t7z7qzN0KeODCs4Q/3fRSiDIxInAUWisjd0hWrcm+ofxD2BeHxF4AvDQjvChvinPmHPFdf1e8PCO xLMNp8vnOBPVx0EqqmA77BunwpyH/KDIE6i5kJCJEHlbNs4Wyw8yEB4XAXwFgHqDjzBeqqUEXUf3 xcoHCnr6W8rwid5eiNksaUQ9C8HvUjFsQNlAkZ7KhVT6K0f7d4LjM+1DaUUrYqIuf2WAXrPq+UGr zoZKSgivW6B7CFYb5A6/HpGpXg9Vj5rCXZT0ChjnAj0KLRP2UwgYIjJ0PaHnADQxGQ9IddB8wu5c UeD2ecPMHeXgXolwe/z/Kw6Q3zx9imgqZihZYM7UevgFzGImQvEedAsHYnBtmcu4OaTApP3v3tcj pMdkmMLocyefiGxhP39WSRCj2x9v7f0fyWSvxOPvWzx8jvj3Hqghk6iGQ6uSpFGM+AZCj0l0gfrM WSAD9DynQYs+LB9m65n8T7e0oRIx1LYMuL5Pwqj6pD1eb4pCr4R9vpHlPBJ9R6G4ugPCAxnzHmnZ 7JMFGUj/V6eb5OsKC9uA+OhLwfP2o8z7A5VDuPrYFVCFTeQ9BzdOYPoD9XZ4e2hthStL9adgjpS1 3v7ReoTA2R7/aJ8UfCQ+TSruM3mcBom5Id+7+M9B7KicwntdaYnhsOIOc51NckznrKDg9wwYIQhd ZxaMYZg+IxFEpIenaIiId4wMA9iFYSNu3OvFq0CcZxQwOi8SBlA8QsGdt6iaQHpLE8JIpmj7wHWY I5QqUdyR8ROn0/N2eq3crsDGF9is6HlT0l47g6tu8HnFyG1Pfn41rWp0dguXSV9ok5Bk9yTge6eJ 0AHpd9C8iGdKimJrr55xkCbL9w+Bcm2cHt0lkFsHwcR+h8B5z0fObfPp4yJxxS8xl0HuPci9Icj+ Pqrp2j4wpIdz48su0aI+UJ/CH0anekXz4lKFiK08n4PnOR6o+8eBl6Hl3PokNpDs18ZIqPwn2+kk ez4HkjWSNuZmw3J6wnsVeLbxb/RfTaiqVU8sL7sMTmbF0mBjOtSRcpBGoVKF3GKc2+bjmtgbHwPi UwPtHubVe7fG0tTkXvFDlUNcBvPQcY2N4OvHeyhRR91/OsDsDDeHstgRHCGSLD569nfIlkeBZuJ1 HIXOehyd5yxisseQ98fBHRHSQ7uyPRNSe+SPz4nsdBvjzkLsYYwKNyMlkJJMzkiiQo8s4XpE6ucQ 4lTusqbDhEuDMRNvdIQnF3tBPCPwjoyZVmJb10r3+Jgkhhw7vFnGYmbCQxml8p4rqKm1OLl3GtNe M5B4ZxTEyOZAvCuDI0odxdSpngK1O8TUo6hYo8CdHROJ0mgNQatOgQoqkVTTAts/gWOUC6JGh1j5 GXMo+KkYHQ2R84vnvtOifo90T6IfL1P/v7QfJHijdOJ8Xs8vJJ4cCWvnOqTZa/UNXm9XvRrOr5Se 5zPu3SR6yP5lIoUxZvunjAamjoyXTAu0Vsop7me8SJFiUV/tMMnx+bzm/5Zz7+Zg9D7eaKobHwQJ GDfc4D2YAPsD6vUfslZFCd1JJIZkqlLedl/PFJ3IyjFrhOZ7RybRvMY+r14Rg3ux4fUmr5lI3tyM anE7yOMvrCJkpSRJvcjCA7p2PxbAcjkfl4x24szQ8UnJhqpJxiYOF6SKLjZ5R9HcrAYMHGMzxMmG nWHoci+O94IwTaPTpx5PCTB0PFJ80dY801hO6dBzFxaeeLzT+5/H5xFaF9qSkKLSI+5Gh85cjQlx BaUD+YqMgAf/Qf3ntLBesI5FogUclZUkqsagfIfdQuGR+2JnPuITxxEvQyLQtm9uafwh/GlHOQn1 4EQYqI+n8x96Jy46Zvto7RnrMKKE+H5TP+WbkpLnjJje7yKV5bL+U9xkJerFMBT0MYGiIcBvVTf2 4OIf/xdyRThQkLhjL+M= --===============2046976603==--