From: Bjorn Munch Date: March 23 2011 11:55am Subject: bzr commit into mysql-5.5-mtr branch (bjorn.munch:3185) WL#5680 List-Archive: http://lists.mysql.com/commits/133618 Message-Id: <201103231155.p2NBtcda017685@khepri15.norway.sun.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============0938246071==" --===============0938246071== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///home/bm136801/my/resfile-55/ based on revid:bjorn.munch@stripped 3185 Bjorn Munch 2011-03-23 WL #5680 MTR results written to file with well defined format Added --result-file option, which will produce var/mtr-results.txt Output has a simple format: : for general info on test run { : .... } for each test Output from failed tests are included but may be truncated. See WL for more details. added: mysql-test/lib/mtr_results.pm modified: mysql-test/lib/My/CoreDump.pm mysql-test/lib/My/Test.pm mysql-test/lib/mtr_report.pm mysql-test/mysql-test-run.pl === modified file 'mysql-test/lib/My/CoreDump.pm' --- a/mysql-test/lib/My/CoreDump.pm 2011-01-18 10:03:44 +0000 +++ b/mysql-test/lib/My/CoreDump.pm 2011-03-23 11:50:52 +0000 @@ -21,6 +21,7 @@ use Carp; use My::Platform; use File::Temp qw/ tempfile tempdir /; +use mtr_results; my $hint_mysqld; # Last resort guess for executable path @@ -80,7 +81,7 @@ sub _gdb { return if $? >> 8; return unless $gdb_output; - print <> 8; return unless $dbx_output; - print < 'pass', + 'MTR_RES_FAILED' => 'fail', + 'MTR_RES_SKIPPED' => 'skipped', + ); + sub write_test { my ($test, $sock, $header)= @_; + if ($::opt_resfile && defined $test->{'result'}) { + resfile_test_info("result", $result_names{$test->{'result'}}); + if ($test->{'timeout'}) { + resfile_test_info("comment", "Timeout"); + } elsif (defined $test->{'comment'}) { + resfile_test_info("comment", $test->{'comment'}); + } + resfile_test_info("result", "warning") if defined $test->{'check'}; + resfile_to_test($test); + } + # Give the test a unique key before serializing it $test->{key}= "$test" unless defined $test->{key}; @@ -113,6 +131,7 @@ sub read_test { $test->{$key}= _decode($value); } } + resfile_from_test($test) if $::opt_resfile; return $test; } === modified file 'mysql-test/lib/mtr_report.pm' --- a/mysql-test/lib/mtr_report.pm 2011-02-28 15:11:53 +0000 +++ b/mysql-test/lib/mtr_report.pm 2011-03-23 11:50:52 +0000 @@ -34,6 +34,7 @@ use My::Platform; use POSIX qw[ _exit ]; use IO::Handle qw[ flush ]; require "mtr_io.pl"; +use mtr_results; my $tot_real_time= 0; @@ -96,6 +97,7 @@ sub mtr_report_test_passed ($) { { $timer_str= mtr_fromfile("$::opt_vardir/log/timer"); $tinfo->{timer}= $timer_str; + resfile_test_info('duration', $timer_str) if $::opt_resfile; } # Big warning if status already set @@ -301,6 +303,7 @@ sub mtr_report_stats ($$;$) { time - $BASETIME, "seconds executing testcases"); } + resfile_global("duration", time - $BASETIME) if $::opt_resfile; my $warnlog= "$::opt_vardir/log/warnings"; if ( -f $warnlog ) === added file 'mysql-test/lib/mtr_results.pm' --- a/mysql-test/lib/mtr_results.pm 1970-01-01 00:00:00 +0000 +++ b/mysql-test/lib/mtr_results.pm 2011-03-23 11:50:52 +0000 @@ -0,0 +1,167 @@ +# -*- cperl -*- +# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +package mtr_results; +use strict; +use IO::Handle qw[ flush ]; + +use base qw(Exporter); +our @EXPORT= qw(resfile_init resfile_global resfile_new_test resfile_test_info + resfile_output resfile_output_file resfile_print + resfile_print_test resfile_to_test resfile_from_test ); + +my %curr_result; # Result for current test +my $curr_output; # Output for current test +my $do_resfile; + +END { + close RESF if $do_resfile; +} + +sub resfile_init($) +{ + my $fname= shift; + open (RESF, " > $fname") or die ("Could not open result file $fname"); + %curr_result= (); + $curr_output= ""; + $do_resfile= 1; +} + +# Strings need to be quoted if they start with white space or ", +# or if they contain newlines. Pass a reference to the string. +# If the string is quoted, " must be escaped, thus \ also must be escaped + +sub quote_value($) +{ + my $stref= shift; + + for ($$stref) { + return unless /^[\s"]/ or /\n/; + s/\\/\\\\/g; + s/"/\\"/g; + $_= '"' . $_ . '"'; + } +} + +# Output global variable setting to result file. + +sub resfile_global($$) +{ + return unless $do_resfile; + my ($tag, $val) = @_; + $val= join (' ', @$val) if ref($val) eq 'ARRAY'; + quote_value(\$val); + print RESF "$tag : $val\n"; +} + +# Prepare to add results for new test + +sub resfile_new_test() +{ + %curr_result= (); + $curr_output= ""; +} + +# Add (or change) one variable setting for current test + +sub resfile_test_info($$) +{ + my ($tag, $val) = @_; + return unless $do_resfile; + quote_value(\$val); + $curr_result{$tag} = $val; +} + +# Add to output value for current test. +# Will be quoted if necessary, truncated if length over 5000. + +sub resfile_output($) +{ + return unless $do_resfile; + + for (shift) { + my $len= length; + if ($len > 5000) { + my $trlen= $len - 5000; + $_= substr($_, 0, 5000) . "\n[TRUNCATED $trlen chars removed]\n"; + } + s/\\/\\\\/g; + s/"/\\"/g; + $curr_output .= $_; + } +} + +# Add to output, read from named file + +sub resfile_output_file($) +{ + resfile_output(::mtr_grab_file(shift)) if $do_resfile; +} + +# Print text, and also append to current output if we're collecting results + +sub resfile_print($) +{ + my $txt= shift; + print($txt); + resfile_output($txt) if $do_resfile; +} + +# Print results for current test, then reset +# (So calling a second time without having generated new results +# will have noe effect) + +sub resfile_print_test() +{ + return unless %curr_result; + + print RESF "{\n"; + while (my ($t, $v) = each %curr_result) { + print RESF "$t : $v\n"; + } + if ($curr_output) { + chomp($curr_output); + print RESF " output : " . $curr_output . "\"\n"; + } + print RESF "}\n"; + IO::Handle::flush(\*RESF); + resfile_new_test(); +} + +# Add current test results to test object (to send from worker) + +sub resfile_to_test($) +{ + return unless $do_resfile; + my $tinfo= shift; + my @res_array= %curr_result; + $tinfo->{'resfile'}= \@res_array; + $tinfo->{'output'}= $curr_output if $curr_output; +} + +# Get test results (from worker) from test object + +sub resfile_from_test($) +{ + return unless $do_resfile; + my $tinfo= shift; + my $res_array= $tinfo->{'resfile'}; + return unless $res_array; + %curr_result= @$res_array; + $curr_output= $tinfo->{'output'} if defined $tinfo->{'output'}; +} + +1; === modified file 'mysql-test/mysql-test-run.pl' --- a/mysql-test/mysql-test-run.pl 2011-03-11 09:12:58 +0000 +++ b/mysql-test/mysql-test-run.pl 2011-03-23 11:50:52 +0000 @@ -96,6 +96,7 @@ use mtr_cases; use mtr_report; use mtr_match; use mtr_unique; +use mtr_results; use IO::Socket::INET; use IO::Select; @@ -242,6 +243,8 @@ my $build_thread= 0; my $opt_record; my $opt_report_features; +our $opt_resfile= $ENV{'MTR_RESULT_FILE'} || 0; + my $opt_skip_core; our $opt_check_testcases= 1; @@ -318,6 +321,14 @@ my $opt_parallel= $ENV{MTR_PARALLEL} || select(STDOUT); $| = 1; # Automatically flush STDOUT +# Used by --result-file for for formatting times + +sub isotime($) { + my ($sec,$min,$hr,$day,$mon,$yr)= gmtime($_[0]); + return sprintf "%d-%02d-%02dT%02d:%02d:%02dZ", + $yr+1900, $mon+1, $day, $hr, $min, $sec; +} + main(); @@ -422,6 +433,11 @@ sub main { my $server_port = $server->sockport(); mtr_report("Using server port $server_port"); + if ($opt_resfile) { + resfile_init("$opt_vardir/mtr-results.txt"); + print_global_resfile(); + } + # -------------------------------------------------------------------------- # Read definitions from include/plugin.defs # @@ -624,6 +640,7 @@ sub run_test_server ($$$) { $savedir); } } + resfile_print_test(); $num_saved_datadir++; $num_failed_test++ unless ($result->{retries} || $result->{exp_fail}); @@ -646,6 +663,7 @@ sub run_test_server ($$$) { } } + resfile_print_test(); # Retry test run after test failure my $retries= $result->{retries} || 2; my $test_has_failed= $result->{failures} || 0; @@ -929,6 +947,49 @@ sub set_vardir { } +sub print_global_resfile { + resfile_global("start_time", isotime $^T); + resfile_global("user_id", $<); + resfile_global("embedded-server", $opt_embedded_server ? 1 : 0); + resfile_global("ps-protocol", $opt_ps_protocol ? 1 : 0); + resfile_global("sp-protocol", $opt_sp_protocol ? 1 : 0); + resfile_global("view-protocol", $opt_view_protocol ? 1 : 0); + resfile_global("cursor-protocol", $opt_cursor_protocol ? 1 : 0); + resfile_global("ssl", $opt_ssl ? 1 : 0); + resfile_global("compress", $opt_compress ? 1 : 0); + resfile_global("parallel", $opt_parallel); + resfile_global("check-testcases", $opt_check_testcases ? 1 : 0); + resfile_global("mysqld", \@opt_extra_mysqld_opt); + resfile_global("debug", $opt_debug ? 1 : 0); + resfile_global("gcov", $opt_gcov ? 1 : 0); + resfile_global("gprof", $opt_gprof ? 1 : 0); + resfile_global("valgrind", $opt_valgrind ? 1 : 0); + resfile_global("callgrind", $opt_callgrind ? 1 : 0); + resfile_global("mem", $opt_mem ? 1 : 0); + resfile_global("tmpdir", $opt_tmpdir); + resfile_global("vardir", $opt_vardir); + resfile_global("fast", $opt_fast ? 1 : 0); + resfile_global("force-restart", $opt_force_restart ? 1 : 0); + resfile_global("reorder", $opt_reorder ? 1 : 0); + resfile_global("sleep", $opt_sleep); + resfile_global("repeat", $opt_repeat); + resfile_global("user", $opt_user); + resfile_global("testcase-timeout", $opt_testcase_timeout); + resfile_global("suite-timeout", $opt_suite_timeout); + resfile_global("shutdown-timeout", $opt_shutdown_timeout ? 1 : 0); + resfile_global("warnings", $opt_warnings ? 1 : 0); + resfile_global("max-connections", $opt_max_connections); +# resfile_global("default-myisam", $opt_default_myisam ? 1 : 0); + resfile_global("product", "MySQL"); + # Somewhat hacky code to convert numeric version back to dot notation + my $v1= int($mysql_version_id / 10000); + my $v2= int(($mysql_version_id % 10000)/100); + my $v3= $mysql_version_id % 100; + resfile_global("version", "$v1.$v2.$v3"); +} + + + sub command_line_setup { my $opt_comment; my $opt_usage; @@ -1068,6 +1129,7 @@ sub command_line_setup { 'max-connections=i' => \$opt_max_connections, 'default-myisam!' => \&collect_option, 'report-times' => \$opt_report_times, + 'result-file' => \$opt_resfile, 'unit-tests!' => \$opt_ctest, 'help|h' => \$opt_usage, @@ -3606,6 +3668,18 @@ sub timezone { # Storage for changed environment variables my %old_env; +sub resfile_report_test ($) { + my $tinfo= shift; + + resfile_new_test(); + + resfile_test_info("name", $tinfo->{name}); + resfile_test_info("variation", $tinfo->{combination}) + if $tinfo->{combination}; + resfile_test_info("start_time", isotime time); +} + + # # Run a single test case # @@ -3618,6 +3692,7 @@ sub run_testcase ($) { my $tinfo= shift; mtr_verbose("Running test:", $tinfo->{name}); + resfile_report_test($tinfo) if $opt_resfile; # Allow only alpanumerics pluss _ - + . in combination names, # or anything beginning with -- (the latter comes from --combination) @@ -3823,6 +3898,7 @@ sub run_testcase ($) { # Test case suceeded, but it has produced unexpected # warnings, continue in $res == 1 $res= 1; + resfile_output($tinfo->{'warnings'}) if $opt_resfile; } if ( $res == 0 ) @@ -3839,6 +3915,7 @@ sub run_testcase ($) { # Test case had sideeffects, not fatal error, just continue stop_all_servers($opt_shutdown_timeout); mtr_report("Resuming tests...\n"); + resfile_output($tinfo->{'check'}) if $opt_resfile; } else { # Test case check failed fatally, probably a server crashed @@ -3900,6 +3977,9 @@ sub run_testcase ($) { # Save info from this testcase run to mysqltest.log if( -f $path_current_testlog) { + if ($opt_resfile && $res && $res != 62) { + resfile_output_file($path_current_testlog); + } mtr_appendfile_to_file($path_current_testlog, $path_testlog); unlink($path_current_testlog); } --===============0938246071== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/bjorn.munch@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: bjorn.munch@stripped # target_branch: file:///home/bm136801/my/resfile-55/ # testament_sha1: c8801f4f588d041631b1b87deafe77e4073bdd65 # timestamp: 2011-03-23 12:55:38 +0100 # base_revision_id: bjorn.munch@stripped\ # nzzli1y1ju09jc5s # # Begin bundle IyBCYXphYXIgcmV2aXNpb24gYnVuZGxlIHY0CiMKQlpoOTFBWSZTWc/GH+YACZFfgHA0f//////v //+////+YBR/eHtrPbPOy4u7wHa96e40AUAbzvD091zS6da6TYO6bkHSg6UFSPbO7uoAdbhKETRN MmmqeyNDQRGaTTaKNpkhptAjJ6h6eppPSYTxTAlCAJoBDQQFT9Cn6UPSeQnqHqNB6nqPUZHqAAA9 QaaE0IJMTSaGmI9T0gepo9TIyAaAAAABoAkJJoSnkRiYKaZiam0npoQxNMgyA0yNHqAGgNDmTTQy ABiMgyAGmCBiAaNNABkDQAJFNEBNDRoRoNGhNNMhNMpsk2oyAeoGgAADKtbT8BZACbBhxGrQYxo2 62cq/4+d11B/4jG2hpHHD1cBx9fsmlq6zabDOQY1+v4afVrfwUTkx7t/v6W9qk58OxZ5LpbdURtv J6qjVMIujjQinsSPYMce1bBjH+8I21fCK7Q2gLMRZkoKpUDG0tZPVo7dw5uiTH8YjkN+0w2f9bvr GxuQrg1ldxxNTRIReqIgBnIprmCx2F5Dh5SlOFfExfI90puCyq8cRti51NBNk3YEsOViJC5W2Ltx BIWILiGCbDt3hSoiNlpYLaWFdZ2Ly+mLFiD0MFvaALWmwXzuGLp+nu6Coglw/xIwGNzNLghHy0y0 V1XLFAJG5yA6NipKBNVClABCXKAnUFYYHmBSZrYpahknZIUphURDTH0isQjNcHwavPkI+GPhihUF 7Yi7QfbnTGsblfT+9bT4yO7Lq/jaEnoX4/zD5gYDabTaE2bgRyY3f+9YIzWbPiCPT8PqbiW2RnIq emRR3Z+k+idJ8kjDx7KmujQwsVQ1yiURVXmRaQLzBEi85NWKXsuTncbntKVcGK20ubisobSfA4Ga s+TAhQOTex5Diwo5M9mjcLk3btRKdeWCxju+z8eWDGro2b4a42j2OxP15FBvcitiaHgR7Oz2Occl F5yYEwIUdcw1FRy/yhBxt224acodF9izf+GdbpSdgrzGHNq1R//OdcdLDH4zrNKkbG+b6h9KeRnz ZlGM5bmoXTMftjHFkL5C6S9h7OF9ScqRgL2PhIxSWs0UjrlL0OOB3WtadFBrYaluh/qPVSs9lc5I IbbZiIqFp64z6UdCobyXptrfGh9HGmNVVZ16MUUDXtzhKDAh5PY8tfCojPbbJpASLnIbIlKxqQ24 alJ0z7v+UNz7rANIr54W5jTWw40mYcslR5Z7lvvkWM0POIsKbclWONu2DNIusybKvZRh+0CK3xAZ lN/V40tamzUZrVfRtCV7+Yh9CkNF1A0cfi42fKvD4nNFXQHJYVnF5UGjdMsx6VDmLMFhnWv5nsQm uMg07NPZgb+OcpiIH8YKGFS0OLMEELtjcHZEUHIwb3a29iNF30KSshtIYMEwGhU5D5UB8zByJDsL zsG1AG/o81UU4NLssAbjI3I2gGaIJamUz0tR5O1NnmZQSRjQ2AxlP4W2FXxKWWcPH5PLHSWh/Emt vuLThY2t/e3beO82WmGUieiB9dQ6nPp5aB4wbu3qPANCbQxobSbTcqzbUj4JOF6cIWYQbR15lQoW h4aKPBBU6ds+98+jgQPueHXOV5Z7Mb15WNpYt65I6Gt7GJDv9GuiLGFzKPLNKjlVSPwycINV1Qsq 8tWI4Ht4bm5E8eCTbQ5uVuqk54jfmVLgQ2+e3XOAiJctyk9j6o+iM4zLqOUUs10Hxbve3w6CzGD2 BhiH0JC7usS2VEHyOzSmhphM/7CzvQfE7iNKGN+6j6tHd3/JTtECO7PXOcF+4fseY0uyLLTtzudb rURjazabyl85XiRnSReMtkbmMkFO+R6apo7CZ3kE91yPqrPSbyMhrSWoXS+pnGcgNbBtCpt2yopg hu0jIx8cXoVDZiBw2rqVfABWWWeAWwzusz6kIs5VRhQCpYZgqMYnuuH4CJAShSxgMPSA5qgs2eTH vLiR+dGRHhhM995UqRwItmQtrVDykWVRDC/FwVUerWhdCAIXUP3V+5xaPtUuHB8WkiWcnBAD8Dz6 6fk016smtYwR6DKgMSyvID7r2JhybTNmlW5mvbnxJ7VMLiCJ+9DVOsf5s73TREjeDWfAWb6ZWNyv 8VM0edTuqhIuJED2269ULjVDgeQuOjxN/Q8iaEExvu6Bxbs0fBtbYLSj430URNFi7oBBURBQsaU5 cudCQpCzjEFeIknmT1FvU5rMUywaskl9p+Ti0WFTKCtuUDSxoSeYnVBD1eoU9Rb1a6Yvc5HTdxi7 HDAkFHCuOsfpSbhE1YJmc6PEDZpP64HPvgPIp1KYCnHAax3YMOFvZLy9sMDx0rUf4GyInI348ZYP dx4DvJ9lVghMU1RNJzKA9B7EEZOSwqQHKRTedhBxFdLiA8a44u+ItkpEgt0gPIVRycd51Gs1UpZZ 6zefOdglqN2ReW46pOWyxB4iWMTgRhDmUAKdTwqryo7eO8ESOLj9WHCYX9BpEiJ8SBf6BjGHnp1l jrkby8gdYieUgljdhEv2fpY0dHEjMdAWTCjLyUiaFhvJWFJHN1qpJTjxRLGO8gOOQ8LMZ+U7/OdD cPORu0rvtguqx4I8lJ+UwiPzFN285ldS5VrcpaV6lh0txw4Ij9gvGTceXPHDJdcJxXNoLm8VIQRT wUmLE0xZKulWSvuHXtTV+JrcQ3SywhrEvJnaIikhbpaRziPgTQiNE3C53saYG8gxo/CtRiR4OvLk YsNeK4mZikQgcmGSGJ4TQExMo5qh/kx9n4g10N8wMaYQjFY7oKyL0kzF4C0gY5PXO/dzUyZUex2W 42rFSm62+Ntk7bDdahtKbRZbu07O9wcFQpXtMgRJkCwiizYENJhO9RmhdmTWDDYu5n77a2ynAh3g hJHNuEb1tnbTbY9mUy3+Mqi15aunZh9njiZr87tgbGNVo74cDbAWZMFloPXnRojOOy8QA9ATm2hE Fbp+jVer5e5+z/9XZyr844wwqtSoqCqKb3w5+OHZJ1utIRKkt+qt1b3X6KNaSXgLqhH7/yZD81RT cKQCuioXJhxOgdmSFbyZ52/TKixIMpaC2vtmvHajmkGSe0zymZVWt/1yXIgO5ZNeiXxE/hzsGcyi 0QlWEGhQCXzs5QxnVUKef44dtMnStp6VBoW45hXJp7kuKFSwU0qTuw0K+noxcNWogpS2JHDCmsFF Hp5eXq2P5YNb5mlv64KcAqZalygrvIhypz+GIPO+8m0IGvTvpuikNMQ0hisP0MoNeqxkCZUNElRo Oi6f20UlQkbRnxGJpNxMAvq6FxKzPFjoqqblNseQic7WvRGmNM6CU4B7f0H6zAE95+UVx9PAkOPc PNPpPg3wMJSFOHHQXkuVERB9jRvceA6yG3SYHlH+8VGFHBeIgOQGMxg2q1aqC2XVDe9CusixfeNU EyfJdkNc5OJKgjkZD5EJ1Qs0omVQ+euh3EzYYjiu6T73QORqQqcC5HHMWJJD3ftESpH9hEU+Bkcz uOcyRt5AENLObOskTPel5HpE0S+V61BD0F5gYTIM5h9aQOpRD4KSB45bd0qM1hTY/UYar5cOlJA4 S7Oouq5Wd52Bicug4ZtZ6+JFfPA8/IDpRxJJDwPkaNPPhYWqxyQKy3uJdYD/aJHvMxgc2eL/VFi7 afaR0Vmt4tdMR+iTulozeArm9JskbVM2q79CdpTcJhRaFdm9qIVCw7Du4SOm+pKiXbL3Ei8okMuw fGs1mkkrdn5ilScWUz4CvDNYpujn49Sp4DvYFoenEJPvDRCvRSsyMhEec2mk1m/1mdXmvtwIO8+c 6MbeO2azOVKBBVmkGHpb5R6HRYLIjo8N9o60IOeqXSfROD77ukr7x431toftZocDJD0OGVWZ4bSF 6z7huJ2eYzeqzJ1Pb3lZeMNR2lQBkzHnQ0S1m3uFlXFABNAFATeohDJkZOwlz5mBiTM48JA/7Zja B33MFdlpTWGKZKV02uetbnK3UZIwp61Xp57+mS8MTxEShdW6LYyElzcMDyMuHVVpXR2Mbc+M3e/T kmS1smV5FXF0JtlDYFSWYGlamgkBoJAMzsFM2Dd/ePCO6UW8qOMRppalKanmJfodVlKIwOMgSFpA ZPTWJB8WARMkAz4sQEXZYkgmgvYF2YzDCx0uBbdpQ9E6xBJia+UlsNk9x3C7CfgfNB5lMPIrPTjj 1TL7+xWpT84SNIo86uOU+lHuMJzhkDbVdpEQJRDARnkjfLeD3VQhUl/zFsaIF3tiofM9MkDsOaWm 4fp816AsnDvWDFL8Yj4qgXlCG5lZiQPcJm8lwhmLUZ8hw7bjTj9wqCQ3QLTB9y0WREjZwC9LE5iG VgHylS+eFjvm0esiZ1mXmnwEk1rXN6hnoUNgxp/nDdLa+UOxpC8FUl3EViH6KL1s1TIEgk4Gxpyo zaggoAAy9NqOLwhmUQmm0rTBvwLx4x1AcgF5CS2yCoE4lN7bJLlk2yikCqbaXh5d13At1poY2gYZ 9KPfecicvoMcQJqoeLGV6fI5UUjbx0Ivgg0exch5jyPpL/soJFp4LpPs5BLsO89gw4jPE9BYbTtA 3WCXN3FDkLuBwJ2VBcuYG231xayj5aCET6ag9UBwsStgK0UVYyxGDFa+t7xoUxIaLuoo5AIKgghc sBj0GIvYagd2MReKU2C5Mem6b5yMmfHu3URu6RLQAjbPx5Li+asQjlSzyEFUxdIyrNIYaglEghJj Eu3gUgN4vm3b7SgaArTQVEhHwB6BgsPFmkzdZH0ncRQtoRGL33JS4TgZiho3fOVajEh5kfWJDOzn JfM0f5YQP1tciutyTiEvAyxerYOJa4iJbJE5zggCF8kDJtNnbMSK1Sdg6jvJWDRRhZwMHoFnPwXH xwL3oYkTUovcEDAmpHkU+q7QVolOxEQXg+ghAFGWsKj0GWQTVMAOssLgZaFSBtibBg+BIiGDqRNp Y4Urdg0KGyauZ+VhKiTBHbPEd08RKa84ipQAjAkB5/DYuSkmngYWQjZWWIIQxIaZqK5I9rIVrCp3 uTM7EUppvgmMZNGdyb3El9LSO0xjTYlhn6ZtDOxERg+Yi3emXCRrAmc5kXXncUFuSR6krFl7ubmX WLTpW4Dm/pvx9h5GyY0udcrbf1qSCTA3HJGJuMSyj0yBpHFlebxvr4UQ0sOFwGyo7uZwSxlicT2I sGIsR77O27Ks0h7DFSZKQZRr8CSyoG0KS1AkU60AWQaRKt/AwKIWR7TxPNeLoGtpmtavUpCDKFsb 14ORvhM7t4F77+OsM4i6SkEY0okwHU2/toJKYWk18ONlM5JGosCxHVIknqTLDjGAy61LETaW9v+Z wXEuVjyKWoa6rQFAI5uCI8rnkginTD4BwabH7Rjx2NR0C1iQX1a10qWAxSAsw8IFia3kSrl105wh aEGwaDsN5MtZIUnzoGJF4VUa9o1zAYSQe0sEFYmB7CVwoOgiGXoY5PRlgE1+IpUy47qVD8EnKWuJ ZnZQggxnVHN8koxnop2GVsW6IFEGsBaFQMEktLAXTLVryNhk3PCT2Ta57Xprq57u5mV5DEghCxMb tFaM/mK0uyeUblUk05o7NZkLydtLS20tVBe9tt1UPHtQsUGttlKpJRqJASYhFbmNHJqA8rOJeTSS eYRGsVlBBAplkYCI/X5FOjs/S9PTFpJBc6I9XZAcThbUKTIBOnOQWazkqMQUuIDuYua3DRlfRdWw kcGTIqrkaihBTGZV2MXOszPC9GHwnE87Far3JYJqC2ql7bYZoCFbTMgmmVjaMhKF00ldDaGGeDaj hEr6V5R65f4zQLOwrWlXuawZOUnzYPdDRsGNNNIwJMWnhDJiIDdIhwTBPRl2507qkl0jmP3E9Ghz bvJd8RguuRpnzkhLVvZeje4GfV6Tl3X8xmQdrULECpByLegCRrPQJMFzwlwoayuZcdC3xI6mC31J UNOTEdKPeXqqzE9KNJgJetb5LqVaXmIM1o5JGdibBF/97DNiL924SLjYg8BeRf7ChccUHEEt/ild 19T2mcxEtwZtzkDZJkgbaBjSL7yZMPgDQLeY8hBzJahzPukkGnTjJeRKIJEsDxLz7vHnz8eClBcX Xqm8iLrAO8dh0khj9xKSLFZY/G9UaR5pYEHQzoPI0VnTyiXCfSu4zWH7uBqCbUExJnaTpkCCq/wl tTF0HrEY+VJj0PNwiRKnbw6zNUheJ+EqvmsTgdJ1C4GNDtW42fhNRctQjzjY222Ld6vr+xC3mvXj imNI+R+MoJy1yGlo530XTBaf+LuSKcKEhn4w/zA= --===============0938246071==--