In this module, we will:

Review of Yesterday

Very briefly, yesterday after learning about storage best practices and various storage options available to UMich researchers, we gained direct experience using these options by transferring our dataset to our own Data Den and Turbo storage locations.


We learned about a broadly-available and very generous compute package available to UMich researchers - the UMRCP - and now we’ll take a few moments to briefly review that.


We also discussed HPC compute clusters managed by ARC and had some opportunities to use the Great Lakes cluster, utilizing some of the web-based connection methods.

We talked about a pattern that may be new to us. In order to really use the HPC cluster, we had to request the appropriate resources from the system ahead of time. Let’s take a few moments to briefly review our experiences there. Today we’ll extend this idea.


Today we’re going to discuss more in depth about additional, powerful methods for connecting to the Great Lakes cluster, requesting resources, and ultimately running jobs in a more reproducible and automatable way. We’ll add more concrete detail about how this works, and gain experience through our exercises.

Great Lakes HPC

Again, we’ll provide the link to ARC’s general overview page on Great Lakes here: https://arc.umich.edu/greatlakes/

Let’s not go there right now, but I’d just like to point out that there’s a good deal of informational resources available on ARC’s website.




A More Detailed Look at How Great Lakes Works

We may have briefly mentioned the concept of a login node and a worker node when getting acquainted with Great Lakes, but we kept the explanation minimal, and only stated the fact that resources must be specified ahead of time for our tasks. With this figure we can dive a bit deeper into how this works.


Software Modules Available on Great Lakes

For our benefit, ARC has made available a plethora of widely used and oft-requested software tools, via their module system. We may refer to this module system as LMOD. We won’t cover the details of how it works, however we’ll demonstrate their usage and get a feel for using these LMOD modules on Great Lakes in our exercises.

The usage is very simple:

  • module load <name-of-module> to enable a particular module
  • module unload <name-of-module> to disable that module
  • module purge to unload all modules
  • module keyword <keyword> to search the modules for a particular keyword
  • module spider <name-of-module> to view all versions of a particular software - many different versions may be available

We’ll use these command-line methods for exploring and using LMOD modules in our exercises shortly, but it may also be helpful to later review this link to all software modules available on various ARC HPC clusters.

Exercise - Log in to Great Lakes using ssh

Following along with the instructor, we’ll all log in to the Great Lakes cluster using ssh. Once there, we’ll get a brief introduction to using the module system.


Scheduled Jobs

We’ve taken a look into how, but now we’re going to go a little deeper on the why aspect - why is the HPC cluster set up this way?

Remember, this infrastructure must support the entire university. This means that we need a system to provide resources in a controlled, efficient, and reasonably fair way.

By having formal mechanisms for requesting resources, and utilizing a job queue and a scheduler to allocate resources and assign them to jobs, we can achieve these goals.


Interactive and Scripted Jobs

We’ve gained a little experience with some types of interactive jobs, for instance during our RStudio demonstration or when we verified the file integrity of our BAMs with md5sum using the OpenOnDemand ‘Basic Desktop’ app. During that exercise, we mentioned that there are other ways of doing this, which we’ll introduce here.

We’ve just logged in using SSH to the Great Lakes HPC, and now we’re all interacting with the login node. Thinking back to yesterday when we were writing the README file, we were similarly interacting with the login node. We mentioned that we can’t do anything compute-intensive here, and instead offered the OpenOnDemand apps as an alternative.

What we didn’t discuss was that where we are now - on the login node - we have the ability to request resources and run jobs via the command line. These are the powerful abilities that we alluded to, and we have two ways of doing this - interactive and scripted jobs.


Interactive Jobs

When we speak of interactive jobs on the command line, what we really mean is that we request resources in a special way so that once they are granted, our shell will be ‘sent’ into a worker node, and we will be able to interact with a command-line interface that is running inside of our worker node. We’ll have all of our desired resources, and we’ll be able to execute our compute-intensive tasks in an interactive way.

In some of the educational material provided by ARC, a lot of times they will introduce this idea later on, or briefly mentioned as an aside. However, we want to introduce it right away, because it’s very useful as a starting point, and is a great way to ‘right-size’ your scripted jobs, which we’ll cover in a moment.

When would we want to run an interactive job?

  • When we’re not quite sure about the resources needed
  • When we want to verify that our commands will work correctly
  • When runtimes are relatively short and commands are fairly straightforward

How do we launch an interactive job from the command line? See the example here:

srun --pty --job-name=${USER}_calculate_md5sum --account=bioinf_wkshp_class --partition standard --mem=2000 --cpus-per-task=1 --time=00:30:00 /bin/bash


Scripted Jobs

When we talk about scripted jobs, generally we mean that inside of a file we place commands that we want to run in order - a script - along with the resource requirements.

In this case, when the resources become available, the contents of the script are executed on a worker node. There is no interaction with the running job. Any feedback that we’d normally receive in the terminal, can go to a log file. We’ll see an example of this.

When would we want to run scripted jobs?

  • When we’re confident that our script/processes are correct and do what we want
  • When we’re confident that we are requesting adequate resources
  • When we want reproducibility
  • When we want scalability, we have the ability of creating many scripted jobs ahead of time, and launching them all at once

What does a scripted job look like? See the dropdown section here:

SBATCH example
#!/bin/bash
# The interpreter used to execute the script

#“#SBATCH” directives that convey submission options:

#SBATCH --job-name=Hello_SBATCH
#SBATCH --cpus-per-task=1
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --mem-per-cpu=400m
#SBATCH --time=00:05:00
#SBATCH --account=bioinf_wkshp_class
#SBATCH --partition=standard
#SBATCH --output=/nfs/turbo/umms-bioinf-wkshp/workshop/home/%u/sleeping_bear/logs/%x-%j.log

# The application(s) to execute along with its input arguments and options:

hostname
pwd

echo "Hello, SBATCH!"

sleep 60


Briefly, we place our resource requirements at the top of our file - the preamble - and then we place our scripted commands until the end of the file. Once we have our file written - our SBATCH file - we’ll launch it with the command sbatch. For example:

sbatch <name-of-SBATCH-file>

We’ll have a chance to try this in a moment, after we get warmed up with some interactive jobs.

Note: We’re just going to demonstrate some of the most salient bits of requesting resources. There are a lot more informational resources available at ARC’s SLURM user guide.


Exercise SBATCH Hello World

Following along with the instructor, we will inspect the hello_SBATCH.sh shell script that each of us have in our $WORKSHOP_HOME directory, review the preamble and body of it, and then submit it with sbatch. Once it is running, we will use squeue to view the status of the job. After it completes, we’ll view its log.

SBATCH Hello World - Solution

source /nfs/turbo/umms-bioinf-wkshp/workshop/home/${USER}/source_me_for_shortcut.txt

cd ${WORKSHOP_HOME}/project_analysis

sbatch ../intro_scripts/hello_SBATCH.sh

While the job is running, check the job queue with: squeue -u $USER


Exercise srun with LMOD - Indexing our BAM Files

