(Adapted from the Data Carpentry Genomics wrangling materials at:- https://datacarpentry.org/wrangling-genomics/02-quality-control/index.html)

Overview

Covered in this section

  • Using the command line to download files
  • Compression and de-compression of files
  • Verifying that a download was completed
  • Quality assessment of raw sequencing data
  • Compiling multiple QC reports into a single file

Bioinformatics workflows

When working with high-throughput sequencing data, the raw reads you get off of the sequencer will need to pass through a number of different tools in order to generate your final desired output. The execution of this set of tools in a specified order is commonly referred to as a workflow or a pipeline.

An example of the workflow we will be using for our RNA-seq analysis is provided below with a brief description of each step.

workflow

  1. Quality control - Assessing quality using FastQC
  2. Align reads to reference genome
  3. Quantification to obtain gene-level counts post-alignment clean-up
  4. Differential Expression

These workflows in bioinformatics adopt a plug-and-play approach in that the output of one tool can be easily used as input to another tool without any extensive configuration. Having standards for data formats is what makes this feasible. Standards ensure that data is stored in a way that is generally accepted and agreed upon within the community. The tools that are used to analyze data at different stages of the workflow are therefore built under the assumption that the data will be provided in a specific format.

Although we are using RNA-seq as a case study, the initial steps for other NGS technologies are highly-similar

Obtaining raw reads

Before we can begin the analysis, we need to make our raw sequencing data accessible within the same computing environment that we are going to use for analysis. Assuming that you will be using a computing node without a GUI, this can be a non-trivial task. For example, we cannot easily drag-and-drop the files from one location to another or click a download link. Therefore we will introduce some commands for transfering files, compressing and de-compressing and checking file integrity.

Lets create a temporary directory to test these tools:-

cd
mkdir tmp
cd tmp

Use wget to download from a remote location

If your data are hosted on a website or FTP site, you can use the wget command to download to the current working directory. A small fastq file is provided on the Sheffield Bioinformatics Core website as an example. The output updates you on the progress of the download.

Note that if downloading from an FTP site you might be prompted for a username and password.

wget http://sbc.shef.ac.uk/data/example_reads.fastq
ls -lh

The contents of the file can be printed to the screen using the head command you should have learnt about previously

head -n 4 example_reads.fastq

Since this file is so small, we needn’t worry about the file size. However, in a real life experiment our raw sequencing reads can be many 10s of Gb in size. It is common practice to compress the file so that it takes less space on disk. The standard way of achieving this in Unix systems is to use the gzip command. A side-effect of the compression is that the resulting file can no longer be printed with cat. However, a zcat command can be used to the same effect.

##example of compressing the file
gzip example_reads.fastq
## list the directory to see what changed...
ls -lh
## Now have to use zcat to print...
zcat example_reads.fastq | head -n4

Download an archived directory

Another popular technique for compressing and transfering a collection of files is to organise them into a single file (or tarball), which can then be compressed. Such a file is also available on the Sheffield Bioinformatics Core website for demonstration purposes. The wget command can be used as before.

wget http://sbc.shef.ac.uk/data/archive.tar.gz
ls

The tar command with the options zxvf (look these up if you want to understand more) can be used to create a directory structure containing all the files.

tar zxvf archive.tar.gz
ls

Checking the download worked

Having downloaded all your files, you should probably check they have been downloaded successfully and been corrupted in transit. Partial or incomplete files can be a source of errors later on in the analysis. If you are downloading many files, it can be difficult to spot if a file failed to download. A simple way is to check the file sizes, but this can be unreliable.

A common way of doing this is to generate an md5sum from the file. You can think of this as a unique digital barcode of a text file. The same file will always give the same md5sum. Sequencing vendors will often calculate these files on their servers and send the results to you in the form of a text file that you can use to check. Note that for large fastq files, these can take several minutes to compute.

### show md5sum for a particular file
md5sum fastq/Sample1/Sample1.fastq
## help is available on the function
md5sum --help

Challenge 1

  1. Download the pre-computed md5sums available at http://sbc.shef.ac.uk/data/archive_md5.txt.
  2. Print the contents of this file and verify that the sum for Sample1.fastq is correct
  3. The md5sum command is able to check the md5sums for a collection of files against some pre-computed values. Use documentation (and google!) to discover how to do this for the files we have downloaded.

Digression - Obtaining public data

A good resource for obtaining public data is the SRA explorer.

In the Search box you can enter the accession number of a study (usually quoted in the published paper), to obtain download links for all the fastq files. It will even generate a bash script for you to run.

Using sharc (UoS-specific)

The University of Sheffield has a High-performance Computing (HPC) cluster called ShARC that you will probably use to perform your analysis.

FTP software such as Cyberduck (Mac OSX), WinSCP (Windows) or Filezilla will allow you to connect and copy the files in a drag-and-drop manner.

You can also copy files to this cluster from your own machine with the secure copy (scp) command or rsnyc.

scp archive.tar.gz md1mjdx@sharc.shef.ac.uk:/shared/bioinformatics_core1/Shared/work

Your research group may already have storage space on ShARC that is accesible from your desktop, in which case you can drag and drop files. See the UoS website for more information on this storage https://www.sheffield.ac.uk/cics/research-storage

Assessing Quality using FastQC

In real life, you won’t be assessing the quality of your reads by visually inspecting your FASTQ files. Rather, you’ll be using a software program to assess read quality and filter out poor quality reads. We’ll first use a program called FastQC to visualize the quality of our reads. Later in our workflow, we’ll use another program to filter out poor quality reads.

FastQC has a number of features which can give you a quick impression of any problems your data may have, so you can take these issues into consideration before moving forward with your analyses. Rather than looking at quality scores for each individual read, FastQC looks at quality collectively across all reads within a sample. The image below shows a FastQC-generated plot that indicates a very high quality sample:

good_quality

The x-axis displays the base position in the read, and the y-axis shows quality scores. In this example, the sample contains reads that are 40 bp long. For each position, there is a box-and-whisker plot showing the distribution of quality scores for all reads at that position. The horizontal red line indicates the median quality score and the yellow box shows the 2nd to 3rd quartile range. This means that 50% of reads have a quality score that falls within the range of the yellow box at that position. The whiskers show the range to the 1st and 4th quartile.

For each position in this sample, the quality values do not drop much lower than 32. This is a high quality score. The plot background is also color-coded to identify good (green), acceptable (yellow), and bad (red) quality scores.

Now let’s take a look at a quality plot on the other end of the spectrum.

bad_quality

Here, we see positions within the read in which the boxes span a much wider range. Also, quality scores drop quite low into the “bad” range, particularly on the tail end of the reads. The FastQC tool produces several other diagnostic plots to assess sample quality, in addition to the one plotted above.

Running FastQC

We will be working with a set of sample data that is located in the directory (rnaseq_data). These files have been compressed, so have the fastq.gz extension. FastQC is happy with either compressed on un-compressed files.

Navigate to your FASTQ dataset:

cd ~/rnaseq_data/

To run the FastQC program, we would normally have to tell our computer where the program is located. In this particular case, FastQC has been installed in a location that can be accessed from all directories.

which fastqc
/usr/bin/fastqc

This is the first program we have seen that is specific to NGS analysis, so might not be available on all file systems by default.

FastQC can accept multiple file names as input, so we can use the *.fastq.gz wildcard to run FastQC on all of the FASTQ files in this directory.

fastqc *.fastq.gz

You will see an automatically updating output message telling you the progress of the analysis. It will start like this:

Started analysis of SRR1552444.fastq.gz
Approx 100% complete for SRR1552444.fastq.gz
Analysis complete for SRR1552444.fastq.gz

In total, it should take less than 1 minute for FastQC to run on all of our FASTQ files. When the analysis completes, your prompt will return. So your screen will look something like this:

Started analysis of SRR1552455.fastq.gz
Approx 100% complete for SRR1552455.fastq.gz
Analysis complete for SRR1552455.fastq.gz

The FastQC program has created several new files within our ~/rnaseq_data/ directory.

ls
SRR1552444.fastq.gz     SRR1552446.fastq.gz     SRR1552448.fastq.gz     SRR1552450.fastq.gz     SRR1552452.fastq.gz     SRR1552454.fastq.gz
SRR1552444_fastqc.html  SRR1552446_fastqc.html  SRR1552448_fastqc.html  SRR1552450_fastqc.html  SRR1552452_fastqc.html  SRR1552454_fastqc.html
SRR1552444_fastqc.zip   SRR1552446_fastqc.zip   SRR1552448_fastqc.zip   SRR1552450_fastqc.zip   SRR1552452_fastqc.zip   SRR1552454_fastqc.zip
SRR1552445.fastq.gz     SRR1552447.fastq.gz     SRR1552449.fastq.gz     SRR1552451.fastq.gz     SRR1552453.fastq.gz     SRR1552455.fastq.gz
SRR1552445_fastqc.html  SRR1552447_fastqc.html  SRR1552449_fastqc.html  SRR1552451_fastqc.html  SRR1552453_fastqc.html  SRR1552455_fastqc.html
SRR1552445_fastqc.zip   SRR1552447_fastqc.zip   SRR1552449_fastqc.zip   SRR1552451_fastqc.zip   SRR1552453_fastqc.zip   SRR1552455_fastqc.zip

For each input FASTQ file, FastQC has created a .zip file and a .html file. The .zip file extension indicates that this is actually a compressed set of multiple output files. We’ll be working with these output files soon. The .html file is a stable webpage displaying the summary report for each of our samples.

We want to keep our data files and our results files separate, so we will move these output files into a new directory within our results/ directory. If this directory does not exist, we will have to create it.

## -p flag stops a message from appearing if the directory already exists
mkdir -p results
mv *.html results/
mv *.zip results/

Combining the reports with multiqc

It can be quite tiresome to click through multiple QC reports and compare the results for different samples. It is useful to have all the QC plots on the same page so that we can more easily spot trends in the data.

The multiqc tool has been designed for the tasks of aggregating qc reports and combining into a single report that is easy to digest.

multiqc
multiqc --help

Challenge 2

Use the multiqc tool to create a single QC report for the dataset. Look at the help for the tool, and figure out how to run the tool on the fastqc output we have just generated. Make sure that multiqc creates saves the report file in the results folder.

The environment that we are working inside includes a version of the Firefox web browser. We can open a particular HTML file with firefox using the command:-

firefox results/SRR1552444_fastqc.html 

If this doesn’t work, there is a File Explorer tool available in the desktop environment that you can use to navigate to, and view the files.

Challenge 3

Discuss your results with a neighbour. Which sample(s) looks the best in terms of per base sequence quality? Which sample(s) look the worst?

LS0tCnRpdGxlOiAiQXNzZXNzaW5nIFJlYWQgUXVhbGl0eSIKYXV0aG9yOiAiTWFyayBEdW5uaW5nIgpkYXRlOiAnYHIgZm9ybWF0KFN5cy50aW1lKCksICJMYXN0IG1vZGlmaWVkOiAlZCAlYiAlWSIpYCcKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIGNzczogc3R5bGVzaGVldHMvc3R5bGVzLmNzcwotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCmBgYAoKKEFkYXB0ZWQgZnJvbSB0aGUgRGF0YSBDYXJwZW50cnkgR2Vub21pY3Mgd3JhbmdsaW5nIG1hdGVyaWFscyBhdDotIGh0dHBzOi8vZGF0YWNhcnBlbnRyeS5vcmcvd3JhbmdsaW5nLWdlbm9taWNzLzAyLXF1YWxpdHktY29udHJvbC9pbmRleC5odG1sKQoKIyBPdmVydmlldwoKQ292ZXJlZCBpbiB0aGlzIHNlY3Rpb24KCi0gVXNpbmcgdGhlIGNvbW1hbmQgbGluZSB0byBkb3dubG9hZCBmaWxlcwotIENvbXByZXNzaW9uIGFuZCBkZS1jb21wcmVzc2lvbiBvZiBmaWxlcwotIFZlcmlmeWluZyB0aGF0IGEgZG93bmxvYWQgd2FzIGNvbXBsZXRlZAotIFF1YWxpdHkgYXNzZXNzbWVudCBvZiByYXcgc2VxdWVuY2luZyBkYXRhCi0gQ29tcGlsaW5nIG11bHRpcGxlIFFDIHJlcG9ydHMgaW50byBhIHNpbmdsZSBmaWxlCgoKIyBCaW9pbmZvcm1hdGljcyB3b3JrZmxvd3MKCldoZW4gd29ya2luZyB3aXRoIGhpZ2gtdGhyb3VnaHB1dCBzZXF1ZW5jaW5nIGRhdGEsIHRoZSByYXcgcmVhZHMgeW91IGdldCBvZmYgb2YgdGhlIHNlcXVlbmNlciB3aWxsIG5lZWQgdG8gcGFzcwp0aHJvdWdoIGEgbnVtYmVyIG9mICBkaWZmZXJlbnQgdG9vbHMgaW4gb3JkZXIgdG8gZ2VuZXJhdGUgeW91ciBmaW5hbCBkZXNpcmVkIG91dHB1dC4gVGhlIGV4ZWN1dGlvbiBvZiB0aGlzIHNldCBvZgp0b29scyBpbiBhIHNwZWNpZmllZCBvcmRlciBpcyBjb21tb25seSByZWZlcnJlZCB0byBhcyBhICp3b3JrZmxvdyogb3IgYSAqcGlwZWxpbmUqLiAKCkFuIGV4YW1wbGUgb2YgdGhlIHdvcmtmbG93IHdlIHdpbGwgYmUgdXNpbmcgZm9yIG91ciBSTkEtc2VxIGFuYWx5c2lzIGlzIHByb3ZpZGVkIGJlbG93IHdpdGggYSBicmllZgpkZXNjcmlwdGlvbiBvZiBlYWNoIHN0ZXAuIAoKIVt3b3JrZmxvd10oaW1hZ2VzL3dvcmtmbG93LnBuZykKCgoxLiBRdWFsaXR5IGNvbnRyb2wgLSBBc3Nlc3NpbmcgcXVhbGl0eSB1c2luZyBGYXN0UUMKMi4gQWxpZ24gcmVhZHMgdG8gcmVmZXJlbmNlIGdlbm9tZSAKMy4gUXVhbnRpZmljYXRpb24gdG8gb2J0YWluIGdlbmUtbGV2ZWwgY291bnRzIHBvc3QtYWxpZ25tZW50IGNsZWFuLXVwCjQuIERpZmZlcmVudGlhbCBFeHByZXNzaW9uCgpUaGVzZSB3b3JrZmxvd3MgaW4gYmlvaW5mb3JtYXRpY3MgYWRvcHQgYSBwbHVnLWFuZC1wbGF5IGFwcHJvYWNoIGluIHRoYXQgdGhlIG91dHB1dCBvZiBvbmUgdG9vbCBjYW4gYmUgZWFzaWx5CnVzZWQgYXMgaW5wdXQgdG8gYW5vdGhlciB0b29sIHdpdGhvdXQgYW55IGV4dGVuc2l2ZSBjb25maWd1cmF0aW9uLiBIYXZpbmcgc3RhbmRhcmRzIGZvciBkYXRhIGZvcm1hdHMgaXMgd2hhdCAKbWFrZXMgdGhpcyBmZWFzaWJsZS4gU3RhbmRhcmRzIGVuc3VyZSB0aGF0IGRhdGEgaXMgc3RvcmVkIGluIGEgd2F5IHRoYXQgaXMgZ2VuZXJhbGx5IGFjY2VwdGVkIGFuZCBhZ3JlZWQgdXBvbiAKd2l0aGluIHRoZSBjb21tdW5pdHkuIFRoZSB0b29scyB0aGF0IGFyZSB1c2VkIHRvIGFuYWx5emUgZGF0YSBhdCBkaWZmZXJlbnQgc3RhZ2VzIG9mIHRoZSB3b3JrZmxvdyBhcmUgdGhlcmVmb3JlIApidWlsdCB1bmRlciB0aGUgYXNzdW1wdGlvbiB0aGF0IHRoZSBkYXRhIHdpbGwgYmUgcHJvdmlkZWQgaW4gYSBzcGVjaWZpYyBmb3JtYXQuICAKCioqQWx0aG91Z2ggd2UgYXJlIHVzaW5nIFJOQS1zZXEgYXMgYSBjYXNlIHN0dWR5LCB0aGUgaW5pdGlhbCBzdGVwcyBmb3Igb3RoZXIgTkdTIHRlY2hub2xvZ2llcyBhcmUgaGlnaGx5LXNpbWlsYXIqKgoKIyBPYnRhaW5pbmcgcmF3IHJlYWRzCgpCZWZvcmUgd2UgY2FuIGJlZ2luIHRoZSBhbmFseXNpcywgd2UgbmVlZCB0byBtYWtlIG91ciByYXcgc2VxdWVuY2luZyBkYXRhIGFjY2Vzc2libGUgd2l0aGluIHRoZSBzYW1lIGNvbXB1dGluZyBlbnZpcm9ubWVudCB0aGF0IHdlIGFyZSBnb2luZyB0byB1c2UgZm9yIGFuYWx5c2lzLiBBc3N1bWluZyB0aGF0IHlvdSB3aWxsIGJlIHVzaW5nIGEgY29tcHV0aW5nIG5vZGUgd2l0aG91dCBhIEdVSSwgdGhpcyBjYW4gYmUgYSBub24tdHJpdmlhbCB0YXNrLiBGb3IgZXhhbXBsZSwgd2UgY2Fubm90IGVhc2lseSBkcmFnLWFuZC1kcm9wIHRoZSBmaWxlcyBmcm9tIG9uZSBsb2NhdGlvbiB0byBhbm90aGVyIG9yIGNsaWNrIGEgZG93bmxvYWQgbGluay4gVGhlcmVmb3JlIHdlIHdpbGwgaW50cm9kdWNlIHNvbWUgY29tbWFuZHMgZm9yIHRyYW5zZmVyaW5nIGZpbGVzLCBjb21wcmVzc2luZyBhbmQgZGUtY29tcHJlc3NpbmcgYW5kIGNoZWNraW5nIGZpbGUgaW50ZWdyaXR5LgoKTGV0cyBjcmVhdGUgYSB0ZW1wb3JhcnkgZGlyZWN0b3J5IHRvIHRlc3QgdGhlc2UgdG9vbHM6LQoKYGBge2Jhc2ggZXZhbD1GQUxTRX0KY2QKbWtkaXIgdG1wCmNkIHRtcApgYGAKCgojIyBVc2UgYHdnZXRgIHRvIGRvd25sb2FkIGZyb20gYSByZW1vdGUgbG9jYXRpb24KCklmIHlvdXIgZGF0YSBhcmUgaG9zdGVkIG9uIGEgd2Vic2l0ZSBvciBGVFAgc2l0ZSwgeW91IGNhbiB1c2UgdGhlIGB3Z2V0YCBjb21tYW5kIHRvIGRvd25sb2FkIHRvIHRoZSBjdXJyZW50IHdvcmtpbmcgZGlyZWN0b3J5LiBBIHNtYWxsIGBmYXN0cWAgZmlsZSBpcyBwcm92aWRlZCBvbiB0aGUgU2hlZmZpZWxkIEJpb2luZm9ybWF0aWNzIENvcmUgd2Vic2l0ZSBhcyBhbiBleGFtcGxlLiBUaGUgb3V0cHV0IHVwZGF0ZXMgeW91IG9uIHRoZSBwcm9ncmVzcyBvZiB0aGUgZG93bmxvYWQuCgpOb3RlIHRoYXQgaWYgZG93bmxvYWRpbmcgZnJvbSBhbiBGVFAgc2l0ZSB5b3UgbWlnaHQgYmUgcHJvbXB0ZWQgZm9yIGEgdXNlcm5hbWUgYW5kIHBhc3N3b3JkLgoKYGBge2Jhc2ggZXZhbD1GQUxTRX0Kd2dldCBodHRwOi8vc2JjLnNoZWYuYWMudWsvZGF0YS9leGFtcGxlX3JlYWRzLmZhc3RxCmxzIC1saApgYGAKClRoZSBjb250ZW50cyBvZiB0aGUgZmlsZSBjYW4gYmUgcHJpbnRlZCB0byB0aGUgc2NyZWVuIHVzaW5nIHRoZSBgaGVhZGAgY29tbWFuZCB5b3Ugc2hvdWxkIGhhdmUgbGVhcm50IGFib3V0IHByZXZpb3VzbHkKCmBgYHtiYXNoIGV2YWw9RkFMU0V9CmhlYWQgLW4gNCBleGFtcGxlX3JlYWRzLmZhc3RxCmBgYAoKU2luY2UgdGhpcyBmaWxlIGlzIHNvIHNtYWxsLCB3ZSBuZWVkbid0IHdvcnJ5IGFib3V0IHRoZSBmaWxlIHNpemUuIEhvd2V2ZXIsIGluIGEgcmVhbCBsaWZlIGV4cGVyaW1lbnQgb3VyIHJhdyBzZXF1ZW5jaW5nIHJlYWRzIGNhbiBiZSBtYW55IDEwcyBvZiBHYiBpbiBzaXplLiBJdCBpcyBjb21tb24gcHJhY3RpY2UgdG8gY29tcHJlc3MgdGhlIGZpbGUgc28gdGhhdCBpdCB0YWtlcyBsZXNzIHNwYWNlIG9uIGRpc2suIFRoZSBzdGFuZGFyZCB3YXkgb2YgYWNoaWV2aW5nIHRoaXMgaW4gVW5peCBzeXN0ZW1zIGlzIHRvIHVzZSB0aGUgYGd6aXBgIGNvbW1hbmQuIEEgc2lkZS1lZmZlY3Qgb2YgdGhlIGNvbXByZXNzaW9uIGlzIHRoYXQgdGhlIHJlc3VsdGluZyBmaWxlIGNhbiBubyBsb25nZXIgYmUgcHJpbnRlZCB3aXRoIGBjYXRgLiBIb3dldmVyLCBhIGB6Y2F0YCBjb21tYW5kIGNhbiBiZSB1c2VkIHRvIHRoZSBzYW1lIGVmZmVjdC4KCmBgYHtiYXNoIGV2YWw9RkFMU0V9CiMjZXhhbXBsZSBvZiBjb21wcmVzc2luZyB0aGUgZmlsZQpnemlwIGV4YW1wbGVfcmVhZHMuZmFzdHEKIyMgbGlzdCB0aGUgZGlyZWN0b3J5IHRvIHNlZSB3aGF0IGNoYW5nZWQuLi4KbHMgLWxoCiMjIE5vdyBoYXZlIHRvIHVzZSB6Y2F0IHRvIHByaW50Li4uCnpjYXQgZXhhbXBsZV9yZWFkcy5mYXN0cSB8IGhlYWQgLW40CmBgYAoKCiMjIERvd25sb2FkIGFuIGFyY2hpdmVkIGRpcmVjdG9yeQoKQW5vdGhlciBwb3B1bGFyIHRlY2huaXF1ZSBmb3IgY29tcHJlc3NpbmcgYW5kIHRyYW5zZmVyaW5nIGEgY29sbGVjdGlvbiBvZiBmaWxlcyBpcyB0byBvcmdhbmlzZSB0aGVtIGludG8gYSBzaW5nbGUgZmlsZSAob3IgKnRhcmJhbGwqKSwgd2hpY2ggY2FuIHRoZW4gYmUgY29tcHJlc3NlZC4gU3VjaCBhIGZpbGUgaXMgYWxzbyBhdmFpbGFibGUgb24gdGhlIFNoZWZmaWVsZCBCaW9pbmZvcm1hdGljcyBDb3JlIHdlYnNpdGUgZm9yIGRlbW9uc3RyYXRpb24gcHVycG9zZXMuIFRoZSBgd2dldGAgY29tbWFuZCBjYW4gYmUgdXNlZCBhcyBiZWZvcmUuCgpgYGB7YmFzaCBldmFsPUZBTFNFfQp3Z2V0IGh0dHA6Ly9zYmMuc2hlZi5hYy51ay9kYXRhL2FyY2hpdmUudGFyLmd6CmxzCmBgYAoKVGhlIGB0YXJgIGNvbW1hbmQgd2l0aCB0aGUgb3B0aW9ucyBgenh2ZmAgKGxvb2sgdGhlc2UgdXAgaWYgeW91IHdhbnQgdG8gdW5kZXJzdGFuZCBtb3JlKSBjYW4gYmUgdXNlZCB0byBjcmVhdGUgYSBkaXJlY3Rvcnkgc3RydWN0dXJlIGNvbnRhaW5pbmcgYWxsIHRoZSBmaWxlcy4KCmBgYHtiYXNoIGV2YWw9RkFMU0V9CnRhciB6eHZmIGFyY2hpdmUudGFyLmd6CmxzCmBgYAoKCgojIyMgQ2hlY2tpbmcgdGhlIGRvd25sb2FkIHdvcmtlZAoKSGF2aW5nIGRvd25sb2FkZWQgYWxsIHlvdXIgZmlsZXMsIHlvdSBzaG91bGQgcHJvYmFibHkgY2hlY2sgdGhleSBoYXZlIGJlZW4gZG93bmxvYWRlZCBzdWNjZXNzZnVsbHkgYW5kIGJlZW4gY29ycnVwdGVkIGluIHRyYW5zaXQuIFBhcnRpYWwgb3IgaW5jb21wbGV0ZSBmaWxlcyBjYW4gYmUgYSBzb3VyY2Ugb2YgZXJyb3JzIGxhdGVyIG9uIGluIHRoZSBhbmFseXNpcy4gSWYgeW91IGFyZSBkb3dubG9hZGluZyBtYW55IGZpbGVzLCBpdCBjYW4gYmUgZGlmZmljdWx0IHRvIHNwb3QgaWYgYSBmaWxlIGZhaWxlZCB0byBkb3dubG9hZC4gQSBzaW1wbGUgd2F5IGlzIHRvIGNoZWNrIHRoZSBmaWxlIHNpemVzLCBidXQgdGhpcyBjYW4gYmUgdW5yZWxpYWJsZS4KCkEgY29tbW9uIHdheSBvZiBkb2luZyB0aGlzIGlzIHRvIGdlbmVyYXRlIGFuICptZDVzdW0qIGZyb20gdGhlIGZpbGUuIFlvdSBjYW4gdGhpbmsgb2YgdGhpcyBhcyBhIHVuaXF1ZSBkaWdpdGFsIGJhcmNvZGUgb2YgYSB0ZXh0IGZpbGUuIFRoZSBzYW1lIGZpbGUgd2lsbCBhbHdheXMgZ2l2ZSB0aGUgc2FtZSBtZDVzdW0uIFNlcXVlbmNpbmcgdmVuZG9ycyB3aWxsIG9mdGVuIGNhbGN1bGF0ZSB0aGVzZSBmaWxlcyBvbiB0aGVpciBzZXJ2ZXJzIGFuZCBzZW5kIHRoZSByZXN1bHRzIHRvIHlvdSBpbiB0aGUgZm9ybSBvZiBhIHRleHQgZmlsZSB0aGF0IHlvdSBjYW4gdXNlIHRvIGNoZWNrLiBOb3RlIHRoYXQgZm9yIGxhcmdlIGZhc3RxIGZpbGVzLCB0aGVzZSBjYW4gdGFrZSBzZXZlcmFsIG1pbnV0ZXMgdG8gY29tcHV0ZS4KCmBgYHtiYXNoIGV2YWw9RkFMU0V9CiMjIyBzaG93IG1kNXN1bSBmb3IgYSBwYXJ0aWN1bGFyIGZpbGUKbWQ1c3VtIGZhc3RxL1NhbXBsZTEvU2FtcGxlMS5mYXN0cQojIyBoZWxwIGlzIGF2YWlsYWJsZSBvbiB0aGUgZnVuY3Rpb24KbWQ1c3VtIC0taGVscApgYGAKCj4gIyMgQ2hhbGxlbmdlIDEgey5jaGFsbGVuZ2V9Cj4KPiAxLiBEb3dubG9hZCB0aGUgcHJlLWNvbXB1dGVkIG1kNXN1bXMgYXZhaWxhYmxlIGF0IGBodHRwOi8vc2JjLnNoZWYuYWMudWsvZGF0YS9hcmNoaXZlX21kNS50eHRgLiAKPiAyLiBQcmludCB0aGUgY29udGVudHMgb2YgdGhpcyBmaWxlIGFuZCB2ZXJpZnkgdGhhdCB0aGUgc3VtIGZvciBTYW1wbGUxLmZhc3RxIGlzIGNvcnJlY3QKPiAzLiBUaGUgbWQ1c3VtIGNvbW1hbmQgaXMgYWJsZSB0byBjaGVjayB0aGUgbWQ1c3VtcyBmb3IgYSBjb2xsZWN0aW9uIG9mIGZpbGVzIGFnYWluc3Qgc29tZSBwcmUtY29tcHV0ZWQgdmFsdWVzLiBVc2UgZG9jdW1lbnRhdGlvbiAoYW5kIGdvb2dsZSEpIHRvIGRpc2NvdmVyIGhvdyB0byBkbyB0aGlzIGZvciB0aGUgZmlsZXMgd2UgaGF2ZSBkb3dubG9hZGVkLgoKIyMjIERpZ3Jlc3Npb24gIC0gT2J0YWluaW5nIHB1YmxpYyBkYXRhCgpBIGdvb2QgcmVzb3VyY2UgZm9yIG9idGFpbmluZyBwdWJsaWMgZGF0YSBpcyB0aGUgU1JBIGV4cGxvcmVyLgoKLSBbaHR0cHM6Ly9zcmEtZXhwbG9yZXIuaW5mby9dKGh0dHBzOi8vc3JhLWV4cGxvcmVyLmluZm8vKQoKSW4gdGhlIFNlYXJjaCBib3ggeW91IGNhbiBlbnRlciB0aGUgYWNjZXNzaW9uIG51bWJlciBvZiBhIHN0dWR5ICh1c3VhbGx5IHF1b3RlZCBpbiB0aGUgcHVibGlzaGVkIHBhcGVyKSwgdG8gb2J0YWluIGRvd25sb2FkIGxpbmtzIGZvciBhbGwgdGhlIGZhc3RxIGZpbGVzLiBJdCB3aWxsIGV2ZW4gZ2VuZXJhdGUgYSBiYXNoIHNjcmlwdCBmb3IgeW91IHRvIHJ1bi4KCiMjIyBVc2luZyBzaGFyYyAoKipVb1Mtc3BlY2lmaWMqKikKClRoZSBVbml2ZXJzaXR5IG9mIFNoZWZmaWVsZCBoYXMgYSBIaWdoLXBlcmZvcm1hbmNlIENvbXB1dGluZyAoSFBDKSBjbHVzdGVyIGNhbGxlZCBbU2hBUkNdKGh0dHBzOi8vd3d3LnNoZWZmaWVsZC5hYy51ay9jaWNzL3Jlc2VhcmNoL2hwYy9zaGFyYykgdGhhdCB5b3Ugd2lsbCBwcm9iYWJseSB1c2UgdG8gcGVyZm9ybSB5b3VyIGFuYWx5c2lzLiAKCkZUUCBzb2Z0d2FyZSBzdWNoIGFzIEN5YmVyZHVjayAoTWFjIE9TWCksIFdpblNDUCAoV2luZG93cykgb3IgRmlsZXppbGxhIHdpbGwgYWxsb3cgeW91IHRvIGNvbm5lY3QgYW5kIGNvcHkgdGhlIGZpbGVzIGluIGEgZHJhZy1hbmQtZHJvcCBtYW5uZXIuCgoKWW91IGNhbiBhbHNvIGNvcHkgZmlsZXMgdG8gdGhpcyBjbHVzdGVyIGZyb20geW91ciBvd24gbWFjaGluZSB3aXRoIHRoZSBzZWN1cmUgY29weSAoYHNjcGApIGNvbW1hbmQgb3IgYHJzbnljYC4KCmBgYHtiYXNoIGV2YWw9RkFMU0V9CnNjcCBhcmNoaXZlLnRhci5neiBtZDFtamR4QHNoYXJjLnNoZWYuYWMudWs6L3NoYXJlZC9iaW9pbmZvcm1hdGljc19jb3JlMS9TaGFyZWQvd29yawpgYGAKCllvdXIgcmVzZWFyY2ggZ3JvdXAgbWF5IGFscmVhZHkgaGF2ZSBzdG9yYWdlIHNwYWNlIG9uIFNoQVJDIHRoYXQgaXMgYWNjZXNpYmxlIGZyb20geW91ciBkZXNrdG9wLCBpbiB3aGljaCBjYXNlIHlvdSBjYW4gZHJhZyBhbmQgZHJvcCBmaWxlcy4gU2VlIHRoZSBVb1Mgd2Vic2l0ZSBmb3IgbW9yZSBpbmZvcm1hdGlvbiBvbiB0aGlzIHN0b3JhZ2UgW2h0dHBzOi8vd3d3LnNoZWZmaWVsZC5hYy51ay9jaWNzL3Jlc2VhcmNoLXN0b3JhZ2VdKGh0dHBzOi8vd3d3LnNoZWZmaWVsZC5hYy51ay9jaWNzL3Jlc2VhcmNoLXN0b3JhZ2UpCgoKIyBBc3Nlc3NpbmcgUXVhbGl0eSB1c2luZyBGYXN0UUMKCkluIHJlYWwgbGlmZSwgeW91IHdvbid0IGJlIGFzc2Vzc2luZyB0aGUgcXVhbGl0eSBvZiB5b3VyIHJlYWRzIGJ5IHZpc3VhbGx5IGluc3BlY3RpbmcgeW91ciAKRkFTVFEgZmlsZXMuIFJhdGhlciwgeW91J2xsIGJlIHVzaW5nIGEgc29mdHdhcmUgcHJvZ3JhbSB0byBhc3Nlc3MgcmVhZCBxdWFsaXR5IGFuZCAKZmlsdGVyIG91dCBwb29yIHF1YWxpdHkgcmVhZHMuIFdlJ2xsIGZpcnN0IHVzZSBhIHByb2dyYW0gY2FsbGVkIFtGYXN0UUNdKGh0dHA6Ly93d3cuYmlvaW5mb3JtYXRpY3MuYmFicmFoYW0uYWMudWsvcHJvamVjdHMvZmFzdHFjLykgdG8gdmlzdWFsaXplIHRoZSBxdWFsaXR5IG9mIG91ciByZWFkcy4gCkxhdGVyIGluIG91ciB3b3JrZmxvdywgd2UnbGwgdXNlIGFub3RoZXIgcHJvZ3JhbSB0byBmaWx0ZXIgb3V0IHBvb3IgcXVhbGl0eSByZWFkcy4gCgpGYXN0UUMgaGFzIGEgbnVtYmVyIG9mIGZlYXR1cmVzIHdoaWNoIGNhbiBnaXZlIHlvdSBhICBxdWljayBpbXByZXNzaW9uIG9mIGFueSBwcm9ibGVtcyB5b3VyCmRhdGEgbWF5IGhhdmUsIHNvIHlvdSBjYW4gdGFrZSB0aGVzZSBpc3N1ZXMgaW50byBjb25zaWRlcmF0aW9uIGJlZm9yZSBtb3ZpbmcgZm9yd2FyZCB3aXRoIHlvdXIKYW5hbHlzZXMuIFJhdGhlciB0aGFuIGxvb2tpbmcgYXQgcXVhbGl0eSBzY29yZXMgZm9yIGVhY2ggaW5kaXZpZHVhbCByZWFkLCBGYXN0UUMgbG9va3MgYXQKcXVhbGl0eSBjb2xsZWN0aXZlbHkgYWNyb3NzIGFsbCByZWFkcyB3aXRoaW4gYSBzYW1wbGUuIFRoZSBpbWFnZSBiZWxvdyBzaG93cyBhIEZhc3RRQy1nZW5lcmF0ZWQgcGxvdCB0aGF0IGluZGljYXRlcwphIHZlcnkgaGlnaCBxdWFsaXR5IHNhbXBsZToKCiFbZ29vZF9xdWFsaXR5XShpbWFnZXMvZ29vZF9xdWFsaXR5MS44LnBuZykKClRoZSB4LWF4aXMgZGlzcGxheXMgdGhlIGJhc2UgcG9zaXRpb24gaW4gdGhlIHJlYWQsIGFuZCB0aGUgeS1heGlzIHNob3dzIHF1YWxpdHkgc2NvcmVzLiBJbiB0aGlzCmV4YW1wbGUsIHRoZSBzYW1wbGUgY29udGFpbnMgcmVhZHMgdGhhdCBhcmUgNDAgYnAgbG9uZy4gRm9yIGVhY2ggcG9zaXRpb24sIHRoZXJlIGlzIGEgCmJveC1hbmQtd2hpc2tlciBwbG90IHNob3dpbmcgdGhlIGRpc3RyaWJ1dGlvbiBvZiBxdWFsaXR5IHNjb3JlcyBmb3IgYWxsIHJlYWRzIGF0IHRoYXQgcG9zaXRpb24uClRoZSBob3Jpem9udGFsIHJlZCBsaW5lIGluZGljYXRlcyB0aGUgbWVkaWFuIHF1YWxpdHkgc2NvcmUgYW5kIHRoZSB5ZWxsb3cgYm94IHNob3dzIHRoZSAybmQgdG8KM3JkIHF1YXJ0aWxlIHJhbmdlLiBUaGlzIG1lYW5zIHRoYXQgNTAlIG9mIHJlYWRzIGhhdmUgYSBxdWFsaXR5IHNjb3JlIHRoYXQgZmFsbHMgd2l0aGluIHRoZQpyYW5nZSBvZiB0aGUgeWVsbG93IGJveCBhdCB0aGF0IHBvc2l0aW9uLiBUaGUgd2hpc2tlcnMgc2hvdyB0aGUgcmFuZ2UgdG8gdGhlIDFzdCBhbmQgNHRoIApxdWFydGlsZS4KCkZvciBlYWNoIHBvc2l0aW9uIGluIHRoaXMgc2FtcGxlLCB0aGUgcXVhbGl0eSB2YWx1ZXMgZG8gbm90IGRyb3AgbXVjaCBsb3dlciB0aGFuIDMyLiBUaGlzIAppcyBhIGhpZ2ggcXVhbGl0eSBzY29yZS4gVGhlIHBsb3QgYmFja2dyb3VuZCBpcyBhbHNvIGNvbG9yLWNvZGVkIHRvIGlkZW50aWZ5IGdvb2QgKGdyZWVuKSwKYWNjZXB0YWJsZSAoeWVsbG93KSwgYW5kIGJhZCAocmVkKSBxdWFsaXR5IHNjb3Jlcy4KCk5vdyBsZXQncyB0YWtlIGEgbG9vayBhdCBhIHF1YWxpdHkgcGxvdCBvbiB0aGUgb3RoZXIgZW5kIG9mIHRoZSBzcGVjdHJ1bS4gCgohW2JhZF9xdWFsaXR5XShpbWFnZXMvYmFkX3F1YWxpdHkxLjgucG5nKQoKSGVyZSwgd2Ugc2VlIHBvc2l0aW9ucyB3aXRoaW4gdGhlIHJlYWQgaW4gd2hpY2ggdGhlIGJveGVzIHNwYW4gYSBtdWNoIHdpZGVyIHJhbmdlLiBBbHNvLCBxdWFsaXR5IHNjb3JlcyBkcm9wIHF1aXRlIGxvdyBpbnRvIHRoZSAiYmFkIiByYW5nZSwgcGFydGljdWxhcmx5IG9uIHRoZSB0YWlsIGVuZCBvZiB0aGUgcmVhZHMuIFRoZSBGYXN0UUMgdG9vbCBwcm9kdWNlcyBzZXZlcmFsIG90aGVyIGRpYWdub3N0aWMgcGxvdHMgdG8gYXNzZXNzIHNhbXBsZSBxdWFsaXR5LCBpbiBhZGRpdGlvbiB0byB0aGUgb25lIHBsb3R0ZWQgYWJvdmUuIAoKIyMgUnVubmluZyBGYXN0UUMgIAoKV2Ugd2lsbCBiZSB3b3JraW5nIHdpdGggYSBzZXQgb2Ygc2FtcGxlIGRhdGEgdGhhdCBpcyBsb2NhdGVkIGluIHRoZSBkaXJlY3RvcnkgKGBybmFzZXFfZGF0YWApLiBUaGVzZSBmaWxlcyBoYXZlIGJlZW4gY29tcHJlc3NlZCwgc28gaGF2ZSB0aGUgYGZhc3RxLmd6YCBleHRlbnNpb24uIEZhc3RRQyBpcyBoYXBweSB3aXRoIGVpdGhlciBjb21wcmVzc2VkIG9uIHVuLWNvbXByZXNzZWQgZmlsZXMuCgoKTmF2aWdhdGUgdG8geW91ciBGQVNUUSBkYXRhc2V0OiAKCmBgYHtiYXNoIGV2YWw9RkFMU0V9CmNkIH4vcm5hc2VxX2RhdGEvCmBgYAoKCgpUbyBydW4gdGhlIEZhc3RRQyBwcm9ncmFtLCB3ZSB3b3VsZCBub3JtYWxseSBoYXZlIHRvIHRlbGwgb3VyIGNvbXB1dGVyIHdoZXJlIHRoZSBwcm9ncmFtIGlzIGxvY2F0ZWQuIEluIHRoaXMgcGFydGljdWxhciBjYXNlLCBGYXN0UUMgaGFzIGJlZW4gaW5zdGFsbGVkIGluIGEgbG9jYXRpb24gdGhhdCBjYW4gYmUgYWNjZXNzZWQgZnJvbSBhbGwgZGlyZWN0b3JpZXMuIAoKYGBge2Jhc2ggZXZhbD1GQUxTRX0Kd2hpY2ggZmFzdHFjCmBgYAoKYGBgCi91c3IvYmluL2Zhc3RxYwpgYGAKCioqVGhpcyBpcyB0aGUgZmlyc3QgcHJvZ3JhbSB3ZSBoYXZlIHNlZW4gdGhhdCBpcyBzcGVjaWZpYyB0byBOR1MgYW5hbHlzaXMsIHNvIG1pZ2h0IG5vdCBiZSBhdmFpbGFibGUgb24gYWxsIGZpbGUgc3lzdGVtcyBieSBkZWZhdWx0LioqCgpGYXN0UUMgY2FuIGFjY2VwdCBtdWx0aXBsZSBmaWxlIG5hbWVzIGFzIGlucHV0LCBzbyB3ZSBjYW4gdXNlIHRoZSBgKi5mYXN0cS5nemAgd2lsZGNhcmQgdG8gcnVuIEZhc3RRQyBvbiBhbGwgb2YgdGhlIEZBU1RRIGZpbGVzIGluIHRoaXMgZGlyZWN0b3J5LgoKYGBge2Jhc2ggZXZhbD1GQUxTRX0KZmFzdHFjICouZmFzdHEuZ3oKYGBgCgoKWW91IHdpbGwgc2VlIGFuIGF1dG9tYXRpY2FsbHkgdXBkYXRpbmcgb3V0cHV0IG1lc3NhZ2UgdGVsbGluZyB5b3UgdGhlIApwcm9ncmVzcyBvZiB0aGUgYW5hbHlzaXMuIEl0IHdpbGwgc3RhcnQgbGlrZSB0aGlzOiAKCgpgYGAKU3RhcnRlZCBhbmFseXNpcyBvZiBTUlIxNTUyNDQ0LmZhc3RxLmd6CkFwcHJveCAxMDAlIGNvbXBsZXRlIGZvciBTUlIxNTUyNDQ0LmZhc3RxLmd6CkFuYWx5c2lzIGNvbXBsZXRlIGZvciBTUlIxNTUyNDQ0LmZhc3RxLmd6CgpgYGAKCkluIHRvdGFsLCBpdCBzaG91bGQgdGFrZSBsZXNzIHRoYW4gMSBtaW51dGUgZm9yIEZhc3RRQyB0byBydW4gb24gYWxsCm9mIG91ciBGQVNUUSBmaWxlcy4gV2hlbiB0aGUgYW5hbHlzaXMgY29tcGxldGVzLCB5b3VyIHByb21wdAp3aWxsIHJldHVybi4gU28geW91ciBzY3JlZW4gd2lsbCBsb29rIHNvbWV0aGluZyBsaWtlIHRoaXM6CgpgYGAKU3RhcnRlZCBhbmFseXNpcyBvZiBTUlIxNTUyNDU1LmZhc3RxLmd6CkFwcHJveCAxMDAlIGNvbXBsZXRlIGZvciBTUlIxNTUyNDU1LmZhc3RxLmd6CkFuYWx5c2lzIGNvbXBsZXRlIGZvciBTUlIxNTUyNDU1LmZhc3RxLmd6CgpgYGAKClRoZSBGYXN0UUMgcHJvZ3JhbSBoYXMgY3JlYXRlZCBzZXZlcmFsIG5ldyBmaWxlcyB3aXRoaW4gb3VyCmB+L3JuYXNlcV9kYXRhL2AgZGlyZWN0b3J5LiAKCmBgYHtiYXNoIGV2YWw9RkFMU0V9CmxzCmBgYAoKCmBgYApTUlIxNTUyNDQ0LmZhc3RxLmd6ICAgICBTUlIxNTUyNDQ2LmZhc3RxLmd6ICAgICBTUlIxNTUyNDQ4LmZhc3RxLmd6ICAgICBTUlIxNTUyNDUwLmZhc3RxLmd6ICAgICBTUlIxNTUyNDUyLmZhc3RxLmd6ICAgICBTUlIxNTUyNDU0LmZhc3RxLmd6ClNSUjE1NTI0NDRfZmFzdHFjLmh0bWwgIFNSUjE1NTI0NDZfZmFzdHFjLmh0bWwgIFNSUjE1NTI0NDhfZmFzdHFjLmh0bWwgIFNSUjE1NTI0NTBfZmFzdHFjLmh0bWwgIFNSUjE1NTI0NTJfZmFzdHFjLmh0bWwgIFNSUjE1NTI0NTRfZmFzdHFjLmh0bWwKU1JSMTU1MjQ0NF9mYXN0cWMuemlwICAgU1JSMTU1MjQ0Nl9mYXN0cWMuemlwICAgU1JSMTU1MjQ0OF9mYXN0cWMuemlwICAgU1JSMTU1MjQ1MF9mYXN0cWMuemlwICAgU1JSMTU1MjQ1Ml9mYXN0cWMuemlwICAgU1JSMTU1MjQ1NF9mYXN0cWMuemlwClNSUjE1NTI0NDUuZmFzdHEuZ3ogICAgIFNSUjE1NTI0NDcuZmFzdHEuZ3ogICAgIFNSUjE1NTI0NDkuZmFzdHEuZ3ogICAgIFNSUjE1NTI0NTEuZmFzdHEuZ3ogICAgIFNSUjE1NTI0NTMuZmFzdHEuZ3ogICAgIFNSUjE1NTI0NTUuZmFzdHEuZ3oKU1JSMTU1MjQ0NV9mYXN0cWMuaHRtbCAgU1JSMTU1MjQ0N19mYXN0cWMuaHRtbCAgU1JSMTU1MjQ0OV9mYXN0cWMuaHRtbCAgU1JSMTU1MjQ1MV9mYXN0cWMuaHRtbCAgU1JSMTU1MjQ1M19mYXN0cWMuaHRtbCAgU1JSMTU1MjQ1NV9mYXN0cWMuaHRtbApTUlIxNTUyNDQ1X2Zhc3RxYy56aXAgICBTUlIxNTUyNDQ3X2Zhc3RxYy56aXAgICBTUlIxNTUyNDQ5X2Zhc3RxYy56aXAgICBTUlIxNTUyNDUxX2Zhc3RxYy56aXAgICBTUlIxNTUyNDUzX2Zhc3RxYy56aXAgICBTUlIxNTUyNDU1X2Zhc3RxYy56aXAKCmBgYAoKCkZvciBlYWNoIGlucHV0IEZBU1RRIGZpbGUsIEZhc3RRQyBoYXMgY3JlYXRlZCBhIGAuemlwYCBmaWxlIGFuZCBhCmAuaHRtbGAgZmlsZS4gVGhlIGAuemlwYCBmaWxlIGV4dGVuc2lvbiBpbmRpY2F0ZXMgdGhhdCB0aGlzIGlzIAphY3R1YWxseSBhIGNvbXByZXNzZWQgc2V0IG9mIG11bHRpcGxlIG91dHB1dCBmaWxlcy4gV2UnbGwgYmUgd29ya2luZwp3aXRoIHRoZXNlIG91dHB1dCBmaWxlcyBzb29uLiBUaGUgYC5odG1sYCBmaWxlIGlzIGEgc3RhYmxlIHdlYnBhZ2UKZGlzcGxheWluZyB0aGUgc3VtbWFyeSByZXBvcnQgZm9yIGVhY2ggb2Ygb3VyIHNhbXBsZXMuCgpXZSB3YW50IHRvIGtlZXAgb3VyIGRhdGEgZmlsZXMgYW5kIG91ciByZXN1bHRzIGZpbGVzIHNlcGFyYXRlLCBzbyB3ZQp3aWxsIG1vdmUgdGhlc2UKb3V0cHV0IGZpbGVzIGludG8gYSBuZXcgZGlyZWN0b3J5IHdpdGhpbiBvdXIgYHJlc3VsdHMvYCBkaXJlY3RvcnkuIElmIHRoaXMgZGlyZWN0b3J5IGRvZXMgbm90IGV4aXN0LCB3ZSB3aWxsIGhhdmUgdG8gY3JlYXRlIGl0LgoKCgoKYGBge2Jhc2ggZXZhbD1GQUxTRX0KIyMgLXAgZmxhZyBzdG9wcyBhIG1lc3NhZ2UgZnJvbSBhcHBlYXJpbmcgaWYgdGhlIGRpcmVjdG9yeSBhbHJlYWR5IGV4aXN0cwpta2RpciAtcCByZXN1bHRzCm12ICouaHRtbCByZXN1bHRzLwptdiAqLnppcCByZXN1bHRzLwpgYGAKCgojIyBDb21iaW5pbmcgdGhlIHJlcG9ydHMgd2l0aCBgbXVsdGlxY2AKCkl0IGNhbiBiZSBxdWl0ZSB0aXJlc29tZSB0byBjbGljayB0aHJvdWdoIG11bHRpcGxlIFFDIHJlcG9ydHMgYW5kIGNvbXBhcmUgdGhlIHJlc3VsdHMgZm9yIGRpZmZlcmVudCBzYW1wbGVzLiBJdCBpcyB1c2VmdWwgdG8gaGF2ZSBhbGwgdGhlIFFDIHBsb3RzIG9uIHRoZSBzYW1lIHBhZ2Ugc28gdGhhdCB3ZSBjYW4gbW9yZSBlYXNpbHkgc3BvdCB0cmVuZHMgaW4gdGhlIGRhdGEuCgpUaGUgbXVsdGlxYyB0b29sIGhhcyBiZWVuIGRlc2lnbmVkIGZvciB0aGUgdGFza3Mgb2YgYWdncmVnYXRpbmcgcWMgcmVwb3J0cyBhbmQgY29tYmluaW5nIGludG8gYSBzaW5nbGUgcmVwb3J0IHRoYXQgaXMgZWFzeSB0byBkaWdlc3QuCgpgYGB7YmFzaCBldmFsPUZBTFNFfQptdWx0aXFjCm11bHRpcWMgLS1oZWxwCmBgYAoKCj4gIyMgQ2hhbGxlbmdlIDIgey5jaGFsbGVuZ2V9Cj4gCj4gVXNlIHRoZSBtdWx0aXFjIHRvb2wgdG8gY3JlYXRlIGEgc2luZ2xlIFFDIHJlcG9ydCBmb3IgdGhlIGRhdGFzZXQuCj4gTG9vayBhdCB0aGUgaGVscCBmb3IgdGhlIHRvb2wsIGFuZCBmaWd1cmUgb3V0IGhvdyB0byBydW4gdGhlIHRvb2wgb24gdGhlIGZhc3RxYyBvdXRwdXQgd2UgaGF2ZSBqdXN0IGdlbmVyYXRlZC4gTWFrZSBzdXJlIHRoYXQgYG11bHRpcWNgIGNyZWF0ZXMgc2F2ZXMgdGhlIHJlcG9ydCBmaWxlIGluIHRoZSBgcmVzdWx0c2AgZm9sZGVyLgoKClRoZSBlbnZpcm9ubWVudCB0aGF0IHdlIGFyZSB3b3JraW5nIGluc2lkZSBpbmNsdWRlcyBhIHZlcnNpb24gb2YgdGhlIEZpcmVmb3ggd2ViIGJyb3dzZXIuIFdlIGNhbiBvcGVuIGEgcGFydGljdWxhciBIVE1MIGZpbGUgd2l0aCBmaXJlZm94IHVzaW5nIHRoZSBjb21tYW5kOi0KCmBgYApmaXJlZm94IHJlc3VsdHMvU1JSMTU1MjQ0NF9mYXN0cWMuaHRtbCAKYGBgCgpJZiB0aGlzIGRvZXNuJ3Qgd29yaywgdGhlcmUgaXMgYSBGaWxlIEV4cGxvcmVyIHRvb2wgYXZhaWxhYmxlIGluIHRoZSBkZXNrdG9wIGVudmlyb25tZW50IHRoYXQgeW91IGNhbiB1c2UgdG8gbmF2aWdhdGUgdG8sIGFuZCB2aWV3IHRoZSBmaWxlcy4KCj4gIyMgQ2hhbGxlbmdlIDMgey5jaGFsbGVuZ2V9Cj4gCj4gRGlzY3VzcyB5b3VyIHJlc3VsdHMgd2l0aCBhIG5laWdoYm91ci4gV2hpY2ggc2FtcGxlKHMpIGxvb2tzIHRoZSBiZXN0Cj4gaW4gdGVybXMgb2YgcGVyIGJhc2Ugc2VxdWVuY2UgcXVhbGl0eT8gV2hpY2ggc2FtcGxlKHMpIGxvb2sgdGhlCj4gd29yc3Q/Cj4gCgo=