From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) by finch.gentoo.org (Postfix) with ESMTP id AFF28138247 for ; Sun, 29 Dec 2013 05:26:58 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 20BEDE0A89; Sun, 29 Dec 2013 05:26:57 +0000 (UTC) Received: from mail-wi0-f173.google.com (mail-wi0-f173.google.com [209.85.212.173]) (using TLSv1 with cipher ECDHE-RSA-RC4-SHA (128/128 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id 48C86E0A89 for ; Sun, 29 Dec 2013 05:26:56 +0000 (UTC) Received: by mail-wi0-f173.google.com with SMTP id hn9so10772077wib.0 for ; Sat, 28 Dec 2013 21:26:54 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:sender:in-reply-to:references:date :message-id:subject:from:to:cc:content-type; bh=dqmAV/Qcz4g5E/Efwx2/zDJdGj9Hj6TaJ1pRB/0T6Vo=; b=kiVmZGycPFl3dM2aqKdzy3zbrwTlgcsyGQUjT/mOvU+pnkHIcACYu9chb+WwrlCSza pF7bdkUwoLHusYu9c9sWAaUtJO4Wo2pjzuEsFST/sX9BfSkh9/QDNsrmCw4IAzXZcVhn 2KiehfRrjW+wzwQPFLy76Cr0/VoCK39sC9v5K97sBODJBFjMZ4oqLF302F3llCmyCo/+ wEoM5LZc/CtDTxzjnTHV9nYhNx/TZjNK/Wqzb0mmwPU9n4ATLJOBdxXIZMCFfTwDoF6d ndrq725S7UldL44ss/mp5zH4eNsV5rY4J32Zkr17pjpR2lQ2K4RNxPNLxK7UFRS3RoIA yIew== X-Gm-Message-State: ALoCoQlVhl3hqG1/1zuHjiqg74MjKEyoTSgbWhaF8gd/dCCfF0IdLPGMZ59mXVGpsWsnBYQSCjwr Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-catalyst@lists.gentoo.org Reply-to: gentoo-catalyst@lists.gentoo.org MIME-Version: 1.0 X-Received: by 10.194.89.97 with SMTP id bn1mr39881835wjb.18.1388294814793; Sat, 28 Dec 2013 21:26:54 -0800 (PST) Sender: antarus@scriptkitty.com Received: by 10.216.170.129 with HTTP; Sat, 28 Dec 2013 21:26:54 -0800 (PST) X-Originating-IP: [173.8.165.226] In-Reply-To: <1388282230-3563-6-git-send-email-dolsen@gentoo.org> References: <1388282230-3563-1-git-send-email-dolsen@gentoo.org> <1388282230-3563-6-git-send-email-dolsen@gentoo.org> Date: Sat, 28 Dec 2013 21:26:54 -0800 X-Google-Sender-Auth: DfqRIyjDR4Y-9toYm797Dtg39EA Message-ID: Subject: Re: [gentoo-catalyst] [PATCH 5/6] modules/generic_stage_target.py, modules/stage1_target.py: Add a target_mounts dictionary From: Alec Warner To: gentoo-catalyst@lists.gentoo.org Cc: Brian Dolbec Content-Type: multipart/alternative; boundary=089e010d84e64799a304eea5931b X-Archives-Salt: 87ba9f6c-5853-4a7a-b936-77c10c965cc0 X-Archives-Hash: 965d14aa0f1385e9285ffec186e5e6fc --089e010d84e64799a304eea5931b Content-Type: text/plain; charset=UTF-8 On Sat, Dec 28, 2013 at 5:57 PM, Brian Dolbec wrote: > Cleans up all self.mounts, self.mountmap usage. > Replace multiple path additions with one instance at the beginning of the > function, reuse the result multiple times. > Add some extra debug prints (to be converted to logging later) > --- > modules/generic_stage_target.py | 94 > ++++++++++++++++++++++++++--------------- > modules/stage1_target.py | 5 ++- > 2 files changed, 63 insertions(+), 36 deletions(-) > > diff --git a/modules/generic_stage_target.py > b/modules/generic_stage_target.py > index ce28ab8..c8d31e1 100644 > --- a/modules/generic_stage_target.py > +++ b/modules/generic_stage_target.py > @@ -4,6 +4,23 @@ from generic_target import * > from stat import * > import catalyst_lock > > +# temporary location. It will be moved to a > +# new defaults file in a later comit > +TARGET_MOUNTS_DEFAULTS = { > + "proc": "/proc", > + "dev": "/dev", > + "devpts": "/dev/pts", > + "portdir": "/usr/portage", > + "distdir": "/usr/portage/distfiles", > + "packagedir": "/usr/portage/packages", > + "port_tmpdir": "/var/tmp/portage", > + "kerncache": "/tmp/kerncache", > + "ccache": "/var/tmp/ccache", > + "icecream": "/usr/lib/icecc/bin", > + "port_logdir": "/var/log/portage", > + } > + > + > class generic_stage_target(generic_target): > """ > This class does all of the chroot setup, copying of files, etc. It > is > @@ -173,6 +190,10 @@ class generic_stage_target(generic_target): > > file_locate(self.settings,["portage_confdir"],expand=0) > > """ Setup our mount points """ > + # initialize our target mounts. > + # later I plan to make these configurable so the > + # defaults can be easily overridden if desired. > + self.target_mounts = TARGET_MOUNTS_DEFAULTS.copy() > if "SNAPCACHE" in self.settings: > self.mounts=["proc", "dev", "portdir", "distdir", > "port_tmpdir"] > self.mountmap={"proc":"/proc", "dev":"/dev", > "devpts":"/dev/pts", > @@ -219,17 +240,18 @@ class generic_stage_target(generic_target): > self.mounts.append("ccache") > self.mountmap["ccache"] = ccdir > """ for the chroot: """ > - self.env["CCACHE_DIR"]="/var/tmp/ccache" > + self.env["CCACHE_DIR"] = > self.target_mounts["ccache"] > > if "ICECREAM" in self.settings: > self.mounts.append("/var/cache/icecream") > > self.mountmap["/var/cache/icecream"]="/var/cache/icecream" > - > self.env["PATH"]="/usr/lib/icecc/bin:"+self.env["PATH"] > + self.env["PATH"] = self.target_mounts["icecream"] > + ":" + \ > + self.env["PATH"] > if "port_logdir" in self.settings: > - self.mounts.append("/var/log/portage") > - > self.mountmap["/var/log/portage"]=self.settings["port_logdir"] > - self.env["PORT_LOGDIR"]="/var/log/portage" > + self.mounts.append("port_logdir") > + > self.mountmap["port_logdir"]=self.settings["port_logdir"] > + > self.env["PORT_LOGDIR"]=self.target_mounts["port_logdir"] > self.env["PORT_LOGDIR_CLEAN"]='find > "${PORT_LOGDIR}" -type f ! -name "summary.log*" -mtime +30 -delete' > I've avoided commenting on + in strings, as my understanding was that we were not doing style fixups in these CLs. I would argue that in general, any time you use string + string in python, you are doing it wrong (e.g. your code is not 'pythonic') You can use "%s:%s" % (string1, string2) or ":".join(string1, string2) Either are fine, and are nominally better than string + string + string. > > def override_cbuild(self): > @@ -603,33 +625,34 @@ class generic_stage_target(generic_target): > "kill-chroot-pids script > failed.",env=self.env) > > def mount_safety_check(self): > - mypath=self.settings["chroot_path"] > - > """ > Check and verify that none of our paths in mypath are > mounted. We don't > want to clean up with things still mounted, and this > allows us to check. > Returns 1 on ok, 0 on "something is still mounted" case. > """ > > - if not os.path.exists(mypath): > + if not os.path.exists(self.settings["chroot_path"]): > return > > + print "self.mounts =", self.mounts > for x in self.mounts: > - if not os.path.exists(mypath + self.mountmap[x]): > + target = normpath(self.settings["chroot_path"] + > self.target_mounts[x]) > + print "mount_safety_check() x =", x, target > + if not os.path.exists(target): > continue > > - if ismount(mypath + self.mountmap[x]): > + if ismount(target): > """ Something is still mounted "" """ > try: > - print self.mountmap[x] + " is > still mounted; performing auto-bind-umount...", > + print target + " is still mounted; > performing auto-bind-umount...", > """ Try to umount stuff ourselves > """ > self.unbind() > - if ismount(mypath + > self.mountmap[x]): > - raise CatalystError, > "Auto-unbind failed for " + self.mountmap[x] > + if ismount(target): > + raise CatalystError, > "Auto-unbind failed for " + target > else: > print "Auto-unbind > successful..." > except CatalystError: > - raise CatalystError, "Unable to > auto-unbind " + self.mountmap[x] > + raise CatalystError, "Unable to > auto-unbind " + target > > def unpack(self): > unpack=True > @@ -897,12 +920,14 @@ class generic_stage_target(generic_target): > > def bind(self): > for x in self.mounts: > - if not os.path.exists(self.settings["chroot_path"] > + self.mountmap[x]): > - > os.makedirs(self.settings["chroot_path"]+x,0755) > + #print "bind(); x =", x > + target = normpath(self.settings["chroot_path"] + > self.target_mounts[x]) > + if not os.path.exists(target): > + os.makedirs(target, 0755) > > if not os.path.exists(self.mountmap[x]): > if not self.mountmap[x] == "tmpfs": > - os.makedirs(self.mountmap[x],0755) > + os.makedirs(self.mountmap[x], 0755) > > src=self.mountmap[x] > #print "bind(); src =", src > @@ -910,20 +935,22 @@ class generic_stage_target(generic_target): > self.snapshot_lock_object.read_lock() > if os.uname()[0] == "FreeBSD": > if src == "/dev": > - retval = os.system("mount -t devfs > none " + > - > self.settings["chroot_path"] + src) > + cmd = "mount -t devfs none " + > target > + retval=os.system(cmd) > "because the code use to do it" aside, is there some compelling reason to not use subprocess.Popen here? os.system is probably the worst syscall you can use. It spawns a shell, it will select things like './mount' over '/usr/bin/mount' because you failed to specify the full path to the binary, its not clear what environment the shell is using. Even something like: import subprocess retval = subprocess.call(cmd.split()) would likely avoid these problems unless you are relying on shell expansion in cmd? > else: > - retval = os.system("mount_nullfs " > + src + " " + > - > self.settings["chroot_path"] + src) > + cmd = "mount_nullfs " + src + " " > + target > + retval=os.system(cmd) > else: > if src == "tmpfs": > if "var_tmpfs_portage" in > self.settings: > - retval=os.system("mount -t > tmpfs -o size="+\ > - > self.settings["var_tmpfs_portage"]+"G "+src+" "+\ > - > self.settings["chroot_path"]+x) > + cmd = "mount -t tmpfs -o > size=" + \ > + > self.settings["var_tmpfs_portage"] + "G " + \ > + src + " " + target > + retval=os.system(cmd) > else: > - retval = os.system("mount --bind " > + src + " " + > - > self.settings["chroot_path"] + src) > + cmd = "mount --bind " + src + " " > + target > + #print "bind(); cmd =", cmd > + retval=os.system(cmd) > if retval!=0: > self.unbind() > raise CatalystError,"Couldn't bind mount " > + src > @@ -935,26 +962,25 @@ class generic_stage_target(generic_target): > myrevmounts.reverse() > """ Unmount in reverse order for nested bind-mounts """ > for x in myrevmounts: > - if not os.path.exists(mypath + self.mountmap[x]): > + target = normpath(mypath + self.target_mounts[x]) > + if not os.path.exists(target): > continue > > - if not ismount(mypath + self.mountmap[x]): > + if not ismount(target): > continue > > - retval=os.system("umount "+\ > - os.path.join(mypath, > self.mountmap[x].lstrip(os.path.sep))) > + retval=os.system("umount " + target) > > if retval!=0: > - warn("First attempt to unmount: " + mypath > + > - self.mountmap[x] +" failed.") > + warn("First attempt to unmount: " + target > + " failed.") > warn("Killing any pids still running in > the chroot") > > self.kill_chroot_pids() > > - retval2 = os.system("umount " + mypath + > self.mountmap[x]) > + retval2 = os.system("umount " + target) > if retval2!=0: > ouch=1 > - warn("Couldn't umount bind mount: > " + mypath + self.mountmap[x]) > + warn("Couldn't umount bind mount: > " + target) > > if "SNAPCACHE" in self.settings and x == > "/usr/portage": > try: > diff --git a/modules/stage1_target.py b/modules/stage1_target.py > index aa43926..1e0d874 100644 > --- a/modules/stage1_target.py > +++ b/modules/stage1_target.py > @@ -88,8 +88,9 @@ class stage1_target(generic_stage_target): > os.makedirs(self.settings["stage_path"]+"/proc") > > # alter the mount mappings to bind mount proc onto it > - self.mounts.append("/tmp/stage1root/proc") > - self.mountmap["/tmp/stage1root/proc"]="/proc" > + self.mounts.append("stage1root/proc") > + self.target_mounts["stage1root/proc"] = > "/tmp/stage1root/proc" > + self.mountmap["stage1root/proc"]="/proc" > > def register(foo): > foo.update({"stage1":stage1_target}) > -- > 1.8.3.2 > > > --089e010d84e64799a304eea5931b Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: base64 PGRpdiBkaXI9Imx0ciI+PGRpdiBjbGFzcz0iZ21haWxfZXh0cmEiPjxkaXYgY2xhc3M9ImdtYWls X3F1b3RlIj5PbiBTYXQsIERlYyAyOCwgMjAxMyBhdCA1OjU3IFBNLCBCcmlhbiBEb2xiZWMgPHNw YW4gZGlyPSJsdHIiPiZsdDs8YSBocmVmPSJtYWlsdG86ZG9sc2VuQGdlbnRvby5vcmciIHRhcmdl dD0iX2JsYW5rIj5kb2xzZW5AZ2VudG9vLm9yZzwvYT4mZ3Q7PC9zcGFuPiB3cm90ZTo8YnI+DQo8 YmxvY2txdW90ZSBjbGFzcz0iZ21haWxfcXVvdGUiIHN0eWxlPSJtYXJnaW46MCAwIDAgLjhleDti b3JkZXItbGVmdDoxcHggI2NjYyBzb2xpZDtwYWRkaW5nLWxlZnQ6MWV4Ij5DbGVhbnMgdXAgYWxs IHNlbGYubW91bnRzLCBzZWxmLm1vdW50bWFwIHVzYWdlLjxicj4NClJlcGxhY2UgbXVsdGlwbGUg cGF0aCBhZGRpdGlvbnMgd2l0aCBvbmUgaW5zdGFuY2UgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUg ZnVuY3Rpb24sIHJldXNlIHRoZSByZXN1bHQgbXVsdGlwbGUgdGltZXMuPGJyPg0KQWRkIHNvbWUg ZXh0cmEgZGVidWcgcHJpbnRzICh0byBiZSBjb252ZXJ0ZWQgdG8gbG9nZ2luZyBsYXRlcik8YnI+ DQotLS08YnI+DQrCoG1vZHVsZXMvZ2VuZXJpY19zdGFnZV90YXJnZXQucHkgfCA5NCArKysrKysr KysrKysrKysrKysrKysrKysrKy0tLS0tLS0tLS0tLS0tLTxicj4NCsKgbW9kdWxlcy9zdGFnZTFf dGFyZ2V0LnB5IMKgIMKgIMKgIMKgfCDCoDUgKystPGJyPg0KwqAyIGZpbGVzIGNoYW5nZWQsIDYz IGluc2VydGlvbnMoKyksIDM2IGRlbGV0aW9ucygtKTxicj4NCjxicj4NCmRpZmYgLS1naXQgYS9t b2R1bGVzL2dlbmVyaWNfc3RhZ2VfdGFyZ2V0LnB5IGIvbW9kdWxlcy9nZW5lcmljX3N0YWdlX3Rh cmdldC5weTxicj4NCmluZGV4IGNlMjhhYjguLmM4ZDMxZTEgMTAwNjQ0PGJyPg0KLS0tIGEvbW9k dWxlcy9nZW5lcmljX3N0YWdlX3RhcmdldC5weTxicj4NCisrKyBiL21vZHVsZXMvZ2VuZXJpY19z dGFnZV90YXJnZXQucHk8YnI+DQpAQCAtNCw2ICs0LDIzIEBAIGZyb20gZ2VuZXJpY190YXJnZXQg aW1wb3J0ICo8YnI+DQrCoGZyb20gc3RhdCBpbXBvcnQgKjxicj4NCsKgaW1wb3J0IGNhdGFseXN0 X2xvY2s8YnI+DQo8YnI+DQorIyB0ZW1wb3JhcnkgbG9jYXRpb24uIMKgSXQgd2lsbCBiZSBtb3Zl ZCB0byBhPGJyPg0KKyMgbmV3IGRlZmF1bHRzIGZpbGUgaW4gYSBsYXRlciBjb21pdDxicj4NCitU QVJHRVRfTU9VTlRTX0RFRkFVTFRTID0gezxicj4NCisgwqAgwqAgwqAgJnF1b3Q7cHJvYyZxdW90 OzogJnF1b3Q7L3Byb2MmcXVvdDssPGJyPg0KKyDCoCDCoCDCoCAmcXVvdDtkZXYmcXVvdDs6ICZx dW90Oy9kZXYmcXVvdDssPGJyPg0KKyDCoCDCoCDCoCAmcXVvdDtkZXZwdHMmcXVvdDs6ICZxdW90 Oy9kZXYvcHRzJnF1b3Q7LDxicj4NCisgwqAgwqAgwqAgJnF1b3Q7cG9ydGRpciZxdW90OzogJnF1 b3Q7L3Vzci9wb3J0YWdlJnF1b3Q7LDxicj4NCisgwqAgwqAgwqAgJnF1b3Q7ZGlzdGRpciZxdW90 OzogJnF1b3Q7L3Vzci9wb3J0YWdlL2Rpc3RmaWxlcyZxdW90Oyw8YnI+DQorIMKgIMKgIMKgICZx dW90O3BhY2thZ2VkaXImcXVvdDs6ICZxdW90Oy91c3IvcG9ydGFnZS9wYWNrYWdlcyZxdW90Oyw8 YnI+DQorIMKgIMKgIMKgICZxdW90O3BvcnRfdG1wZGlyJnF1b3Q7OiAmcXVvdDsvdmFyL3RtcC9w b3J0YWdlJnF1b3Q7LDxicj4NCisgwqAgwqAgwqAgJnF1b3Q7a2VybmNhY2hlJnF1b3Q7OiAmcXVv dDsvdG1wL2tlcm5jYWNoZSZxdW90Oyw8YnI+DQorIMKgIMKgIMKgICZxdW90O2NjYWNoZSZxdW90 OzogJnF1b3Q7L3Zhci90bXAvY2NhY2hlJnF1b3Q7LDxicj4NCisgwqAgwqAgwqAgJnF1b3Q7aWNl Y3JlYW0mcXVvdDs6ICZxdW90Oy91c3IvbGliL2ljZWNjL2JpbiZxdW90Oyw8YnI+DQorIMKgIMKg IMKgICZxdW90O3BvcnRfbG9nZGlyJnF1b3Q7OiAmcXVvdDsvdmFyL2xvZy9wb3J0YWdlJnF1b3Q7 LDxicj4NCisgwqAgwqAgwqAgfTxicj4NCis8YnI+DQorPGJyPg0KwqBjbGFzcyBnZW5lcmljX3N0 YWdlX3RhcmdldChnZW5lcmljX3RhcmdldCk6PGJyPg0KwqAgwqAgwqAgwqAgJnF1b3Q7JnF1b3Q7 JnF1b3Q7PGJyPg0KwqAgwqAgwqAgwqAgVGhpcyBjbGFzcyBkb2VzIGFsbCBvZiB0aGUgY2hyb290 IHNldHVwLCBjb3B5aW5nIG9mIGZpbGVzLCBldGMuIEl0IGlzPGJyPg0KQEAgLTE3Myw2ICsxOTAs MTAgQEAgY2xhc3MgZ2VuZXJpY19zdGFnZV90YXJnZXQoZ2VuZXJpY190YXJnZXQpOjxicj4NCsKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGZpbGVfbG9jYXRlKHNlbGYuc2V0dGlu Z3MsWyZxdW90O3BvcnRhZ2VfY29uZmRpciZxdW90O10sZXhwYW5kPTApPGJyPg0KPGJyPg0KwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgJnF1b3Q7JnF1b3Q7JnF1b3Q7IFNldHVwIG91ciBtb3VudCBw b2ludHMgJnF1b3Q7JnF1b3Q7JnF1b3Q7PGJyPg0KKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCAjIGlu aXRpYWxpemUgb3VyIHRhcmdldCBtb3VudHMuPGJyPg0KKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCAj IGxhdGVyIEkgcGxhbiB0byBtYWtlIHRoZXNlIGNvbmZpZ3VyYWJsZSBzbyB0aGU8YnI+DQorIMKg IMKgIMKgIMKgIMKgIMKgIMKgICMgZGVmYXVsdHMgY2FuIGJlIGVhc2lseSBvdmVycmlkZGVuIGlm IGRlc2lyZWQuPGJyPg0KKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCBzZWxmLnRhcmdldF9tb3VudHMg PSBUQVJHRVRfTU9VTlRTX0RFRkFVTFRTLmNvcHkoKTxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIGlmICZxdW90O1NOQVBDQUNIRSZxdW90OyBpbiBzZWxmLnNldHRpbmdzOjxicj4NCsKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHNlbGYubW91bnRzPVsmcXVvdDtwcm9jJnF1 b3Q7LCAmcXVvdDtkZXYmcXVvdDssICZxdW90O3BvcnRkaXImcXVvdDssICZxdW90O2Rpc3RkaXIm cXVvdDssICZxdW90O3BvcnRfdG1wZGlyJnF1b3Q7XTxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIHNlbGYubW91bnRtYXA9eyZxdW90O3Byb2MmcXVvdDs6JnF1b3Q7L3By b2MmcXVvdDssICZxdW90O2RldiZxdW90OzomcXVvdDsvZGV2JnF1b3Q7LCAmcXVvdDtkZXZwdHMm cXVvdDs6JnF1b3Q7L2Rldi9wdHMmcXVvdDssPGJyPg0KQEAgLTIxOSwxNyArMjQwLDE4IEBAIGNs YXNzIGdlbmVyaWNfc3RhZ2VfdGFyZ2V0KGdlbmVyaWNfdGFyZ2V0KTo8YnI+DQrCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBzZWxmLm1vdW50cy5hcHBlbmQoJnF1b3Q7Y2NhY2hl JnF1b3Q7KTxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHNlbGYubW91 bnRtYXBbJnF1b3Q7Y2NhY2hlJnF1b3Q7XSA9IGNjZGlyPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgJnF1b3Q7JnF1b3Q7JnF1b3Q7IGZvciB0aGUgY2hyb290OiAmcXVv dDsmcXVvdDsmcXVvdDs8YnI+DQotIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHNl bGYuZW52WyZxdW90O0NDQUNIRV9ESVImcXVvdDtdPSZxdW90Oy92YXIvdG1wL2NjYWNoZSZxdW90 Ozxicj4NCisgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgc2VsZi5lbnZbJnF1b3Q7 Q0NBQ0hFX0RJUiZxdW90O10gPSBzZWxmLnRhcmdldF9tb3VudHNbJnF1b3Q7Y2NhY2hlJnF1b3Q7 XTxicj4NCjxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGlmICZxdW90O0lDRUNSRUFNJnF1 b3Q7IGluIHNlbGYuc2V0dGluZ3M6PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgc2VsZi5tb3VudHMuYXBwZW5kKCZxdW90Oy92YXIvY2FjaGUvaWNlY3JlYW0mcXVvdDsp PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgc2VsZi5tb3VudG1hcFsm cXVvdDsvdmFyL2NhY2hlL2ljZWNyZWFtJnF1b3Q7XT0mcXVvdDsvdmFyL2NhY2hlL2ljZWNyZWFt JnF1b3Q7PGJyPg0KLSDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBzZWxmLmVudlsm cXVvdDtQQVRIJnF1b3Q7XT0mcXVvdDsvdXNyL2xpYi9pY2VjYy9iaW46JnF1b3Q7K3NlbGYuZW52 WyZxdW90O1BBVEgmcXVvdDtdPGJyPg0KKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCBzZWxmLmVudlsmcXVvdDtQQVRIJnF1b3Q7XSA9IHNlbGYudGFyZ2V0X21vdW50c1smcXVvdDtp Y2VjcmVhbSZxdW90O10gKyAmcXVvdDs6JnF1b3Q7ICsgXDxicj4NCisgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgc2VsZi5lbnZbJnF1b3Q7UEFUSCZxdW90O108 YnI+PC9ibG9ja3F1b3RlPjxibG9ja3F1b3RlIGNsYXNzPSJnbWFpbF9xdW90ZSIgc3R5bGU9Im1h cmdpbjowIDAgMCAuOGV4O2JvcmRlci1sZWZ0OjFweCAjY2NjIHNvbGlkO3BhZGRpbmctbGVmdDox ZXgiPsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGlmICZxdW90O3BvcnRfbG9nZGlyJnF1b3Q7IGlu IHNlbGYuc2V0dGluZ3M6PGJyPg0KDQotIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IHNlbGYubW91bnRzLmFwcGVuZCgmcXVvdDsvdmFyL2xvZy9wb3J0YWdlJnF1b3Q7KTxicj4NCi0g wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgc2VsZi5tb3VudG1hcFsmcXVvdDsvdmFy L2xvZy9wb3J0YWdlJnF1b3Q7XT1zZWxmLnNldHRpbmdzWyZxdW90O3BvcnRfbG9nZGlyJnF1b3Q7 XTxicj4NCi0gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgc2VsZi5lbnZbJnF1b3Q7 UE9SVF9MT0dESVImcXVvdDtdPSZxdW90Oy92YXIvbG9nL3BvcnRhZ2UmcXVvdDs8YnI+DQorIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHNlbGYubW91bnRzLmFwcGVuZCgmcXVvdDtw b3J0X2xvZ2RpciZxdW90Oyk8YnI+DQorIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IHNlbGYubW91bnRtYXBbJnF1b3Q7cG9ydF9sb2dkaXImcXVvdDtdPXNlbGYuc2V0dGluZ3NbJnF1 b3Q7cG9ydF9sb2dkaXImcXVvdDtdPGJyPg0KKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCBzZWxmLmVudlsmcXVvdDtQT1JUX0xPR0RJUiZxdW90O109c2VsZi50YXJnZXRfbW91bnRz WyZxdW90O3BvcnRfbG9nZGlyJnF1b3Q7XTxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIHNlbGYuZW52WyZxdW90O1BPUlRfTE9HRElSX0NMRUFOJnF1b3Q7XT0mIzM5O2Zp bmQgJnF1b3Q7JHtQT1JUX0xPR0RJUn0mcXVvdDsgLXR5cGUgZiAhIC1uYW1lICZxdW90O3N1bW1h cnkubG9nKiZxdW90OyAtbXRpbWUgKzMwIC1kZWxldGUmIzM5Ozxicj48L2Jsb2NrcXVvdGU+PGRp dj48YnI+PC9kaXY+PGRpdj5JJiMzOTt2ZSBhdm9pZGVkIGNvbW1lbnRpbmcgb24gKyBpbiBzdHJp bmdzLCBhcyBteSB1bmRlcnN0YW5kaW5nIHdhcyB0aGF0IHdlIHdlcmUgbm90IGRvaW5nIHN0eWxl IGZpeHVwcyBpbiB0aGVzZSBDTHMuIEkgd291bGQgYXJndWUgdGhhdCBpbiBnZW5lcmFsLCBhbnkg dGltZSB5b3UgdXNlIHN0cmluZyArIHN0cmluZyBpbiBweXRob24sIHlvdSBhcmUgZG9pbmcgaXQg d3JvbmcgKGUuZy4geW91ciBjb2RlIGlzIG5vdCAmIzM5O3B5dGhvbmljJiMzOTspPC9kaXY+DQo8 ZGl2Pjxicj48L2Rpdj48ZGl2PllvdSBjYW4gdXNlPC9kaXY+PGRpdj48YnI+PC9kaXY+PGRpdj4m cXVvdDslczolcyZxdW90OyAlIChzdHJpbmcxLCBzdHJpbmcyKSBvciAmcXVvdDs6JnF1b3Q7Lmpv aW4oc3RyaW5nMSwgc3RyaW5nMik8L2Rpdj48ZGl2Pjxicj48L2Rpdj48ZGl2PkVpdGhlciBhcmUg ZmluZSwgYW5kIGFyZSBub21pbmFsbHkgYmV0dGVyIHRoYW4gc3RyaW5nICsgc3RyaW5nICsgc3Ry aW5nLjwvZGl2Pg0KPGRpdj48YnI+PC9kaXY+PGRpdj7CoDwvZGl2PjxibG9ja3F1b3RlIGNsYXNz PSJnbWFpbF9xdW90ZSIgc3R5bGU9Im1hcmdpbjowIDAgMCAuOGV4O2JvcmRlci1sZWZ0OjFweCAj Y2NjIHNvbGlkO3BhZGRpbmctbGVmdDoxZXgiPg0KPGJyPg0KwqAgwqAgwqAgwqAgZGVmIG92ZXJy aWRlX2NidWlsZChzZWxmKTo8YnI+DQpAQCAtNjAzLDMzICs2MjUsMzQgQEAgY2xhc3MgZ2VuZXJp Y19zdGFnZV90YXJnZXQoZ2VuZXJpY190YXJnZXQpOjxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgICZxdW90O2tpbGwtY2hyb290LXBpZHMgc2NyaXB0 IGZhaWxlZC4mcXVvdDssZW52PXNlbGYuZW52KTxicj4NCjxicj4NCsKgIMKgIMKgIMKgIGRlZiBt b3VudF9zYWZldHlfY2hlY2soc2VsZik6PGJyPg0KLSDCoCDCoCDCoCDCoCDCoCDCoCDCoCBteXBh dGg9c2VsZi5zZXR0aW5nc1smcXVvdDtjaHJvb3RfcGF0aCZxdW90O108YnI+DQotPGJyPg0KwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgJnF1b3Q7JnF1b3Q7JnF1b3Q7PGJyPg0KwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgQ2hlY2sgYW5kIHZlcmlmeSB0aGF0IG5vbmUgb2Ygb3VyIHBhdGhzIGluIG15 cGF0aCBhcmUgbW91bnRlZC4gV2UgZG9uJiMzOTt0PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgd2FudCB0byBjbGVhbiB1cCB3aXRoIHRoaW5ncyBzdGlsbCBtb3VudGVkLCBhbmQgdGhpcyBh bGxvd3MgdXMgdG8gY2hlY2suPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgUmV0dXJucyAx IG9uIG9rLCAwIG9uICZxdW90O3NvbWV0aGluZyBpcyBzdGlsbCBtb3VudGVkJnF1b3Q7IGNhc2Uu PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgJnF1b3Q7JnF1b3Q7JnF1b3Q7PGJyPg0KPGJy Pg0KLSDCoCDCoCDCoCDCoCDCoCDCoCDCoCBpZiBub3Qgb3MucGF0aC5leGlzdHMobXlwYXRoKTo8 YnI+DQorIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGlmIG5vdCBvcy5wYXRoLmV4aXN0cyhzZWxmLnNl dHRpbmdzWyZxdW90O2Nocm9vdF9wYXRoJnF1b3Q7XSk6PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgcmV0dXJuPGJyPg0KPGJyPg0KKyDCoCDCoCDCoCDCoCDCoCDCoCDC oCBwcmludCAmcXVvdDtzZWxmLm1vdW50cyA9JnF1b3Q7LCBzZWxmLm1vdW50czxicj4NCsKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIGZvciB4IGluIHNlbGYubW91bnRzOjxicj4NCi0gwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaWYgbm90IG9zLnBhdGguZXhpc3RzKG15cGF0aCArIHNl bGYubW91bnRtYXBbeF0pOjxicj4NCisgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg dGFyZ2V0ID0gbm9ybXBhdGgoc2VsZi5zZXR0aW5nc1smcXVvdDtjaHJvb3RfcGF0aCZxdW90O10g KyBzZWxmLnRhcmdldF9tb3VudHNbeF0pPGJyPg0KKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCBwcmludCAmcXVvdDttb3VudF9zYWZldHlfY2hlY2soKSB4ID0mcXVvdDssIHgsIHRh cmdldDxicj4NCisgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaWYgbm90IG9zLnBh dGguZXhpc3RzKHRhcmdldCk6PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgY29udGludWU8YnI+DQo8YnI+DQotIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIGlmIGlzbW91bnQobXlwYXRoICsgc2VsZi5tb3VudG1hcFt4XSk6PGJyPg0K KyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBpZiBpc21vdW50KHRhcmdldCk6PGJy Pg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgJnF1b3Q7 JnF1b3Q7JnF1b3Q7IFNvbWV0aGluZyBpcyBzdGlsbCBtb3VudGVkICZxdW90OyZxdW90OyAmcXVv dDsmcXVvdDsmcXVvdDs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCB0cnk6PGJyPg0KLSDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBwcmludCBzZWxmLm1vdW50bWFwW3hdICsgJnF1b3Q7IGlz IHN0aWxsIG1vdW50ZWQ7IHBlcmZvcm1pbmcgYXV0by1iaW5kLXVtb3VudC4uLiZxdW90Oyw8YnI+ DQorIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIHByaW50IHRhcmdldCArICZxdW90OyBpcyBzdGlsbCBtb3VudGVkOyBwZXJmb3JtaW5nIGF1 dG8tYmluZC11bW91bnQuLi4mcXVvdDssPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgJnF1b3Q7JnF1b3Q7JnF1b3Q7IFRyeSB0 byB1bW91bnQgc3R1ZmYgb3Vyc2VsdmVzICZxdW90OyZxdW90OyZxdW90Ozxicj4NCsKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHNlbGYu dW5iaW5kKCk8YnI+DQotIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIGlmIGlzbW91bnQobXlwYXRoICsgc2VsZi5tb3VudG1hcFt4XSk6PGJy Pg0KLSDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCByYWlzZSBDYXRhbHlzdEVycm9yLCAmcXVvdDtBdXRvLXVuYmluZCBm YWlsZWQgZm9yICZxdW90OyArIHNlbGYubW91bnRtYXBbeF08YnI+DQorIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGlmIGlzbW91bnQodGFy Z2V0KTo8YnI+DQorIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHJhaXNlIENhdGFseXN0RXJyb3IsICZxdW90O0F1dG8t dW5iaW5kIGZhaWxlZCBmb3IgJnF1b3Q7ICsgdGFyZ2V0PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgZWxzZTo8YnI+DQrCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCBwcmludCAmcXVvdDtBdXRvLXVuYmluZCBzdWNjZXNzZnVsLi4uJnF1b3Q7PGJy Pg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgZXhjZXB0 IENhdGFseXN0RXJyb3I6PGJyPg0KLSDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCByYWlzZSBDYXRhbHlzdEVycm9yLCAmcXVvdDtVbmFibGUg dG8gYXV0by11bmJpbmQgJnF1b3Q7ICsgc2VsZi5tb3VudG1hcFt4XTxicj4NCisgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgcmFpc2UgQ2F0 YWx5c3RFcnJvciwgJnF1b3Q7VW5hYmxlIHRvIGF1dG8tdW5iaW5kICZxdW90OyArIHRhcmdldDxi cj4NCjxicj4NCsKgIMKgIMKgIMKgIGRlZiB1bnBhY2soc2VsZik6PGJyPg0KwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgdW5wYWNrPVRydWU8YnI+DQpAQCAtODk3LDEyICs5MjAsMTQgQEAgY2xhc3Mg Z2VuZXJpY19zdGFnZV90YXJnZXQoZ2VuZXJpY190YXJnZXQpOjxicj4NCjxicj4NCsKgIMKgIMKg IMKgIGRlZiBiaW5kKHNlbGYpOjxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGZvciB4IGlu IHNlbGYubW91bnRzOjxicj4NCi0gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaWYg bm90IG9zLnBhdGguZXhpc3RzKHNlbGYuc2V0dGluZ3NbJnF1b3Q7Y2hyb290X3BhdGgmcXVvdDtd ICsgc2VsZi5tb3VudG1hcFt4XSk6PGJyPg0KLSDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCBvcy5tYWtlZGlycyhzZWxmLnNldHRpbmdzWyZxdW90O2Nocm9vdF9w YXRoJnF1b3Q7XSt4LDA3NTUpPGJyPg0KKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCAjcHJpbnQgJnF1b3Q7YmluZCgpOyB4ID0mcXVvdDssIHg8YnI+DQorIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIHRhcmdldCA9IG5vcm1wYXRoKHNlbGYuc2V0dGluZ3NbJnF1b3Q7 Y2hyb290X3BhdGgmcXVvdDtdICsgc2VsZi50YXJnZXRfbW91bnRzW3hdKTxicj4NCisgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaWYgbm90IG9zLnBhdGguZXhpc3RzKHRhcmdldCk6 PGJyPg0KKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBvcy5t YWtlZGlycyh0YXJnZXQsIDA3NTUpPGJyPg0KPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgaWYgbm90IG9zLnBhdGguZXhpc3RzKHNlbGYubW91bnRtYXBbeF0pOjxicj4N CsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGlmIG5vdCBz ZWxmLm1vdW50bWFwW3hdID09ICZxdW90O3RtcGZzJnF1b3Q7Ojxicj4NCi0gwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgb3MubWFrZWRpcnMo c2VsZi5tb3VudG1hcFt4XSwwNzU1KTxicj4NCisgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgb3MubWFrZWRpcnMoc2VsZi5tb3VudG1hcFt4 XSwgMDc1NSk8YnI+DQo8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBz cmM9c2VsZi5tb3VudG1hcFt4XTxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgICNwcmludCAmcXVvdDtiaW5kKCk7IHNyYyA9JnF1b3Q7LCBzcmM8YnI+DQpAQCAtOTEwLDIw ICs5MzUsMjIgQEAgY2xhc3MgZ2VuZXJpY19zdGFnZV90YXJnZXQoZ2VuZXJpY190YXJnZXQpOjxi cj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHNlbGYu c25hcHNob3RfbG9ja19vYmplY3QucmVhZF9sb2NrKCk8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCBpZiBvcy51bmFtZSgpWzBdID09ICZxdW90O0ZyZWVCU0QmcXVvdDs6 PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaWYg c3JjID09ICZxdW90Oy9kZXYmcXVvdDs6PGJyPg0KLSDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCByZXR2YWwgPSBvcy5zeXN0ZW0oJnF1b3Q7 bW91bnQgLXQgZGV2ZnMgbm9uZSAmcXVvdDsgKzxicj4NCi0gwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgc2VsZi5zZXR0 aW5nc1smcXVvdDtjaHJvb3RfcGF0aCZxdW90O10gKyBzcmMpPGJyPg0KKyDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBjbWQgPSAmcXVvdDtt b3VudCAtdCBkZXZmcyBub25lICZxdW90OyArIHRhcmdldDxicj4NCisgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgcmV0dmFsPW9zLnN5c3Rl bShjbWQpPGJyPjwvYmxvY2txdW90ZT48ZGl2Pjxicj48L2Rpdj48ZGl2PiZxdW90O2JlY2F1c2Ug dGhlIGNvZGUgdXNlIHRvIGRvIGl0JnF1b3Q7IGFzaWRlLCBpcyB0aGVyZSBzb21lIGNvbXBlbGxp bmcgcmVhc29uIHRvIG5vdCB1c2Ugc3VicHJvY2Vzcy5Qb3BlbiBoZXJlPyBvcy5zeXN0ZW0gaXMg cHJvYmFibHkgdGhlIHdvcnN0IHN5c2NhbGwgeW91IGNhbiB1c2UuIEl0IHNwYXducyBhIHNoZWxs LCBpdCB3aWxsIHNlbGVjdCB0aGluZ3MgbGlrZSAmIzM5Oy4vbW91bnQmIzM5OyBvdmVyICYjMzk7 L3Vzci9iaW4vbW91bnQmIzM5OyBiZWNhdXNlIHlvdSBmYWlsZWQgdG8gc3BlY2lmeSB0aGUgZnVs bCBwYXRoIHRvIHRoZSBiaW5hcnksIGl0cyBub3QgY2xlYXIgd2hhdCBlbnZpcm9ubWVudCB0aGUg c2hlbGwgaXMgdXNpbmcuPC9kaXY+DQo8ZGl2Pjxicj48L2Rpdj48ZGl2PkV2ZW4gc29tZXRoaW5n IGxpa2U6PC9kaXY+PGRpdj48YnI+PC9kaXY+PGRpdj5pbXBvcnQgc3VicHJvY2VzczwvZGl2Pjxk aXY+cmV0dmFsID0gc3VicHJvY2Vzcy5jYWxsKGNtZC5zcGxpdCgpKTwvZGl2PjxkaXY+PGJyPjwv ZGl2PjxkaXY+d291bGQgbGlrZWx5IGF2b2lkIHRoZXNlIHByb2JsZW1zIHVubGVzcyB5b3UgYXJl IHJlbHlpbmcgb24gc2hlbGwgZXhwYW5zaW9uIGluIGNtZD88L2Rpdj4NCjxkaXY+PGJyPjwvZGl2 PjxkaXY+PGJyPjwvZGl2PjxkaXY+wqA8L2Rpdj48YmxvY2txdW90ZSBjbGFzcz0iZ21haWxfcXVv dGUiIHN0eWxlPSJtYXJnaW46MCAwIDAgLjhleDtib3JkZXItbGVmdDoxcHggI2NjYyBzb2xpZDtw YWRkaW5nLWxlZnQ6MWV4Ij4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIGVsc2U6PGJyPg0KLSDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCByZXR2YWwgPSBvcy5zeXN0ZW0oJnF1b3Q7bW91bnRfbnVs bGZzICZxdW90OyArIHNyYyArICZxdW90OyAmcXVvdDsgKzxicj4NCi0gwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgc2Vs Zi5zZXR0aW5nc1smcXVvdDtjaHJvb3RfcGF0aCZxdW90O10gKyBzcmMpPGJyPg0KKyDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBjbWQgPSAm cXVvdDttb3VudF9udWxsZnMgJnF1b3Q7ICsgc3JjICsgJnF1b3Q7ICZxdW90OyArIHRhcmdldDxi cj4NCisgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgcmV0dmFsPW9zLnN5c3RlbShjbWQpPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgZWxzZTo8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCBpZiBzcmMgPT0gJnF1b3Q7dG1wZnMmcXVvdDs6PGJyPg0KwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaWYgJnF1 b3Q7dmFyX3RtcGZzX3BvcnRhZ2UmcXVvdDsgaW4gc2VsZi5zZXR0aW5nczo8YnI+DQotIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIHJldHZhbD1vcy5zeXN0ZW0oJnF1b3Q7bW91bnQgLXQgdG1wZnMgLW8gc2l6ZT0mcXVv dDsrXDxicj4NCi0gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgc2VsZi5zZXR0aW5nc1smcXVvdDt2 YXJfdG1wZnNfcG9ydGFnZSZxdW90O10rJnF1b3Q7RyAmcXVvdDsrc3JjKyZxdW90OyAmcXVvdDsr XDxicj4NCi0gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgc2VsZi5zZXR0aW5nc1smcXVvdDtjaHJv b3RfcGF0aCZxdW90O10reCk8YnI+DQorIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGNtZCA9ICZxdW90O21vdW50IC10 IHRtcGZzIC1vIHNpemU9JnF1b3Q7ICsgXDxicj4NCisgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg c2VsZi5zZXR0aW5nc1smcXVvdDt2YXJfdG1wZnNfcG9ydGFnZSZxdW90O10gKyAmcXVvdDtHICZx dW90OyArIFw8YnI+DQorIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHNyYyArICZxdW90OyAmcXVv dDsgKyB0YXJnZXQ8YnI+DQorIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHJldHZhbD1vcy5zeXN0ZW0oY21kKTxicj4N CsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGVsc2U6PGJy Pg0KLSDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCByZXR2YWwgPSBvcy5zeXN0ZW0oJnF1b3Q7bW91bnQgLS1iaW5kICZxdW90OyArIHNyYyAr ICZxdW90OyAmcXVvdDsgKzxicj4NCi0gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgc2VsZi5zZXR0aW5nc1smcXVvdDtj aHJvb3RfcGF0aCZxdW90O10gKyBzcmMpPGJyPg0KKyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBjbWQgPSAmcXVvdDttb3VudCAtLWJpbmQg JnF1b3Q7ICsgc3JjICsgJnF1b3Q7ICZxdW90OyArIHRhcmdldDxicj4NCisgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgI3ByaW50ICZxdW90 O2JpbmQoKTsgY21kID0mcXVvdDssIGNtZDxicj4NCisgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgcmV0dmFsPW9zLnN5c3RlbShjbWQpPGJy Pg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaWYgcmV0dmFsIT0wOjxicj4N CsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHNlbGYudW5i aW5kKCk8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCByYWlzZSBDYXRhbHlzdEVycm9yLCZxdW90O0NvdWxkbiYjMzk7dCBiaW5kIG1vdW50ICZxdW90 OyArIHNyYzxicj4NCkBAIC05MzUsMjYgKzk2MiwyNSBAQCBjbGFzcyBnZW5lcmljX3N0YWdlX3Rh cmdldChnZW5lcmljX3RhcmdldCk6PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgbXlyZXZt b3VudHMucmV2ZXJzZSgpPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgJnF1b3Q7JnF1b3Q7 JnF1b3Q7IFVubW91bnQgaW4gcmV2ZXJzZSBvcmRlciBmb3IgbmVzdGVkIGJpbmQtbW91bnRzICZx dW90OyZxdW90OyZxdW90Ozxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGZvciB4IGluIG15 cmV2bW91bnRzOjxicj4NCi0gwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaWYgbm90 IG9zLnBhdGguZXhpc3RzKG15cGF0aCArIHNlbGYubW91bnRtYXBbeF0pOjxicj4NCisgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgdGFyZ2V0ID0gbm9ybXBhdGgobXlwYXRoICsgc2Vs Zi50YXJnZXRfbW91bnRzW3hdKTxicj4NCisgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgaWYgbm90IG9zLnBhdGguZXhpc3RzKHRhcmdldCk6PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgY29udGludWU8YnI+DQo8YnI+DQotIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGlmIG5vdCBpc21vdW50KG15cGF0aCArIHNlbGYu bW91bnRtYXBbeF0pOjxicj4NCisgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaWYg bm90IGlzbW91bnQodGFyZ2V0KTo8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCBjb250aW51ZTxicj4NCjxicj4NCi0gwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgcmV0dmFsPW9zLnN5c3RlbSgmcXVvdDt1bW91bnQgJnF1b3Q7K1w8YnI+ DQotIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIG9zLnBhdGgu am9pbihteXBhdGgsIHNlbGYubW91bnRtYXBbeF0ubHN0cmlwKG9zLnBhdGguc2VwKSkpPGJyPg0K KyDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCByZXR2YWw9b3Muc3lzdGVtKCZxdW90 O3Vtb3VudCAmcXVvdDsgKyB0YXJnZXQpPGJyPg0KPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgaWYgcmV0dmFsIT0wOjxicj4NCi0gwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgd2FybigmcXVvdDtGaXJzdCBhdHRlbXB0IHRvIHVubW91 bnQ6ICZxdW90OyArIG15cGF0aCArPGJyPg0KLSDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBzZWxmLm1vdW50bWFwW3hdICsmcXVvdDsgZmFp bGVkLiZxdW90Oyk8YnI+DQorIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIHdhcm4oJnF1b3Q7Rmlyc3QgYXR0ZW1wdCB0byB1bm1vdW50OiAmcXVvdDsgKyB0YXJn ZXQgKyAmcXVvdDsgZmFpbGVkLiZxdW90Oyk8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCB3YXJuKCZxdW90O0tpbGxpbmcgYW55IHBpZHMgc3RpbGwg cnVubmluZyBpbiB0aGUgY2hyb290JnF1b3Q7KTxicj4NCjxicj4NCsKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHNlbGYua2lsbF9jaHJvb3RfcGlkcygpPGJy Pg0KPGJyPg0KLSDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBy ZXR2YWwyID0gb3Muc3lzdGVtKCZxdW90O3Vtb3VudCAmcXVvdDsgKyBteXBhdGggKyBzZWxmLm1v dW50bWFwW3hdKTxicj4NCisgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgcmV0dmFsMiA9IG9zLnN5c3RlbSgmcXVvdDt1bW91bnQgJnF1b3Q7ICsgdGFyZ2V0KTxi cj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGlmIHJl dHZhbDIhPTA6PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgb3VjaD0xPGJyPg0KLSDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCB3YXJuKCZxdW90O0NvdWxkbiYjMzk7dCB1 bW91bnQgYmluZCBtb3VudDogJnF1b3Q7ICsgbXlwYXRoICsgc2VsZi5tb3VudG1hcFt4XSk8YnI+ DQorIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIHdhcm4oJnF1b3Q7Q291bGRuJiMzOTt0IHVtb3VudCBiaW5kIG1vdW50OiAmcXVvdDsgKyB0 YXJnZXQpPGJyPg0KPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaWYg JnF1b3Q7U05BUENBQ0hFJnF1b3Q7IGluIHNlbGYuc2V0dGluZ3MgYW5kIHggPT0gJnF1b3Q7L3Vz ci9wb3J0YWdlJnF1b3Q7Ojxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIHRyeTo8YnI+DQpkaWZmIC0tZ2l0IGEvbW9kdWxlcy9zdGFnZTFfdGFyZ2V0 LnB5IGIvbW9kdWxlcy9zdGFnZTFfdGFyZ2V0LnB5PGJyPg0KaW5kZXggYWE0MzkyNi4uMWUwZDg3 NCAxMDA2NDQ8YnI+DQotLS0gYS9tb2R1bGVzL3N0YWdlMV90YXJnZXQucHk8YnI+DQorKysgYi9t b2R1bGVzL3N0YWdlMV90YXJnZXQucHk8YnI+DQpAQCAtODgsOCArODgsOSBAQCBjbGFzcyBzdGFn ZTFfdGFyZ2V0KGdlbmVyaWNfc3RhZ2VfdGFyZ2V0KTo8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCBvcy5tYWtlZGlycyhzZWxmLnNldHRpbmdzWyZxdW90O3N0YWdlX3Bh dGgmcXVvdDtdKyZxdW90Oy9wcm9jJnF1b3Q7KTxicj4NCjxicj4NCsKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgICMgYWx0ZXIgdGhlIG1vdW50IG1hcHBpbmdzIHRvIGJpbmQgbW91bnQgcHJvYyBvbnRv IGl0PGJyPg0KLSDCoCDCoCDCoCDCoCDCoCDCoCDCoCBzZWxmLm1vdW50cy5hcHBlbmQoJnF1b3Q7 L3RtcC9zdGFnZTFyb290L3Byb2MmcXVvdDspPGJyPg0KLSDCoCDCoCDCoCDCoCDCoCDCoCDCoCBz ZWxmLm1vdW50bWFwWyZxdW90Oy90bXAvc3RhZ2Uxcm9vdC9wcm9jJnF1b3Q7XT0mcXVvdDsvcHJv YyZxdW90Ozxicj4NCisgwqAgwqAgwqAgwqAgwqAgwqAgwqAgc2VsZi5tb3VudHMuYXBwZW5kKCZx dW90O3N0YWdlMXJvb3QvcHJvYyZxdW90Oyk8YnI+DQorIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHNl bGYudGFyZ2V0X21vdW50c1smcXVvdDtzdGFnZTFyb290L3Byb2MmcXVvdDtdID0gJnF1b3Q7L3Rt cC9zdGFnZTFyb290L3Byb2MmcXVvdDs8YnI+DQorIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHNlbGYu bW91bnRtYXBbJnF1b3Q7c3RhZ2Uxcm9vdC9wcm9jJnF1b3Q7XT0mcXVvdDsvcHJvYyZxdW90Ozxi cj4NCjxicj4NCsKgZGVmIHJlZ2lzdGVyKGZvbyk6PGJyPg0KwqAgwqAgwqAgwqAgZm9vLnVwZGF0 ZSh7JnF1b3Q7c3RhZ2UxJnF1b3Q7OnN0YWdlMV90YXJnZXR9KTxicj4NCjxzcGFuIGNsYXNzPSJI T0VuWmIiPjxmb250IGNvbG9yPSIjODg4ODg4Ij4tLTxicj4NCjEuOC4zLjI8YnI+DQo8YnI+DQo8 YnI+DQo8L2ZvbnQ+PC9zcGFuPjwvYmxvY2txdW90ZT48L2Rpdj48YnI+PC9kaXY+PC9kaXY+DQo= --089e010d84e64799a304eea5931b--