Following along with the instructor, we’ll launch an interactive job with srun, load the samtools module, and use samtools to index our BAM files. This is a required step for some of our later processes, so we’ll take care of it now. Additionally, we should do a baseline sanity check of the number of entries in each sample.

srun with LMOD Indexing BAMs - Solution

srun --pty --job-name=${USER}_index_bams --account=bioinf_wkshp_class --partition standard --mem=2000 --cpus-per-task=2 --time=00:30:00 /bin/bash

module load Bioinformatics; module load samtools

for f in *.bam ; do echo $f ; samtools index $f ; done

for f in *.bam ; do echo -n "${f}: " ; samtools view $f | wc -l ; done

Note: Type the command exit to exit from a running interactive job. This will put you back onto the log in node and free up remaining resources.


Exercise srun with LMOD - Filtering our BAM Files

Following along with the instructor, we’ll launch an interactive job with srun, load the samtools module, and use samtools to filter our sample_A BAM file to select only alignments from chromosome 19.

srun with LMOD Filtering BAM - Solution

srun --pty --job-name=${USER}_filter_sample_A --account=bioinf_wkshp_class --partition standard --mem=2000 --cpus-per-task=2 --time=00:30:00 /bin/bash

module load Bioinformatics; module load samtools

mkdir filter_lmod

samtools view -o filter_lmod/sample_A.chr19.bam input_bams/sample_A.genome.bam 19

Note: We re-create this same filtered BAM file in the additional SBATCH exercises below


Exercise SBATCH with LMOD - Filtering our BAM Files Cont’d

Following along with the instructor, we’ll create an SBATCH script that is similar to our previous srun exercise, and use that to filter our sample_B BAM file in the same fashion. We will launch it with sbatch and inspect the results. If it is successful, we will continue this exercise by creating and running two more SBATCH scripts for sample_C and sample_D.

SBATCH with LMOD Filtering BAMs Cont’d - Solution

cp ../intro_scripts/hello_SBATCH.sh scripts/filter_lmod_sample_A_sbatch.sh

nano scripts/filter_lmod_sample_A_sbatch.sh # Edit the file appropriately

sbatch scripts/filter_lmod_sample_A_sbatch.sh

When we’re happy with how sample_A turned out, we’ll copy our sbatch file and set it up for sample_B etc.

cp scripts/filter_lmod_sample_A_sbatch.sh scripts/filter_lmod_sample_B_sbatch.sh

nano scripts/filter_lmod_sample_B_sbatch.sh

sbatch scripts/filter_lmod_sample_B_sbatch.sh


Contents of filter_lmod_sample_A_sbatch.sh

#!/bin/bash
# The interpreter used to execute the script

#“#SBATCH” directives that convey submission options:

#SBATCH --job-name=Filter_sample_A
#SBATCH --cpus-per-task=2
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --mem-per-cpu=2000m
#SBATCH --time=00:20:00
#SBATCH --account=bioinf_wkshp_class
#SBATCH --partition=standard
#SBATCH --output=/nfs/turbo/umms-bioinf-wkshp/workshop/home/%u/project_analysis/logs/%x-%j.log

# The application(s) to execute along with its input arguments and options:

hostname
pwd

module load Bioinformatics
module load samtools
samtools view -o filter_lmod/sample_A.chr19.bam input_bams/sample_A.genome.bam 19


Note: Make sure to unload the samtools module, so that it does not interfere with the conda exercises in the next section!


