From: Martin Zaun
Date: January 8 2011 5:46am
Subject: bzr push into mysql-5.1-telco-7.1 branch (martin.zaun:4042 to 4043)
List-Archive: http://lists.mysql.com/commits/128213
Message-Id: <201101080547.p07LhjZf017567@rcsinet13.oracle.com>
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="===============0551424447=="
--===============0551424447==
MIME-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
4043 Martin Zaun 2011-01-07 [merge]
merge from ndb-7.1-dbg64 to ndb-7.1
added:
storage/ndb/test/crund/process.sh
storage/ndb/test/crund/src/com/mysql/cluster/crund/ResultProcessor.java
modified:
storage/ndb/test/crund/build.xml
4042 jonas oreland 2011-01-06 [merge]
ndb - mege 70 to 71
modified:
storage/ndb/include/util/Bitmask.hpp
storage/ndb/src/common/util/Bitmask.cpp
storage/ndb/src/common/util/Makefile.am
storage/ndb/src/ndbapi/trp_buffer.hpp
=== modified file 'storage/ndb/test/crund/build.xml'
--- a/storage/ndb/test/crund/build.xml 2010-10-08 11:17:35 +0000
+++ b/storage/ndb/test/crund/build.xml 2011-01-08 05:43:07 +0000
@@ -293,6 +293,8 @@
+
=== added file 'storage/ndb/test/crund/process.sh'
--- a/storage/ndb/test/crund/process.sh 1970-01-01 00:00:00 +0000
+++ b/storage/ndb/test/crund/process.sh 2011-01-08 05:44:51 +0000
@@ -0,0 +1,4 @@
+#!/bin/bash
+echo "running result processor..."
+java -classpath build com.mysql.cluster.crund.ResultProcessor $*
+echo "done."
=== added file 'storage/ndb/test/crund/src/com/mysql/cluster/crund/ResultProcessor.java'
--- a/storage/ndb/test/crund/src/com/mysql/cluster/crund/ResultProcessor.java 1970-01-01 00:00:00 +0000
+++ b/storage/ndb/test/crund/src/com/mysql/cluster/crund/ResultProcessor.java 2011-01-08 05:44:51 +0000
@@ -0,0 +1,418 @@
+/* -*- mode: java; c-basic-offset: 4; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=4:tabstop=4:smarttab:
+ *
+ * Copyright (c) 2003, 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 com.mysql.cluster.crund;
+
+import java.util.Properties;
+import java.util.List;
+import java.util.ArrayList;
+import java.text.ParseException;
+import java.text.DecimalFormat;
+
+import java.io.FileInputStream;
+import java.io.FileReader;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.InputStream;
+
+
+/**
+ * This class parses and processes the result files of the Crund benchmark.
+ */
+public class ResultProcessor {
+
+ /**
+ * This class reports the results of the Crund benchmark.
+ */
+ public interface ResultReporter {
+
+ /**
+ * Reports a data series.
+ *
+ * @param tag a name for this data series
+ * @param op the names of the operations
+ * @param avg the average values
+ * @param avg the standard deviations
+ * @param avg the relative standard deviations
+ */
+ void report(String tag,
+ String[] op,
+ double[] avg,
+ double[] sdev,
+ double[] rsdev);
+ }
+
+ /**
+ * This class reports the results of the Crund benchmark.
+ */
+ static public class SimpleResultReporter implements ResultReporter {
+ static protected final DecimalFormat df = new DecimalFormat("#.##");
+
+ /**
+ *
+ */
+ public void report(String tag,
+ String[] op,
+ double[] avg,
+ double[] sdev,
+ double[] rsdev) {
+ out.println();
+ out.println("tag = " + tag);
+ out.println();
+
+ // ops with large deviations
+ final double thres = 10.0;
+ final List problematic = new ArrayList();
+
+ for (int i = 0; i < op.length; i++) {
+ out.println("op = " + op[i]);
+ out.println("avg = " + df.format(avg[i]));
+ out.println("sdev = " + df.format(sdev[i]));
+ out.println("rsdev = " + df.format(rsdev[i]) + "%");
+ out.println();
+
+ if (rsdev[i] > thres) {
+ problematic.add(df.format(rsdev[i]) + "%\t" + op[i]);
+ }
+ }
+
+ if (problematic.size() > 1) {
+ out.println("operations with large deviations:");
+ for (String p : problematic) {
+ out.println(" " + p);
+ }
+ }
+ }
+ }
+
+ // console
+ static protected final PrintWriter out = new PrintWriter(System.out, true);
+ static protected final PrintWriter err = new PrintWriter(System.err, true);
+
+ // shortcuts
+ static protected final String endl = System.getProperty("line.separator");
+
+ // result processor command-line arguments
+ static private final List propFileNames = new ArrayList();
+ static private final List ilogFileNames = new ArrayList();
+
+ // result processor settings
+ protected final Properties props = new Properties();
+ protected int warmupRuns;
+ protected int hotRuns;
+
+ // result processor resources
+ protected ResultReporter reporter;
+ protected String[] header;
+ protected String ltag;
+ protected int nval;
+ protected double[] ravg;
+ protected double[] rdev;
+
+ // ----------------------------------------------------------------------
+ // result processor usage
+ // ----------------------------------------------------------------------
+
+ /**
+ * Prints a command-line usage message and exits.
+ */
+ static protected void exitUsage() {
+ out.println("usage: [options] ...");
+ out.println(" [-p ]... a properties file name");
+ out.println(" [-h|--help] print usage message and exit");
+ out.println();
+ System.exit(1); // return an error code
+ }
+
+ /**
+ * Parses the result processor's command-line arguments.
+ */
+ static public void parseArguments(String[] args) {
+ for (int i = 0; i < args.length; i++) {
+ final String arg = args[i];
+ if (arg.equals("-p")) {
+ if (i >= args.length) {
+ exitUsage();
+ }
+ propFileNames.add(args[++i]);
+ } else if (arg.equals("-h") || arg.equals("--help")) {
+ exitUsage();
+ } else if (arg.startsWith("-")) {
+ out.println("unknown option: " + arg);
+ exitUsage();
+ } else {
+ ilogFileNames.add(args[i]);
+ }
+ }
+
+ if (propFileNames.size() == 0) {
+ // XXX propFileNames.add("crundResult.properties");
+ }
+
+ if (ilogFileNames.size() == 0) {
+ out.println("missing input files");
+ exitUsage();
+ }
+ }
+
+ // ----------------------------------------------------------------------
+
+ /**
+ * Creates an instance.
+ */
+ public ResultProcessor() {}
+
+ /**
+ * Runs the result processor.
+ */
+ public void run() {
+ try {
+ init();
+
+ for (String fn : ilogFileNames) {
+ out.println();
+ out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
+ out.println("reading log file: " + fn);
+ out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
+
+ BufferedReader ilog = null;
+ try {
+ ilog = new BufferedReader(new FileReader(fn));
+ process(ilog);
+ } finally {
+ if (ilog != null)
+ ilog.close();
+ }
+ }
+
+ close();
+ } catch (Exception ex) {
+ // end the program regardless of threads
+ out.println("caught " + ex);
+ ex.printStackTrace();
+ System.exit(2); // return an error code
+ }
+ }
+
+ // processes the log file
+ protected void process(BufferedReader ilog)
+ throws IOException, ParseException {
+
+ int lineNo = 1;
+ String line;
+ while (true) {
+ line = ilog.readLine();
+ if (line == null) {
+ return; // eof
+ }
+ lineNo++;
+ //out.println(line);
+
+ // skip comments
+ if (line.startsWith("#")) {
+ continue;
+ }
+
+ // parse empty line
+ if (line.equals("")) {
+ if (header != null) {
+ report();
+ }
+
+ header = null;
+ ltag = null;
+ ravg = null;
+ rdev = null;
+ continue;
+ }
+
+ // parse header line
+ if (header == null) {
+ header = line.split("\\t");
+ assert (header.length > 0);
+
+ nval = 0;
+ ravg = new double[header.length];
+ rdev = new double[header.length];
+ continue;
+ }
+
+ // parse value line
+ final String[] values = line.split("\\t");
+ if (values.length != header.length) {
+ String msg = ("line # " + lineNo
+ + ": wrong number of tokens; "
+ + "expected: " + header.length
+ + ", found: " + values.length);
+ throw new ParseException(msg, 0);
+ }
+ nval++;
+
+ // parse line tag
+ if (ltag == null) {
+ ltag = values[0];
+ } else if (!ltag.equals(values[0])) {
+ String msg = ("line # " + lineNo
+ + ": unexpected line tag; "
+ + "expected: '" + ltag + "'"
+ + ", found: '" + values[0] + "'");
+ throw new ParseException(msg, 0);
+ }
+
+ // parse numbers
+ for (int i = 1; i < values.length; i++) {
+ long l;
+ try {
+ l = Long.valueOf(values[i]);
+ } catch (NumberFormatException e) {
+ String msg = ("line # " + lineNo
+ + ": " + e);
+ throw new ParseException(msg, i);
+ }
+
+ // compute running averages and squared deviations
+ final double v = l;
+ final double oavg = ravg[i];
+ final double navg = oavg + (v - oavg) / nval;
+ final double odev = rdev[i];
+ final double ndev = odev + (v - oavg) * (v - navg);
+ ravg[i] = navg;
+ rdev[i] = ndev;
+ }
+ }
+ }
+
+ protected void report() {
+ // result data
+ final int nops = header.length - 1;
+ final String[] op = new String[nops];
+ final double[] avg = new double[nops];
+ final double[] sdev = new double[nops];
+ final double[] rsdev = new double[nops];
+
+ // compute results
+ for (int i = 1; i <= nops; i++) {
+ op[i-1] = header[i];
+ avg[i-1] = ravg[i];
+ sdev[i-1] = Math.sqrt(rdev[i] / nval);
+ rsdev[i-1] = (sdev[i-1] * 100.0) / avg[i-1];
+ }
+ final String tag = header[0] + ", " + ltag;
+
+ reporter.report(tag, op, avg, sdev, rsdev);
+ }
+
+ // ----------------------------------------------------------------------
+ // result processor intializers/finalizers
+ // ----------------------------------------------------------------------
+
+ // initializes the result processor's resources.
+ protected void init() throws Exception {
+ loadProperties();
+ initProperties();
+ printProperties();
+ reporter = new SimpleResultReporter();
+ }
+
+ // releases the result processor's resources.
+ protected void close() throws Exception {
+ reporter = null;
+ props.clear();
+ }
+
+ // loads the result processor's properties from properties files
+ private void loadProperties() throws IOException {
+ out.println();
+ for (String fn : propFileNames) {
+ out.println("reading properties file: " + fn);
+ InputStream is = null;
+ try {
+ is = new FileInputStream(fn);
+ props.load(is);
+ } finally {
+ if (is != null)
+ is.close();
+ }
+ }
+ }
+
+ // retrieves a property's value and parses it as a boolean
+ protected boolean parseBoolean(String k, boolean vdefault) {
+ final String v = props.getProperty(k);
+ return (v == null ? vdefault : Boolean.parseBoolean(v));
+ }
+
+ // retrieves a property's value and parses it as a signed decimal integer
+ protected int parseInt(String k, int vdefault) {
+ final String v = props.getProperty(k);
+ try {
+ return (v == null ? vdefault : Integer.parseInt(v));
+ } catch (NumberFormatException e) {
+ final NumberFormatException nfe = new NumberFormatException(
+ "invalid value of property ('" + k + "', '"
+ + v + "').");
+ nfe.initCause(e);
+ throw nfe;
+ }
+ }
+
+ // initializes the result processor properties
+ protected void initProperties() {
+ //props.list(out);
+ out.print("setting properties ...");
+ out.flush();
+
+ final StringBuilder msg = new StringBuilder();
+ final String eol = System.getProperty("line.separator");
+
+ warmupRuns = parseInt("warmupRuns", 0);
+ if (warmupRuns < 0) {
+ msg.append("[ignored] warmupRuns: " + warmupRuns + eol);
+ warmupRuns = 0;
+ }
+
+ if (msg.length() == 0) {
+ out.println(" [ok]");
+ } else {
+ out.println();
+ out.print(msg.toString());
+ }
+ }
+
+ // prints the result processor's properties
+ protected void printProperties() {
+ out.println();
+ out.println("result processor settings ...");
+ out.println("warmupRuns: " + warmupRuns);
+ }
+
+ // ----------------------------------------------------------------------
+
+ static public void main(String[] args) {
+ System.out.println("ResultProcessor.main()");
+ parseArguments(args);
+ new ResultProcessor().run();
+ System.out.println();
+ System.out.println("ResultProcessor.main(): done.");
+ }
+}
--===============0551424447==
MIME-Version: 1.0
Content-Type: text/bzr-bundle; charset="us-ascii";
name="bzr/martin.zaun@stripped"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: martin.zaun@stripped
# target_branch: file:///Users/mz/mysql/ndb-7.1/
# testament_sha1: 82cefc6d384de2fd651eb982bfaff9c08f7dd9a8
# timestamp: 2011-01-07 21:46:38 -0800
# source_branch: file:///Users/mz/mysql/ndb-7.1-opt1/
# base_revision_id: jonas@stripped
#
# Begin bundle
IyBCYXphYXIgcmV2aXNpb24gYnVuZGxlIHY0CiMKQlpoOTFBWSZTWaOzlloADSr/gGf0ZJF+////
/+fe/r////5gFr12+nfbdPfOlUT3ti8bu9s+vb1OgAWd2909t959Fz2+b26+tz6Zd32uXbXPTu7j
UXe6rbq29sL69713Zduwn2wkk1GppiCNpT9AmRkNMRpTwpo2gmg9TIBoGho09I9QCSICACZExFNp
qZqnqbUfqnqDEZNBoAAGgADIDTTSEaaqfqmTTRkZAGIAyYQ00aAAAAAGjQJCRECGgRimaZTyTymh
tRmkaMjTI00AyGmg0DIAiUJoQmTQBT1PJpqeKZJ7VPTU/UhmjSA8Ueo9R6gABoMgkSEASZpNPQTU
YVPbVT2mRPJT0gAAAND1AAAGkQkll8nmQ/0Zt+1z/83/rVMphExuSmUpFBmZMzMTSvt6kv39g+w7
hubo6oc/TbOkj0W7qXr7oYWQZZBLWgVH3Icj8nWCF9MGlBh0IKjAkEgkknYFiLBbpYbV4VQeZ1ls
qHUE2MayuVJ2XE5wq22XQQFt1oM9MUVpYHqZYENSLaqDnTc38LYGLkkd2QaaCmmfrBc/BmMCzY2j
Fymm1HIoNNvGJRgn7oNaWqblB58nCMN491eLz1XjchUnKK92NizvaKs4mfN5KpNDARYRdv5s5ovn
i2hySATTi8lQ6LvNxgiJuBBAAcLsEuSGxSBLeGAIqRIF+TBAowXAc2T0NutRVisY6ijzptTdizSD
+YFoYbOrMZTPYX+W1FSKhhmoDVCCq3TgesobEdjzYBBrl0f4iJbkZsQav7EqwW8wtkxTQ0VOv552
EzVfMx05FftyB3Cx2ViJ2sxsOuOPa8NLSR2sUU7luwTaomeXZap2bpTrbBOD4JFyZGMykpq3B9Jw
oIlIrQujRgPnGeg9J4p5Y3uQVCdAOiWQduxOShX0SnhgdyPk/h9H5V16vMvVYZmX8aRMq18GB/5K
wpdyU714Sq8Lo/W0eCnIcd3ZPbZH12xlo8ondVUYTiCMCxHH+fT4TtWrAvYch0oRiDLI6fd/7ic3
sdRQtes1vlwyXk0etkPL5vdXQ4LvJsNk8LvTin0i/sq1XGZpcVPnqlMY7UcyeSLL+LNHKZe0J2qd
4xDBoUKSGFxUVkzy96zLZuyKtxuZK/MGFkBJPmKefPCVp5qOcDPhDdi9n7LfiV2pw0kyRlwwNW7S
ylXwmTorZ6aqUHOR6eN1E+FN6aqv0+E5AdKaR0Rlpn4NJY00k0YXDvr5PuoMtO1c/PyKXae3XKb7
qaOymWmMVLoe1vGLTAJmLTn/e+OPRukOyI+JiA+8Bmvzq+eavqdXcjKQ47JhYMnDUXdeuVJwUMi0
r7cHnTN1dxYcwEzJcd8GrWZSvgRzHonbt8V5SnznDhbFDJ5GBGLzpxfD5jK7s7bgu3EJlpfXN4GN
unTGkx1ibbcQjNi1XGk44gaaPe0h3eTreMsSwQXgHZps1+/Aft9Pi8fnpK+Z/Ds4tbryprpHy6al
xK8Kevr5W6csjUYzKxb47PU5TfZX83oyNVjIDPWlJbc751CYNg6L8UIkJpjTdNKRfH0NrTLNDeEI
tpHEcdmGtu6lEpQ5bEJdYFAWabrcxZZ4xx3yPlk6+MxqYS5SbpsxCDTvBlZEWqMlXLKZi9TC/Zsj
BpUvIsaadlbgbY2MUoir3RhsN0cDrjx1oLbhw0t3J6JTkS2+PwCMSJuc9Ti6dojDMO9dhgihlcWB
I1dyXIc4kKl6FlNMJmSyCEWI6wd6EvVZKcgjfY2OMWDuLUob4kqgxJ8jbpyzcTO62VparN4jmn1J
I7bIh/Q0yOMaCkHsEoViWaX2njYQSNbBmC8F8gGHx+50VV5oEIQjY32c69fHozGJqNFksweDssN+
SbVbA3Ao+38LDuPVmKR3mwfsAO4+QhJTW6R8qPWFyyFFPm6zifjQd3NbrJevNXq+lvkq8iMoWTVv
ZHgw9qD5oeuV2ZbOi46OaevobMVpmV/Dl032EREa8lo6oHMyBppC0DkHpVvkEFZTrFWFrmyxwHdB
AysXpi48mgCuW28sRdB1OrAbU2OlV7RO5eOAQiJ9z5x+gpjUfbby1rjRoMU2lIciUl3XfHhv2c9O
WuIgiN3MatrfdoEYLtgCOtxi5HwrCKkNsQDSAYFroiN4al8xwr4vOk6HF0gv5HCrhkhX20PLgC6f
Q4F0LLr3Y+QWfFr7Kc7064F2GAfTSPENS3IUi1wNIqMiPw3zUxd5xx8LfIuOLKiBtsOuJGwgdI7t
9jbVhAfQ5SmqK29lSe+1+cN1+rej43P9UrmjtQRDyWafrwty7PRDgUYL7iouQOtBQ+ZIqcrw9h1I
mp0zm3fnuDrDRv04rUaHKnGiJSE2IDWlQ4bkauNxMdNYcaQIurE0VaTa8odkhFTiMcZKH5DpV9zJ
Hn98OBCzIMDB0GZCUX83flIxG641huysXR57KBvOiGwT2jENrTpHTixD2OsS6lttLYo80HQRryU6
xCSZFDDcMUDAyS4q1FIpEQi6yMiuGxPK+qO9WcrpWdEjAUULYX2zWBS/Ruy0/6g0RJbLVa1fk/HC
SRBYVV15acbLrArShZYCUN0sO9McSJoMU2baVihIoxEH9qphjh0SGU1bZs10oqj+IPH0yx2gUvM2
2GR1mUheUhPc7uRRYI5LVKy2TcEjwUKa6oO1F3YccjbU2j5qhejrTXcxML8IY2LZemxB048SgXVh
pfnlY+3wkXCaaxWoSfe7hBNoSU79zMkUfa5Tgr+CzoaZGBPnerJDuUO3wD/yCGNy9wLjjvhu0VwG
KrJ32Gpa+rOdHJjEsNhXLe5WFrUSJrSsajxPH1dAejWVfCIGUK9+TxTWhPWmb1I2yh5mXd9iO/Rq
PEUuxCObLjvzSJnTS0dPvbdcflnwQ6IPDxdRzXylxNsCZtEcI8k3pSWjphGWkSbu7pmhlmi0jIRs
C8lTJRBiLcGOZiYFKRod9pieqrF3Cv5s+1GIveTsvddJmR61Afmh8kEfZYqRlQDh4Zm6DbHlob1H
ZIQtBuS9OBoXWEClMyjBr6gTqdJKCO71Q+/2+p+7v73pOeLsCpdNMbBttvy+GFzwd2ZNo1PR0rpX
2Muz6cDM7WO9ndOM4TUZBmGZndta3wgke7CdjkcH94pPRaiwP7L8A4fRF1BMvMmtZDvTTiVZKTq3
v8EZTeZFpkM96PyMjTBEQTYSXDGvq1yLC5t2Isi2FyVIT4hGGD4MujPgLBDWwH0z1T+bUxnh5hQo
Zb0QrHpuO6p4sXgYhFHbBaMcm7uIgbCCPaPY3yAS9Y2ljUcNiAQASNls5ByWBhAyKEZ80R+r4Hy3
RXW2R6LVaEnuEO3kqXi/PiGNW3zUJs4377QHG1l39ofVxULEsr6S6EI+v1E/HY9pq9DgevD8359O
d/ZifptsPaMqYeHdFnAD6lDNz3g2IAKHXbr+geeV4B0XtMYRCKV9Lt5wLMUK1CM6Kxhn+pLC3Tdj
GYD4yRc22LOKBW7YdDCpw2ODhxsvUeL3Oyyuh730lCkIR3G4mCHlSDPU2VdhLJd1WHgXJfA1DxZC
zWy4qvK/GgYiGVTjMGa5y3vD/VkSS6vwSC7UbF73FRI1bpnTw8TvjYXGkenDULt5ZdNWQytynC5s
UCX6eflifaUQtlq8HAKM9yyUm2yrWoUjAN0GCzrZVjZK3sX6a4x/WgggxYeo+VF5vt3N2W4enjkM
du4053A/PjfmY9m+GYfIkqLkgCOnqVqramK6SZoS4wAHtl2QVs4TISSZlCgNaa9ie0JFFSpxgIWP
PcSBpmjvjIanNwibJDQ1QxtQcHAJvhpgqd01qG6dP21OI6XEsUanRh3tlwzQ1HPZ7/AZ1kNCF2oV
kORi6XmaC4hTtfOYdwW1pbIcCXXWbLnmx1ykKUoUDBogeht8vQKtp18OFb7sUHdED4/jdM7s7otO
Sq19fezoKK/w5ySo83NUaNOktOgsrKp1stosiO+cVNGLkoEw5CIhDMLATINXVQ+XFJy4ivrJxh0m
eB6LIkNvn0Nze+VVKFyST1NELdv7NHfip9s6yqeW+609EywpOONhdzMbtVz2W6qNwJrRjVM5AZkS
GYhmmdFTSJu6eQPwkhAIQouAEzODYcBbydhb63ar78WHdR6Jub2iq8cHMi9ONamCHq8fHdZrpjW8
8zrKPOGWaiwXFcrmkrWrFqdZYt2JxUFZnRoQ0pTj62nNP0OCPn2hoeGOaHWNEMnSnCVXqSEhkrrQ
7k69JkQkJDdoUjIQhBq4/i6dmGiDmBzWpuE88k+d7F1zWzsSE2uXnPFjV8CphXSgOWThAuYb88JM
lItuIWRVyYhrAHbhjil0gLG9hDgRiadQWqVYlFHdzIRIFrSRM82axx5njLzq9xkkcy9qxBGLhB91
ww6oQx39I8NpxyksppJTjcr4Q18l+V7V8nakU3JANTrG0LhDJt7viTfMogys322m/EKdQG4HascO
aHmx5WV2OB0VYNdCaLubQnroow9abdHHzlvlOUynTIaoUmAnRV5VRu6k2wq11eqqYfiG83yknFgB
kEWwzVgGbBShNgY6jxhD4nQGZmBEYEC/ZrnUxafeo0jCrTwuz7TUbYAp0GhLe3h0m++bkWGc7CCd
7wrMx51ggZjg3YFtUvAglApZFIsS1JEwOg/NgPA63byHHdMEgTch+sLcbyI32P2IR4K5GMFkCGw6
5uR+51ZQRuSW6wvJ2pkNfZzrX6iXLkaRlQmlp3dOoU+ujtr28nQGsfOYnQpOOzTFoq+LWK2+USXR
4tCsz2MM2trRfE5CRIs3+uODRrCIVTGIaYASZUvl9q5LFWixqEmJgxMDToLs8OkGModNeYL3n3As
Ko+GJxHGTI2F3L9o0ScrFNZ8shXI+CRs2BcCzjNfLPq6CDFSDk3yEY5I0JHtOzftsoTBDaQ9lUCl
N91D3LyFmCwEWKAVcWmQJhShrAXtlaOdHXCGh4NHIKJJRZxlYL5ygBRwHDPZgF+RHF21aWU1169j
2Pw8vcRGciQHZEa3VLEe+kbF/63F3phEjwACt3uNYmdkAd9ftzDMkikIvSAsrMvjI4qiLbRLxhTN
6CYHAY0kr0MYPpDGaktRfMOpeK5B9I4jgGQmQDIjYr+QgxDIWgTulCrmIwIdQ6MX4nYt+mGTkOSu
i5sQ4NzIOJ6YVQ3z7HnxmYX3GSkEyZQbfhBPRE0ZiRXQgIaJyibXIKDSwAUHKBdVjUV1rRj7rhm4
XSo1KNGEOxLCVCpC+8SWrUvhZXIgPbRs4Dti+CAZTfmQmMGRCSQQxR0hwtO8olhbRMoe8MY+fXpD
BFaGwbMIYOYlMboIA04ykwApA2mMFmixQHC9VlCL31LENwjSCtraEmAJgwIQaDMOM9x0i/1GeYW4
d6PJpzL8I3NQqbBbxA9bzHa6sZ8lwJg2r51LH0aqkWpEY3MTSyJC4GdkQRCqn06b+VKMDIha1AkN
RF4oB4lWonv6r9xAkYEfMAXWQooLwVWJbQkU+b14xIloKS4tyTXzbDD4YEOQsODTqEcJJTKK6OkN
dhrmfqzqbdWsG4uJHaysPkQjlj3+boTM+NwYhB3pvwkfpTkyTYOqi6oQlJeSdBpF6Ap8mnbgYYwg
CF+dm/hEcuDkIdZF570XLhaBohlfQNWSJIm+juoyD1SzpDLIjiihWgrIQe8NiXIKIh0bAfSwgmDG
2uhI02mNBIKUyDBiYwIp2KUTpIP4Py3VawSBineHc9ujAwOA2yEQwO5SJEubvBXNz6nj2h66TwCs
MT1OpJJvMxd2qLONC0MDfkRbghrcC4FQtbQA2g7Y5sHchDnvRQPgH2pAAk8P0pRzeMQzoh7yWUxi
EiQhCEMqBxmeqoOEgEGBB98gpxAfBpO1TVtCqce0OLnbomBvK+iKUBKiBRhJRd5x5uw8DFrpvimT
kkHbY6oWe0oQtXXqckvhCbbVo63A48XnhiSRYLzsibVD6LmIaQU4CCAng4vQgVUMegA7NSYKsIaT
10YGI8GGS7Jg24ZFDVyojtNCymNJt3uFt/IM+KIUVrK41tNbY3NReQ3zJpmwLZzBXEtp23Eb5pxt
O/GZyERstY9lyYZedcXqUa++QKqopbHOMhIeoNFtugR2szOsZh7ZrLxgkYbkEXdA6rEmeR89kpWI
NVx7sRFxMED/iPE3y6FpkUqo9KKukQLAF4n5MhITCiw8G2SFTXKScqyz670TDzJJAUuOQfeWm/AB
rFhWlFzcggi6FoSQ4FwqLn0n28M/g6ebF2TLzunz0EGC3dy9aPuaLgJHqSJsJR2Gqg1RaWszAxAd
86iVWOBxIFzLuDtpWiQQ1myoRsabGxDbhHynm7avVm8OvIqLsBOF5hoIG83fEDeBAGZwAtODbERh
EUGx2hA6DpAR60MzTgX05pwM07FiqGU4mgcWgDcCte8FtG+u8g+V8I2FPjckOfcTN0NBPnDs5YlC
a9F1aOByiEIIV/EE6Qs6CKsExIQ5TsqexTuQ0XelMXHKmwMNc2xEIHbWhPC1qhOXGdLKRIShIROw
O0KA6RDfG4ZwxjJOdwqEobOOKCxeiALvxFMExHEyJI1g7i2VbPx47Vhsl4jH4QhA5g6qDOvKkmI2
E9dDEssW/CvBIYWZiQTCqC71hcdImyC1ILKDnQfQo7l1K8ynwvUG4hvutUfqZ/fyU7/kgPO9D5T6
LWAshYKolKMmj2dj/xdyRThQkKOzllo=
--===============0551424447==--