Previous lesson Top of this lesson Next lesson
LS0tCnRpdGxlOiAiR3JlYXQgTGFrZXMgSFBDIENsdXN0ZXIiCmF1dGhvcjogIlVNIEJpb2luZm9ybWF0aWNzIENvcmUiCm91dHB1dDoKICAgICAgICBodG1sX2RvY3VtZW50OgogICAgICAgICAgICBpbmNsdWRlczoKICAgICAgICAgICAgICAgIGluX2hlYWRlcjogaGVhZGVyLmh0bWwKICAgICAgICAgICAgdGhlbWU6IHBhcGVyCiAgICAgICAgICAgIG51bWJlcl9zZWN0aW9uczogZmFsc2UKICAgICAgICAgICAgZmlnX2NhcHRpb246IHRydWUKICAgICAgICAgICAgbWFya2Rvd246IEdGTQogICAgICAgICAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCi0tLQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPgpib2R5eyAvKiBOb3JtYWwgICovCiAgICAgIGZvbnQtc2l6ZTogMTRwdDsKICB9CnByZSB7CiAgZm9udC1zaXplOiAxMnB0Cn0KPC9zdHlsZT4KCkluIHRoaXMgbW9kdWxlLCB3ZSB3aWxsOgoKKiBkaXNjdXNzIHRoZSBHcmVhdCBMYWtlcyBIUEMgY2x1c3RlciBhbmQgcmV2aWV3IGl0cyB1c2FnZQoqIGRpc2N1c3Mgc29mdHdhcmUgbW9kdWxlcyBhdmFpbGFibGUgb24gR3JlYXQgTGFrZXMKKiBsb2cgaW4gdG8gdGhlIEdyZWF0IExha2VzIGNsdXN0ZXIgdXNpbmcgYHNzaGAKKiByZXZpZXcgc29tZSBvZiB0aGUgZnVuZGFtZW50YWwgaGVscGVyIGNvbW1hbmRzIG9uIEdyZWF0IExha2VzCiogcmV2aWV3IFNCQVRDSCBhbmQgc3VibWl0IGpvYnMgZm9yIG91ciBhbmFseXNpcwoKIyMgUmV2aWV3IG9mIFllc3RlcmRheQoKVmVyeSBicmllZmx5LCB5ZXN0ZXJkYXkgYWZ0ZXIgbGVhcm5pbmcgYWJvdXQgc3RvcmFnZSBiZXN0IHByYWN0aWNlcyBhbmQgdmFyaW91cyBzdG9yYWdlIG9wdGlvbnMgYXZhaWxhYmxlIHRvIFVNaWNoIHJlc2VhcmNoZXJzLCB3ZSBnYWluZWQgZGlyZWN0IGV4cGVyaWVuY2UgdXNpbmcgdGhlc2Ugb3B0aW9ucyBieSB0cmFuc2ZlcnJpbmcgb3VyIGRhdGFzZXQgdG8gb3VyIG93biBEYXRhIERlbiBhbmQgVHVyYm8gc3RvcmFnZSBsb2NhdGlvbnMuCgo8YnI+CgpXZSBsZWFybmVkIGFib3V0IGEgYnJvYWRseS1hdmFpbGFibGUgYW5kIHZlcnkgZ2VuZXJvdXMgY29tcHV0ZSBwYWNrYWdlIGF2YWlsYWJsZSB0byBVTWljaCByZXNlYXJjaGVycyAtIHRoZSBVTVJDUCAtIGFuZCBub3cgd2UnbGwgdGFrZSBhIGZldyBtb21lbnRzIHRvIGJyaWVmbHkgcmV2aWV3IHRoYXQuCgohW10oaW1hZ2VzL01vZHVsZTAxX1VNUkNQX3Byb3ZpZGVzLnBuZykKCjxicj4KCldlIGFsc28gZGlzY3Vzc2VkIEhQQyBjb21wdXRlIGNsdXN0ZXJzIG1hbmFnZWQgYnkgQVJDIGFuZCBoYWQgc29tZSBvcHBvcnR1bml0aWVzIHRvIHVzZSB0aGUgR3JlYXQgTGFrZXMgY2x1c3RlciwgIHV0aWxpemluZyBzb21lIG9mIHRoZSB3ZWItYmFzZWQgY29ubmVjdGlvbiBtZXRob2RzLgoKV2UgdGFsa2VkIGFib3V0IGEgcGF0dGVybiB0aGF0IG1heSBiZSBuZXcgdG8gdXMuIEluIG9yZGVyIHRvIHJlYWxseSB1c2UgdGhlIEhQQyBjbHVzdGVyLCB3ZSBoYWQgdG8gcmVxdWVzdCB0aGUgYXBwcm9wcmlhdGUgcmVzb3VyY2VzIGZyb20gdGhlIHN5c3RlbSBhaGVhZCBvZiB0aW1lLiBMZXQncyB0YWtlIGEgZmV3IG1vbWVudHMgdG8gYnJpZWZseSByZXZpZXcgb3VyIGV4cGVyaWVuY2VzIHRoZXJlLiBUb2RheSB3ZSdsbCBleHRlbmQgdGhpcyBpZGVhLgoKPGJyPgoKVG9kYXkgd2UncmUgZ29pbmcgdG8gZGlzY3VzcyBtb3JlIGluIGRlcHRoIGFib3V0IGFkZGl0aW9uYWwsIHBvd2VyZnVsIG1ldGhvZHMgZm9yIGNvbm5lY3RpbmcgdG8gdGhlIEdyZWF0IExha2VzIGNsdXN0ZXIsIHJlcXVlc3RpbmcgcmVzb3VyY2VzLCBhbmQgdWx0aW1hdGVseSBydW5uaW5nIGpvYnMgaW4gYSBtb3JlIHJlcHJvZHVjaWJsZSBhbmQgYXV0b21hdGFibGUgd2F5LiBXZSdsbCBhZGQgbW9yZSBjb25jcmV0ZSBkZXRhaWwgYWJvdXQgaG93IHRoaXMgd29ya3MsIGFuZCBnYWluIGV4cGVyaWVuY2UgdGhyb3VnaCBvdXIgZXhlcmNpc2VzLgoKIyMgR3JlYXQgTGFrZXMgSFBDCgpBZ2Fpbiwgd2UnbGwgcHJvdmlkZSB0aGUgbGluayB0byBBUkMncyBnZW5lcmFsIG92ZXJ2aWV3IHBhZ2Ugb24gR3JlYXQgTGFrZXMgaGVyZTogaHR0cHM6Ly9hcmMudW1pY2guZWR1L2dyZWF0bGFrZXMvCgohW10oaW1hZ2VzL01vZHVsZTAzYl9hcmNfc2l0ZV9uYXZiYXIucG5nKQoKTGV0J3Mgbm90IGdvIHRoZXJlIHJpZ2h0IG5vdywgYnV0IEknZCBqdXN0IGxpa2UgdG8gcG9pbnQgb3V0IHRoYXQgdGhlcmUncyBhIGdvb2QgZGVhbCBvZiBpbmZvcm1hdGlvbmFsIHJlc291cmNlcyBhdmFpbGFibGUgb24gQVJDJ3Mgd2Vic2l0ZS4KCjxicj4KPGJyPgo8YnI+CgojIyMgQSBNb3JlIERldGFpbGVkIExvb2sgYXQgSG93IEdyZWF0IExha2VzIFdvcmtzCiFbXShpbWFnZXMvTW9kdWxlMDNfY2x1c3Rlcl9vdmVydmlldy5wbmcpCgpXZSBtYXkgaGF2ZSBicmllZmx5IG1lbnRpb25lZCB0aGUgY29uY2VwdCBvZiBhIGxvZ2luIG5vZGUgYW5kIGEgd29ya2VyIG5vZGUgd2hlbiBnZXR0aW5nIGFjcXVhaW50ZWQgd2l0aCBHcmVhdCBMYWtlcywgYnV0IHdlIGtlcHQgdGhlIGV4cGxhbmF0aW9uIG1pbmltYWwsIGFuZCBvbmx5IHN0YXRlZCB0aGUgZmFjdCB0aGF0IHJlc291cmNlcyBtdXN0IGJlIHNwZWNpZmllZCBhaGVhZCBvZiB0aW1lIGZvciBvdXIgdGFza3MuIFdpdGggdGhpcyBmaWd1cmUgd2UgY2FuIGRpdmUgYSBiaXQgZGVlcGVyIGludG8gaG93IHRoaXMgd29ya3MuCgo8YnI+CgojIyMgU29mdHdhcmUgTW9kdWxlcyBBdmFpbGFibGUgb24gR3JlYXQgTGFrZXMKCkZvciBvdXIgYmVuZWZpdCwgQVJDIGhhcyBtYWRlIGF2YWlsYWJsZSBhIHBsZXRob3JhIG9mIHdpZGVseSB1c2VkIGFuZCBvZnQtcmVxdWVzdGVkIHNvZnR3YXJlIHRvb2xzLCB2aWEgdGhlaXIgbW9kdWxlIHN5c3RlbS4gV2UgbWF5IHJlZmVyIHRvIHRoaXMgbW9kdWxlIHN5c3RlbSBhcyBMTU9ELiBXZSB3b24ndCBjb3ZlciB0aGUgZGV0YWlscyBvZiBob3cgaXQgd29ya3M8IS0tIExJVkVfTk9URTogbm90ZSB3ZSB3aWxsIHJldmlzaXQgdGhpcyBpZGVhIHdoZW4gY29tcGFyaW5nIHdpdGggb3RoZXIgc29mdHdhcmUgbWFuYWdlbWVudCBzb2x1dGlvbnMgbGF0ZXIgLS0+LCBob3dldmVyIHdlJ2xsIGRlbW9uc3RyYXRlIHRoZWlyIHVzYWdlIGFuZCBnZXQgYSBmZWVsIGZvciB1c2luZyB0aGVzZSBMTU9EIG1vZHVsZXMgb24gR3JlYXQgTGFrZXMgaW4gb3VyIGV4ZXJjaXNlcy4KClRoZSB1c2FnZSBpcyB2ZXJ5IHNpbXBsZToKCi0gYG1vZHVsZSBsb2FkIDxuYW1lLW9mLW1vZHVsZT5gIHRvIGVuYWJsZSBhIHBhcnRpY3VsYXIgbW9kdWxlCi0gYG1vZHVsZSB1bmxvYWQgPG5hbWUtb2YtbW9kdWxlPmAgdG8gZGlzYWJsZSB0aGF0IG1vZHVsZQotIGBtb2R1bGUgcHVyZ2VgIHRvIHVubG9hZCBhbGwgbW9kdWxlcwotIGBtb2R1bGUga2V5d29yZCA8a2V5d29yZD5gIHRvIHNlYXJjaCB0aGUgbW9kdWxlcyBmb3IgYSBwYXJ0aWN1bGFyIGtleXdvcmQKLSBgbW9kdWxlIHNwaWRlciA8bmFtZS1vZi1tb2R1bGU+YCB0byB2aWV3IGFsbCB2ZXJzaW9ucyBvZiBhIHBhcnRpY3VsYXIgc29mdHdhcmUgLSBtYW55IGRpZmZlcmVudCB2ZXJzaW9ucyBtYXkgYmUgYXZhaWxhYmxlCgpXZSdsbCB1c2UgdGhlc2UgY29tbWFuZC1saW5lIG1ldGhvZHMgZm9yIGV4cGxvcmluZyBhbmQgdXNpbmcgTE1PRCBtb2R1bGVzIGluIG91ciBleGVyY2lzZXMgc2hvcnRseSwgYnV0IGl0IG1heSBhbHNvIGJlIGhlbHBmdWwgdG8gbGF0ZXIgcmV2aWV3IHRoaXMgW2xpbmsgdG8gYWxsIHNvZnR3YXJlIG1vZHVsZXMgYXZhaWxhYmxlIG9uIHZhcmlvdXMgQVJDIEhQQyBjbHVzdGVyc10oaHR0cHM6Ly9hcmMudW1pY2guZWR1L3NvZnR3YXJlLykuCgojIyMgRXhlcmNpc2UgLSBMb2cgaW4gdG8gR3JlYXQgTGFrZXMgdXNpbmcgc3NoCgpGb2xsb3dpbmcgYWxvbmcgd2l0aCB0aGUgaW5zdHJ1Y3Rvciwgd2UnbGwgYWxsIGxvZyBpbiB0byB0aGUgR3JlYXQgTGFrZXMgY2x1c3RlciB1c2luZyBzc2guIE9uY2UgdGhlcmUsIHdlJ2xsIGdldCBhIGJyaWVmIGludHJvZHVjdGlvbiB0byB1c2luZyB0aGUgbW9kdWxlIHN5c3RlbS4KCjxicj4KCiMjIyBTY2hlZHVsZWQgSm9icwoKIVtdKGltYWdlcy9Nb2R1bGUwM19zY2hlZHVsZWRfam9icy5wbmcpCgpXZSd2ZSB0YWtlbiBhIGxvb2sgaW50byBob3csIGJ1dCBub3cgd2UncmUgZ29pbmcgdG8gZ28gYSBsaXR0bGUgZGVlcGVyIG9uIHRoZSB3aHkgYXNwZWN0IC0gd2h5IGlzIHRoZSBIUEMgY2x1c3RlciBzZXQgdXAgdGhpcyB3YXk/IAoKUmVtZW1iZXIsIHRoaXMgaW5mcmFzdHJ1Y3R1cmUgbXVzdCBzdXBwb3J0IHRoZSBlbnRpcmUgdW5pdmVyc2l0eS4gVGhpcyBtZWFucyB0aGF0IHdlIG5lZWQgYSBzeXN0ZW0gdG8gcHJvdmlkZSByZXNvdXJjZXMgaW4gYSBjb250cm9sbGVkLCBlZmZpY2llbnQsIGFuZCByZWFzb25hYmx5IGZhaXIgd2F5LgoKQnkgaGF2aW5nIGZvcm1hbCBtZWNoYW5pc21zIGZvciByZXF1ZXN0aW5nIHJlc291cmNlcywgYW5kIHV0aWxpemluZyBhIGpvYiBxdWV1ZSBhbmQgYSBzY2hlZHVsZXIgdG8gYWxsb2NhdGUgcmVzb3VyY2VzIGFuZCBhc3NpZ24gdGhlbSB0byBqb2JzLCB3ZSBjYW4gYWNoaWV2ZSB0aGVzZSBnb2Fscy4KCjwhLS0gTElWRV9OT1RFOiBSZWxhdGUgdGhlIGVmZmljaWVuY3kgb2YgdGhlIHNjaGVkdWxlZCBqb2JzIGluIHRoZSBmaWd1cmUuIElkbGUgdGltZSBpcyBtaW5pbWl6ZWQsIHdoaWxlIG1hbnkgZGlmZmVyZW50bHktc2l6ZWQgam9icyBjYW4gcnVuIHNpbXVsdGFuZW91c2x5IC0tPgoKPGJyPgoKIyMjIEludGVyYWN0aXZlIGFuZCBTY3JpcHRlZCBKb2JzCgpXZSd2ZSBnYWluZWQgYSBsaXR0bGUgZXhwZXJpZW5jZSB3aXRoIHNvbWUgdHlwZXMgb2YgaW50ZXJhY3RpdmUgam9icywgZm9yIGluc3RhbmNlIGR1cmluZyBvdXIgYFJTdHVkaW9gIGRlbW9uc3RyYXRpb24gb3Igd2hlbiB3ZSB2ZXJpZmllZCB0aGUgZmlsZSBpbnRlZ3JpdHkgb2Ygb3VyIEJBTXMgd2l0aCBgbWQ1c3VtYCB1c2luZyB0aGUgT3Blbk9uRGVtYW5kICdCYXNpYyBEZXNrdG9wJyBhcHAuIER1cmluZyB0aGF0IGV4ZXJjaXNlLCB3ZSBtZW50aW9uZWQgdGhhdCB0aGVyZSBhcmUgb3RoZXIgd2F5cyBvZiBkb2luZyB0aGlzLCB3aGljaCB3ZSdsbCBpbnRyb2R1Y2UgaGVyZS4KCldlJ3ZlIGp1c3QgbG9nZ2VkIGluIHVzaW5nIFNTSCB0byB0aGUgR3JlYXQgTGFrZXMgSFBDLCBhbmQgbm93IHdlJ3JlIGFsbCBpbnRlcmFjdGluZyB3aXRoIHRoZSBsb2dpbiBub2RlLiBUaGlua2luZyBiYWNrIHRvIHllc3RlcmRheSB3aGVuIHdlIHdlcmUgd3JpdGluZyB0aGUgUkVBRE1FIGZpbGUsIHdlIHdlcmUgc2ltaWxhcmx5IGludGVyYWN0aW5nIHdpdGggdGhlIGxvZ2luIG5vZGUuICBXZSBtZW50aW9uZWQgdGhhdCB3ZSBjYW4ndCBkbyBhbnl0aGluZyBjb21wdXRlLWludGVuc2l2ZSBoZXJlLCBhbmQgaW5zdGVhZCBvZmZlcmVkIHRoZSBPcGVuT25EZW1hbmQgYXBwcyBhcyBhbiBhbHRlcm5hdGl2ZS4KCldoYXQgd2UgZGlkbid0IGRpc2N1c3Mgd2FzIHRoYXQgd2hlcmUgd2UgYXJlIG5vdyAtIG9uIHRoZSBsb2dpbiBub2RlIC0gd2UgaGF2ZSB0aGUgYWJpbGl0eSB0byByZXF1ZXN0IHJlc291cmNlcyBhbmQgcnVuIGpvYnMgdmlhIHRoZSBjb21tYW5kIGxpbmUuIFRoZXNlIGFyZSB0aGUgcG93ZXJmdWwgYWJpbGl0aWVzIHRoYXQgd2UgYWxsdWRlZCB0bywgYW5kIHdlIGhhdmUgdHdvIHdheXMgb2YgZG9pbmcgdGhpcyAtIGludGVyYWN0aXZlIGFuZCBzY3JpcHRlZCBqb2JzLgoKPCEtLSBMSVZFX05PVEU6IFRoZXNlIGFyZSBib3RoIGV4YW1wbGVzIG9mIHNjaGVkdWxlZCBqb2JzLCBlaXRoZXIgd2F5IHdlJ2xsIHJlcXVlc3QgcmVzb3VyY2VzIGFuZCB1c2UgdGhlbSBvbmNlIGdyYW50ZWQgLS0+Cgo8YnI+CgojIyMgSW50ZXJhY3RpdmUgSm9icwoKV2hlbiB3ZSBzcGVhayBvZiBpbnRlcmFjdGl2ZSBqb2JzIG9uIHRoZSBjb21tYW5kIGxpbmUsIHdoYXQgd2UgcmVhbGx5IG1lYW4gaXMgdGhhdCB3ZSByZXF1ZXN0IHJlc291cmNlcyBpbiBhIHNwZWNpYWwgd2F5IHNvIHRoYXQgb25jZSB0aGV5IGFyZSBncmFudGVkLCBvdXIgc2hlbGwgd2lsbCBiZSAnc2VudCcgaW50byBhIHdvcmtlciBub2RlLCBhbmQgd2Ugd2lsbCBiZSBhYmxlIHRvIGludGVyYWN0IHdpdGggYSBjb21tYW5kLWxpbmUgaW50ZXJmYWNlIHRoYXQgaXMgcnVubmluZyBpbnNpZGUgb2Ygb3VyIHdvcmtlciBub2RlLiBXZSdsbCBoYXZlIGFsbCBvZiBvdXIgZGVzaXJlZCByZXNvdXJjZXMsIGFuZCB3ZSdsbCBiZSBhYmxlIHRvIGV4ZWN1dGUgb3VyIGNvbXB1dGUtaW50ZW5zaXZlIHRhc2tzIGluIGFuIGludGVyYWN0aXZlIHdheS4KCkluIHNvbWUgb2YgdGhlIGVkdWNhdGlvbmFsIG1hdGVyaWFsIHByb3ZpZGVkIGJ5IEFSQywgYSBsb3Qgb2YgdGltZXMgdGhleSB3aWxsIGludHJvZHVjZSB0aGlzIGlkZWEgbGF0ZXIgb24sIG9yIGJyaWVmbHkgbWVudGlvbmVkIGFzIGFuIGFzaWRlLiBIb3dldmVyLCB3ZSB3YW50IHRvIGludHJvZHVjZSBpdCByaWdodCBhd2F5LCBiZWNhdXNlIGl0J3MgdmVyeSB1c2VmdWwgYXMgYSBzdGFydGluZyBwb2ludCwgYW5kIGlzIGEgZ3JlYXQgd2F5IHRvICdyaWdodC1zaXplJyB5b3VyIHNjcmlwdGVkIGpvYnMsIHdoaWNoIHdlJ2xsIGNvdmVyIGluIGEgbW9tZW50LgoKV2hlbiB3b3VsZCB3ZSB3YW50IHRvIHJ1biBhbiBpbnRlcmFjdGl2ZSBqb2I/CgotIFdoZW4gd2UncmUgbm90IHF1aXRlIHN1cmUgYWJvdXQgdGhlIHJlc291cmNlcyBuZWVkZWQKLSBXaGVuIHdlIHdhbnQgdG8gdmVyaWZ5IHRoYXQgb3VyIGNvbW1hbmRzIHdpbGwgd29yayBjb3JyZWN0bHkKLSBXaGVuIHJ1bnRpbWVzIGFyZSByZWxhdGl2ZWx5IHNob3J0IGFuZCBjb21tYW5kcyBhcmUgZmFpcmx5IHN0cmFpZ2h0Zm9yd2FyZAoKPCEtLSBMSVZFX05PVEU6IENvbW1hbmRzIGluc2lkZSBvZiB0aGUgaW50ZXJhY3RpdmUgam9iIG1heSBsYWNrIHJlcHJvZHVjaWJpbGl0eSwgd2UgaGF2ZSB0byBtYW51YWxseSByZWNvcmQgd2hhdCB3ZSBkbyB3aXRoaW4gdGhlIGludGVyYWN0aXZlIGpvYi4gLS0+CgpIb3cgZG8gd2UgbGF1bmNoIGFuIGludGVyYWN0aXZlIGpvYiBmcm9tIHRoZSBjb21tYW5kIGxpbmU/IFNlZSB0aGUgZXhhbXBsZSBoZXJlOgoKYGBgCnNydW4gLS1wdHkgLS1qb2ItbmFtZT0ke1VTRVJ9X2NhbGN1bGF0ZV9tZDVzdW0gLS1hY2NvdW50PWJpb2luZl93a3NocF9jbGFzcyAtLXBhcnRpdGlvbiBzdGFuZGFyZCAtLW1lbT0yMDAwIC0tY3B1cy1wZXItdGFzaz0xIC0tdGltZT0wMDozMDowMCAvYmluL2Jhc2gKYGBgCgo8YnI+CgojIyMgU2NyaXB0ZWQgSm9icwoKV2hlbiB3ZSB0YWxrIGFib3V0IHNjcmlwdGVkIGpvYnMsIGdlbmVyYWxseSB3ZSBtZWFuIHRoYXQgaW5zaWRlIG9mIGEgZmlsZSB3ZSBwbGFjZSBjb21tYW5kcyB0aGF0IHdlIHdhbnQgdG8gcnVuIGluIG9yZGVyIC0gYSBzY3JpcHQgLSBhbG9uZyB3aXRoIHRoZSByZXNvdXJjZSByZXF1aXJlbWVudHMuCgpJbiB0aGlzIGNhc2UsIHdoZW4gdGhlIHJlc291cmNlcyBiZWNvbWUgYXZhaWxhYmxlLCB0aGUgY29udGVudHMgb2YgdGhlIHNjcmlwdCBhcmUgZXhlY3V0ZWQgb24gYSB3b3JrZXIgbm9kZS4gVGhlcmUgaXMgbm8gaW50ZXJhY3Rpb24gd2l0aCB0aGUgcnVubmluZyBqb2I8IS0tKipMSVZFX05PVEU6IEV4Y2VwdCBtYXliZSB0byBvYnNlcnZlIGl0KiogLS0+LiBBbnkgZmVlZGJhY2sgdGhhdCB3ZSdkIG5vcm1hbGx5IHJlY2VpdmUgaW4gdGhlIHRlcm1pbmFsLCBjYW4gZ28gdG8gYSBsb2cgZmlsZS4gV2UnbGwgc2VlIGFuIGV4YW1wbGUgb2YgdGhpcy4KCldoZW4gd291bGQgd2Ugd2FudCB0byBydW4gc2NyaXB0ZWQgam9icz8KCi0gV2hlbiB3ZSdyZSBjb25maWRlbnQgdGhhdCBvdXIgc2NyaXB0L3Byb2Nlc3NlcyBhcmUgY29ycmVjdCBhbmQgZG8gd2hhdCB3ZSB3YW50Ci0gV2hlbiB3ZSdyZSBjb25maWRlbnQgdGhhdCB3ZSBhcmUgcmVxdWVzdGluZyBhZGVxdWF0ZSByZXNvdXJjZXMKLSBXaGVuIHdlIHdhbnQgcmVwcm9kdWNpYmlsaXR5Ci0gV2hlbiB3ZSB3YW50IHNjYWxhYmlsaXR5LCB3ZSBoYXZlIHRoZSBhYmlsaXR5IG9mIGNyZWF0aW5nIG1hbnkgc2NyaXB0ZWQgam9icyBhaGVhZCBvZiB0aW1lLCBhbmQgbGF1bmNoaW5nIHRoZW0gYWxsIGF0IG9uY2UKCjwhLS0gTElWRV9OT1RFOiBUaGVyZSBhcmUgbWFueSBzb2x1dGlvbnMgZm9yIHNjYWxhYmlsaXR5LCB0aGF0IGNhbiBsZXZlcmVnZSBzY3JpcHRlZCBqb2JzIHdpdGhvdXQgYXMgbXVjaCB1cGZyb250IHdvcmsuIENocmlzIHdpbGwgY292ZXIgdGhlc2UgdG9tb3Jyb3cgLS0+CgpXaGF0IGRvZXMgYSBzY3JpcHRlZCBqb2IgbG9vayBsaWtlPyBTZWUgdGhlIGRyb3Bkb3duIHNlY3Rpb24gaGVyZToKCjwhLS0gTElWRV9OT1RFOiBXZSdsbCBzZWUgdGhpcyBpbiBqdXN0IGEgbW9tZW50LCBubyBuZWVkIHRvIGxvb2sgYXQgaXQgaGVyZSAtLT4KCjxkZXRhaWxzPgo8c3VtbWFyeT5TQkFUQ0ggZXhhbXBsZTwvc3VtbWFyeT4KCmBgYAojIS9iaW4vYmFzaAojIFRoZSBpbnRlcnByZXRlciB1c2VkIHRvIGV4ZWN1dGUgdGhlIHNjcmlwdAoKI+KAnCNTQkFUQ0jigJ0gZGlyZWN0aXZlcyB0aGF0IGNvbnZleSBzdWJtaXNzaW9uIG9wdGlvbnM6CgojU0JBVENIIC0tam9iLW5hbWU9SGVsbG9fU0JBVENICiNTQkFUQ0ggLS1jcHVzLXBlci10YXNrPTEKI1NCQVRDSCAtLW5vZGVzPTEKI1NCQVRDSCAtLW50YXNrcy1wZXItbm9kZT0xCiNTQkFUQ0ggLS1tZW0tcGVyLWNwdT00MDBtCiNTQkFUQ0ggLS10aW1lPTAwOjA1OjAwCiNTQkFUQ0ggLS1hY2NvdW50PWJpb2luZl93a3NocF9jbGFzcwojU0JBVENIIC0tcGFydGl0aW9uPXN0YW5kYXJkCiNTQkFUQ0ggLS1vdXRwdXQ9L25mcy90dXJiby91bW1zLWJpb2luZi13a3NocC93b3Jrc2hvcC9ob21lLyV1L3NsZWVwaW5nX2JlYXIvbG9ncy8leC0lai5sb2cKCiMgVGhlIGFwcGxpY2F0aW9uKHMpIHRvIGV4ZWN1dGUgYWxvbmcgd2l0aCBpdHMgaW5wdXQgYXJndW1lbnRzIGFuZCBvcHRpb25zOgoKaG9zdG5hbWUKcHdkCgplY2hvICJIZWxsbywgU0JBVENIISIKCnNsZWVwIDYwCmBgYAoKPC9kZXRhaWxzPgoKPGJyPgoKQnJpZWZseSwgd2UgcGxhY2Ugb3VyIHJlc291cmNlIHJlcXVpcmVtZW50cyBhdCB0aGUgdG9wIG9mIG91ciBmaWxlIC0gdGhlIHByZWFtYmxlIC0gYW5kIHRoZW4gd2UgcGxhY2Ugb3VyIHNjcmlwdGVkIGNvbW1hbmRzIHVudGlsIHRoZSBlbmQgb2YgdGhlIGZpbGUuIE9uY2Ugd2UgaGF2ZSBvdXIgZmlsZSB3cml0dGVuIC0gb3VyIFNCQVRDSCBmaWxlIC0gd2UnbGwgbGF1bmNoIGl0IHdpdGggdGhlIGNvbW1hbmQgYHNiYXRjaGAuIEZvciBleGFtcGxlOgoKYHNiYXRjaCA8bmFtZS1vZi1TQkFUQ0gtZmlsZT5gCgpXZSdsbCBoYXZlIGEgY2hhbmNlIHRvIHRyeSB0aGlzIGluIGEgbW9tZW50LCBhZnRlciB3ZSBnZXQgd2FybWVkIHVwIHdpdGggc29tZSBpbnRlcmFjdGl2ZSBqb2JzLgoKPk5vdGU6IFdlJ3JlIGp1c3QgZ29pbmcgdG8gZGVtb25zdHJhdGUgc29tZSBvZiB0aGUgbW9zdCBzYWxpZW50IGJpdHMgb2YgcmVxdWVzdGluZyByZXNvdXJjZXMuIFRoZXJlIGFyZSBhIGxvdCBtb3JlIGluZm9ybWF0aW9uYWwgcmVzb3VyY2VzIGF2YWlsYWJsZSBhdCBbQVJDJ3MgU0xVUk0gdXNlciBndWlkZV0oaHR0cHM6Ly9hcmMudW1pY2guZWR1L2dyZWF0bGFrZXMvc2x1cm0tdXNlci1ndWlkZS8pLgoKPGJyPgoKIyMgRXhlcmNpc2UgU0JBVENIIEhlbGxvIFdvcmxkCgpGb2xsb3dpbmcgYWxvbmcgd2l0aCB0aGUgaW5zdHJ1Y3Rvciwgd2Ugd2lsbCBpbnNwZWN0IHRoZSBgaGVsbG9fU0JBVENILnNoYCBzaGVsbCBzY3JpcHQgdGhhdCBlYWNoIG9mIHVzIGhhdmUgaW4gb3VyIGAkV09SS1NIT1BfSE9NRWAgZGlyZWN0b3J5LCByZXZpZXcgdGhlIHByZWFtYmxlIGFuZCBib2R5IG9mIGl0LCBhbmQgdGhlbiBzdWJtaXQgaXQgd2l0aCBgc2JhdGNoYC4gT25jZSBpdCBpcyBydW5uaW5nLCB3ZSB3aWxsIHVzZSBgc3F1ZXVlYCB0byB2aWV3IHRoZSBzdGF0dXMgb2YgdGhlIGpvYi4gQWZ0ZXIgaXQgY29tcGxldGVzLCB3ZSdsbCB2aWV3IGl0cyBsb2cuCgo8ZGV0YWlscz4KPHN1bW1hcnk+U0JBVENIIEhlbGxvIFdvcmxkIC0gU29sdXRpb248L3N1bW1hcnk+Cgpgc291cmNlIC9uZnMvdHVyYm8vdW1tcy1iaW9pbmYtd2tzaHAvd29ya3Nob3AvaG9tZS8ke1VTRVJ9L3NvdXJjZV9tZV9mb3Jfc2hvcnRjdXQudHh0YAoKYGNkICR7V09SS1NIT1BfSE9NRX0vcHJvamVjdF9hbmFseXNpc2AKCmBzYmF0Y2ggLi4vaW50cm9fc2NyaXB0cy9oZWxsb19TQkFUQ0guc2hgCgpXaGlsZSB0aGUgam9iIGlzIHJ1bm5pbmcsIGNoZWNrIHRoZSBqb2IgcXVldWUgd2l0aDoKYHNxdWV1ZSAtdSAkVVNFUmAKCjwvZGV0YWlscz4KCjxicj4KCiMjIEV4ZXJjaXNlIGBzcnVuYCB3aXRoIExNT0QgLSBJbmRleGluZyBvdXIgQkFNIEZpbGVzCgpGb2xsb3dpbmcgYWxvbmcgd2l0aCB0aGUgaW5zdHJ1Y3Rvciwgd2UnbGwgbGF1bmNoIGFuIGludGVyYWN0aXZlIGpvYiB3aXRoIGBzcnVuYCwgbG9hZCB0aGUgc2FtdG9vbHMgbW9kdWxlLCBhbmQgdXNlIHNhbXRvb2xzIHRvIGluZGV4IG91ciBCQU0gZmlsZXMuIFRoaXMgaXMgYSByZXF1aXJlZCBzdGVwIGZvciBzb21lIG9mIG91ciBsYXRlciBwcm9jZXNzZXMsIHNvIHdlJ2xsIHRha2UgY2FyZSBvZiBpdCBub3cuIEFkZGl0aW9uYWxseSwgd2Ugc2hvdWxkIGRvIGEgYmFzZWxpbmUgc2FuaXR5IGNoZWNrIG9mIHRoZSBudW1iZXIgb2YgZW50cmllcyBpbiBlYWNoIHNhbXBsZS4KCjxkZXRhaWxzPgo8c3VtbWFyeT5gc3J1bmAgd2l0aCBMTU9EIEluZGV4aW5nIEJBTXMgLSBTb2x1dGlvbjwvc3VtbWFyeT4KCmBzcnVuIC0tcHR5IC0tam9iLW5hbWU9JHtVU0VSfV9pbmRleF9iYW1zIC0tYWNjb3VudD1iaW9pbmZfd2tzaHBfY2xhc3MgLS1wYXJ0aXRpb24gc3RhbmRhcmQgLS1tZW09MjAwMCAtLWNwdXMtcGVyLXRhc2s9MiAtLXRpbWU9MDA6MzA6MDAgL2Jpbi9iYXNoYAoKYG1vZHVsZSBsb2FkIEJpb2luZm9ybWF0aWNzOyBtb2R1bGUgbG9hZCBzYW10b29sc2AKCmBmb3IgZiBpbiAqLmJhbSA7IGRvIGVjaG8gJGYgOyBzYW10b29scyBpbmRleCAkZiA7IGRvbmVgCgo8IS0tIExJVkVfTk9URTogTmVlZCB0byBkbyBhIGJhc2VsaW5lIHNhbml0eSBjaGVjayBoZXJlOiAtLT4KYGZvciBmIGluICouYmFtIDsgZG8gZWNobyAtbiAiJHtmfTogIiA7IHNhbXRvb2xzIHZpZXcgJGYgfCB3YyAtbCA7IGRvbmVgCgo+Tm90ZTogVHlwZSB0aGUgY29tbWFuZCBgZXhpdGAgdG8gZXhpdCBmcm9tIGEgcnVubmluZyBpbnRlcmFjdGl2ZSBqb2IuIFRoaXMgd2lsbCBwdXQgeW91IGJhY2sgb250byB0aGUgbG9nIGluIG5vZGUgYW5kIGZyZWUgdXAgcmVtYWluaW5nIHJlc291cmNlcy4KCjwvZGV0YWlscz4KCjxicj4KCiMjIEV4ZXJjaXNlIGBzcnVuYCB3aXRoIExNT0QgLSBGaWx0ZXJpbmcgb3VyIEJBTSBGaWxlcwoKRm9sbG93aW5nIGFsb25nIHdpdGggdGhlIGluc3RydWN0b3IsIHdlJ2xsIGxhdW5jaCBhbiBpbnRlcmFjdGl2ZSBqb2Igd2l0aCBgc3J1bmAsIGxvYWQgdGhlIHNhbXRvb2xzIG1vZHVsZSwgYW5kIHVzZSBzYW10b29scyB0byBmaWx0ZXIgb3VyIHNhbXBsZV9BIEJBTSBmaWxlIHRvIHNlbGVjdCBvbmx5IGFsaWdubWVudHMgZnJvbSBjaHJvbW9zb21lIDE5LgoKPGRldGFpbHM+CjxzdW1tYXJ5PmBzcnVuYCB3aXRoIExNT0QgRmlsdGVyaW5nIEJBTSAtIFNvbHV0aW9uPC9zdW1tYXJ5PgoKYHNydW4gLS1wdHkgLS1qb2ItbmFtZT0ke1VTRVJ9X2ZpbHRlcl9zYW1wbGVfQSAtLWFjY291bnQ9YmlvaW5mX3drc2hwX2NsYXNzIC0tcGFydGl0aW9uIHN0YW5kYXJkIC0tbWVtPTIwMDAgLS1jcHVzLXBlci10YXNrPTIgLS10aW1lPTAwOjMwOjAwIC9iaW4vYmFzaGAKCmBtb2R1bGUgbG9hZCBCaW9pbmZvcm1hdGljczsgbW9kdWxlIGxvYWQgc2FtdG9vbHNgCgpgbWtkaXIgZmlsdGVyX2xtb2RgCgpgc2FtdG9vbHMgdmlldyAtbyBmaWx0ZXJfbG1vZC9zYW1wbGVfQS5jaHIxOS5iYW0gaW5wdXRfYmFtcy9zYW1wbGVfQS5nZW5vbWUuYmFtIDE5YAoKPk5vdGU6IFdlIHJlLWNyZWF0ZSB0aGlzIHNhbWUgZmlsdGVyZWQgQkFNIGZpbGUgaW4gdGhlIGFkZGl0aW9uYWwgU0JBVENIIGV4ZXJjaXNlcyBiZWxvdwoKPC9kZXRhaWxzPgoKPGJyPgoKIyMgRXhlcmNpc2UgU0JBVENIIHdpdGggTE1PRCAtIEZpbHRlcmluZyBvdXIgQkFNIEZpbGVzIENvbnQnZAoKRm9sbG93aW5nIGFsb25nIHdpdGggdGhlIGluc3RydWN0b3IsIHdlJ2xsIGNyZWF0ZSBhbiBTQkFUQ0ggc2NyaXB0IHRoYXQgaXMgc2ltaWxhciB0byBvdXIgcHJldmlvdXMgYHNydW5gIGV4ZXJjaXNlLCBhbmQgdXNlIHRoYXQgdG8gZmlsdGVyIG91ciBzYW1wbGVfQiBCQU0gZmlsZSBpbiB0aGUgc2FtZSBmYXNoaW9uLiBXZSB3aWxsIGxhdW5jaCBpdCB3aXRoIGBzYmF0Y2hgIGFuZCBpbnNwZWN0IHRoZSByZXN1bHRzLiBJZiBpdCBpcyBzdWNjZXNzZnVsLCB3ZSB3aWxsIGNvbnRpbnVlIHRoaXMgZXhlcmNpc2UgYnkgY3JlYXRpbmcgYW5kIHJ1bm5pbmcgdHdvIG1vcmUgU0JBVENIIHNjcmlwdHMgZm9yIHNhbXBsZV9DIGFuZCBzYW1wbGVfRC4KCjxkZXRhaWxzPgo8c3VtbWFyeT5TQkFUQ0ggd2l0aCBMTU9EIEZpbHRlcmluZyBCQU1zIENvbnQnZCAtIFNvbHV0aW9uPC9zdW1tYXJ5PgoKYGNwIC4uL2ludHJvX3NjcmlwdHMvaGVsbG9fU0JBVENILnNoIHNjcmlwdHMvZmlsdGVyX2xtb2Rfc2FtcGxlX0Ffc2JhdGNoLnNoYAoKYG5hbm8gc2NyaXB0cy9maWx0ZXJfbG1vZF9zYW1wbGVfQV9zYmF0Y2guc2ggIyBFZGl0IHRoZSBmaWxlIGFwcHJvcHJpYXRlbHlgCgpgc2JhdGNoIHNjcmlwdHMvZmlsdGVyX2xtb2Rfc2FtcGxlX0Ffc2JhdGNoLnNoYAoKV2hlbiB3ZSdyZSBoYXBweSB3aXRoIGhvdyBzYW1wbGVfQSB0dXJuZWQgb3V0LCB3ZSdsbCBjb3B5IG91ciBzYmF0Y2ggZmlsZSBhbmQgc2V0IGl0IHVwIGZvciBzYW1wbGVfQiBldGMuCgpgY3Agc2NyaXB0cy9maWx0ZXJfbG1vZF9zYW1wbGVfQV9zYmF0Y2guc2ggc2NyaXB0cy9maWx0ZXJfbG1vZF9zYW1wbGVfQl9zYmF0Y2guc2hgCgpgbmFubyBzY3JpcHRzL2ZpbHRlcl9sbW9kX3NhbXBsZV9CX3NiYXRjaC5zaGAKCmBzYmF0Y2ggc2NyaXB0cy9maWx0ZXJfbG1vZF9zYW1wbGVfQl9zYmF0Y2guc2hgCgo8YnI+CgpDb250ZW50cyBvZiBgZmlsdGVyX2xtb2Rfc2FtcGxlX0Ffc2JhdGNoLnNoYApgYGAKIyEvYmluL2Jhc2gKIyBUaGUgaW50ZXJwcmV0ZXIgdXNlZCB0byBleGVjdXRlIHRoZSBzY3JpcHQKCiPigJwjU0JBVENI4oCdIGRpcmVjdGl2ZXMgdGhhdCBjb252ZXkgc3VibWlzc2lvbiBvcHRpb25zOgoKI1NCQVRDSCAtLWpvYi1uYW1lPUZpbHRlcl9zYW1wbGVfQQojU0JBVENIIC0tY3B1cy1wZXItdGFzaz0yCiNTQkFUQ0ggLS1ub2Rlcz0xCiNTQkFUQ0ggLS1udGFza3MtcGVyLW5vZGU9MQojU0JBVENIIC0tbWVtLXBlci1jcHU9MjAwMG0KI1NCQVRDSCAtLXRpbWU9MDA6MjA6MDAKI1NCQVRDSCAtLWFjY291bnQ9YmlvaW5mX3drc2hwX2NsYXNzCiNTQkFUQ0ggLS1wYXJ0aXRpb249c3RhbmRhcmQKI1NCQVRDSCAtLW91dHB1dD0vbmZzL3R1cmJvL3VtbXMtYmlvaW5mLXdrc2hwL3dvcmtzaG9wL2hvbWUvJXUvcHJvamVjdF9hbmFseXNpcy9sb2dzLyV4LSVqLmxvZwoKIyBUaGUgYXBwbGljYXRpb24ocykgdG8gZXhlY3V0ZSBhbG9uZyB3aXRoIGl0cyBpbnB1dCBhcmd1bWVudHMgYW5kIG9wdGlvbnM6Cgpob3N0bmFtZQpwd2QKCm1vZHVsZSBsb2FkIEJpb2luZm9ybWF0aWNzCm1vZHVsZSBsb2FkIHNhbXRvb2xzCnNhbXRvb2xzIHZpZXcgLW8gZmlsdGVyX2xtb2Qvc2FtcGxlX0EuY2hyMTkuYmFtIGlucHV0X2JhbXMvc2FtcGxlX0EuZ2Vub21lLmJhbSAxOQpgYGAKCjwvZGV0YWlscz4KCjxicj4KCjwhLS0gTElWRV9OT1RFOiBXZSB3b3VsZCBsaWtlIHRvIGFsc28gdmlzdWFsaXplIG91ciBzYW1wbGVzLCB3ZSBrbm93IHRoYXQgd2UgY2FuIHVzZSBgYmFtQ292ZXJhZ2VgIGZyb20gdGhlIGBkZWVwdG9vbHMgcGFja2FnZSwgaG93ZXZlciBpdCdzIG5vdCBhdmFpbGFibGUgYXMgYW4gTE1PRCBtb2R1bGUuIC0tPgoKPCEtLSBMSVZFX05PVEU6IE1ha2Ugc3VyZSB3ZSB1bmxvYWQgc2FtdG9vbHMgbW9kdWxlISAtLT4KCj5Ob3RlOiBNYWtlIHN1cmUgdG8gdW5sb2FkIHRoZSBzYW10b29scyBtb2R1bGUsIHNvIHRoYXQgaXQgZG9lcyBub3QgaW50ZXJmZXJlIHdpdGggdGhlIGNvbmRhIGV4ZXJjaXNlcyBpbiB0aGUgbmV4dCBzZWN0aW9uIQoKLS0tCgoKfCBbUHJldmlvdXMgbGVzc29uXShNb2R1bGUwM2Ffc25lYWtfcGVla19ncmVhdF9sYWtlcy5odG1sKSB8IFtUb3Agb2YgdGhpcyBsZXNzb25dKCN0b3ApIHwgW05leHQgbGVzc29uXShNb2R1bGUwNF9zb2Z0d2FyZV9tYW5hZ2VtZW50X2NvbmRhLmh0bWwpIHwKfCA6LS0tIHwgOi0tLS06IHwgLS0tOiB8Cg==