In this module, we will:


Reproducible Computing

Reproducible computing has become increasingly important in recent years. As experimental data volumes have increased exponentially, and as research endeavors have employed more complicated analyses over time, computation has become a fundamental aspect of virtually every type of research.

Reproducibility itself is an integral part of the scientific process. We describe our experiments with sufficient detail so that they can be replicated and our findings can be confirmed by others, and so that eventually others may build upon them.

So taking these two things together, the increasing use of computing in research and the inherent need for reproducibility in the scientific process, we can start to understand the importance of reproducible computing.

There are some challenges we must overcome in this realm. When we try to employ our typical methodologies for general scientific reproducibility, they may not be sufficient to truly enable others to recreate our work. In many cases, in order to credibly validate an analysis, we must be able to not only see and understand the steps of an analysis, but also to use the same software with the same input data and perform these same data manipulations ourselves. Trying to achieve this task with only a descriptive summary of our analysis methods, particularly when using cutting-edge academic software, may often produce little more than frustration.

Let’s take a moment to think about our own experiences with this topic. Can we think of experiences where we encountered challenges while trying to reproduce the analysis of others? Or while trying to share our own analyses with colleagues?

There are a number of tools and techniques that have emerged to address some of these challenges, and to really lower the barrier to sharing and reproducing our results.

In this workshop we’ll discuss these tools and techniques, we’ll provide specific guidance for University of Michigan researchers to address reproducibility concerns, and we’ll use practical examples along the way to gain experience and emphasize the concepts that we learn.


Storage Best Practices

One simple way to organize our thinking about storage best practices is to divide the topic into raw data considerations, and considerations for analysis projects. By separating and focusing on those two aspects, we can effectively address many of the challenges associated with each.

Note: The importance of documentation is universal to all aspects of reproducible research. In considering best practices both for our raw data and for our analysis projects, we will emphasize the importance of documentation!

A Generalized Data Flow

Raw Data

When considering best practices for raw data storage, we can generally orient ourselves around one task - ensure that the data are safe.

Safe from:

  • Accidental deletion
  • Hardware failure
  • Loss of access

With this in mind, we recommend placing your raw experimental data into a specific designated location which is solely dedicated to storing your raw data.

Soon we’ll talk about specific options for UMich researchers, but for now we’ll just speak of the general process. Data that cannot easily be re-obtained should be treated with great care. By following the recommendations here, we can achieve this and have peace of mind that we are preserving our raw data and our capabilities for reproducible research well into the future.

Recommended:

  • Designated location for storing raw data
  • Limit write access of stored data files
  • Use institutional storage
    • Large file sizes and large total allocations
    • Long-term support
    • Hardware redundancy
    • Location redundancy

Another thing to mention for raw data best practices is the procedure of checking file integrity. Whenever transferring data from one storage location to another, and especially while doing so over a network connection, it is good practice to follow up with a file integrity check. Briefly, we use software to inspect our files and determine if any of the contents have changed. In a later module we’ll have a chance to try this ourselves, using the md5sum utility. This is a relatively efficient way of verifying file integrity after a file transfer.

Analysis Projects

We can begin thinking of our next task - handling data and organizing files and artifacts for our analysis - by starting with the idea of the data flow described above. One of the first tasks in this area is to set up a new location for your analysis and make a copy of your raw data there.

Some considerations:

  • Fast storage, well suited for computation
  • Project organization that facilitates reproducibility
  • In-progress analyses, cleanup procedures, and end-to-end repeatable analyses

When we think about fast storage that is well suited for computation, we mostly contrast that with our long-term archival storage. A storage option is well suited for computation if it is accessible via high-throughput connection to sufficiently powerful processing hardware. The speed of reading and writing from this location can greatly affect processing times of your analysis, depending on the steps involved.

In terms of project organization, generally we want to have distinct locations for specific purposes, and preferably organizing things in a consistent manner for all of our projects.

In a particular project, you may want:

  • input_data directory for copy of raw data
  • scripts directory for analysis scripts
  • Directories for intermediates, log files, and final outputs
  • README.txt for the project
    • Optional docs directory for extensive documentation, supporting works, etc.

A useful idea for our project directory layouts is to think about the project life cycle and work towards an end-goal of a reproducible analysis. While at the beginning of an analysis many things may be flexible, at the end we will want to be able to re-execute the analysis starting from the raw input data and running all the way until it produces the final outputs.

Taking time to segregate specific efforts within a project, documenting our steps as we perform in-progress analyses, performing cleanups where needed, and similar efforts will aid us as we work towards that goal.

Think ahead when designing the layout of your projects. If you will be trying several related analysis approaches using the same input data, but intend on using results from only one of the evaluated methods, it may make sense to intentionally subdivide the contents of your project directory accordingly. If you have several distinct analyses that may use the same input data, then perhaps creating separate projects for each of them will make the most sense. It’s hard to be totally prescriptive when making recommendations here, but through our example we hope to spark the kinds of conversations and the types of thinking that are required here.

One last note on handling and organizing analysis projects - use some form of identification system for projects in your lab. This simplifies communication and record keeping, in addition to the organizational benefits.

Some ideas for project identification systems:

  • Codenames
  • Alphanumeric IDs


Storage Options for UMich Researchers

We’ve discussed best practices for data, analysis intermediates and scripts, etc. in general terms, but now we’ll have the opportunity to revisit these ideas while highlighting specific options and recommendations for UMich researchers. By the end of this module, we will understand our numerous storage options available to us. Looking forward to future modules, we’ll also run exercises that interact with some of these storage allocations as we proceed, including Data Den and its unique characteristics and usage patterns.

What is ARC?

The vast majority of computing resources we’ll be discussing in the workshop are provided and managed by ARC - Advanced Research Computing at University of Michigan. The shared computing cluster that we’ll be using in the workshop is run by ARC, and the storage allocations likewise are provided by ARC. Their mission is to provide university researchers with the advanced computing resources that they need, and they’ve been working with research groups in various compute intensive fields to achieve this.

Later in this module we’ll discuss in detail how to request resources through ARC, but for now we’ll focus on the storage topic and cover some important storage options that ARC provides.

Data Den

Data Den is a low-cost, highly durable storage system operated by ARC.

  • Tape-based archival storage
  • The largest and most affordable storage available through ARC.
  • Can only access this indirectly
    • i.e. use Globus to interface with this storage.

Note: Data Den has a file size limitation - it does not handle large amounts of small files. Optimal file size is in the multi-gigabyte range. The limitation 10,000 files per TB of storage.

Turbo

Turbo is a high-capacity, reliable, and fast storage system operated by ARC. It is more costly than Data Den.

  • More costly than Data Den
  • Tuned for files moderate to large in size, but can also easily accomodate small files
  • Can be accessed through the High-Performance Computing (HPC) cluster

Fast storage like Turbo is well-equipped for computing direcly from it. Turbo supports fast read/write times, and is an excellent place to perform analyses.

Turbo and Data Den - Cost Difference

We discussed above that Data Den is slow, unsuited for analysis, yet cost-effective, while Turbo is fast, well-tuned for analysis, and more costly. To put some numbers to this price discussion, see the following table of cost per TB per year:

Unreplicated Replicated
Turbo $77.88 $156.22
Data Den NA $20.04

Notice that Turbo storage is about 8x more costly than Data Den for the same amount of replicated storage.

Note: Data Den is only available in the replicated format.

Home, Scratch, tmp, and others

  • Home directory (80 GB quota)
    • /home/uniqname
  • Scratch directory (10 TB and 1,000,000 file quota)
    • /scratch/account_root/account/uniqname
    • Not persistent over time
      • Automatically deleted if not accessed in 60 days
  • Local disk (4 TB shared)
    • /tmp
    • Not persistent across machines

Institutional Storage vs Other Storage

Institutional Other
Turbo Laptop Storage
Data Den Storage on a Shared Lab Computer
Home / Scratch* Portable Hard Drive / Flash Drive
MiStorage Cloud Storage


UMRCP

The figure above highlights the most important and impressive details of the UMRCP, but you can find full details of the resources offered through this program on the UMRCP page of ARC’s website.

Signing up for the UMRCP

Within that site, there is another page that I highly recommend as a great place to start - the UMRCP Requesting Resources Guide. There you’ll find details about the signup process. After signing up, you’ll be able to use some of the numerous compute nodes available through ARC, as well as the various storage tiers described above.



Additional Resources Available Through HITS RCI

In addition to the resources provided through the UMRCP, some researchers within the medical system will have additonal resources available through UM Health Information Technology & Services (HITS). Through strategic investments in High Performance Computing by Michigan Medicine, eligible researchers can enjoy additional allocations for the described resources - most notably unlimited Data Den storage.

In the documentation for the UMRCP and the UMRCI, you’ll see that they recommend first using the UMRCP resources (available to all university researchers) and then transitioning to these additional HITS UMRCI resources (available to Michigan Medicine researchers) when possible. In any case, since these allocations are managed by ARC for all univerisity researchers - Michigan Medicne or otherwise - you’ll be using the same forms and procedures to request resources and use them. However, the billing details may change depending on this eligibility.

Link to HITS page on UMRCI


Great Lakes, Armis2, and Lighthouse Clusters

This module overall is primarily focused on storage-related topics. We’ve briefly mentioned that in addition to storage resources, ARC also provides access to high-performance computing (HPC) hardware as well. While in this workshop we’ll just be focusing on one of them, in fact there are several HPC clusters that are available to UMich researchers, in order to meet various needs.

When discussing research needs, especially in anticipation of requesting UMRCP resources and filling out the required form, we should discuss a little bit about three HPC options provided through ARC:

  • Great Lakes
  • Armis2 (HIPAA-aligned)
  • Lighthouse (Researcher-owned hardware)

We’ll be discussing Great Lakes at length throughout this workshop and using it for our example analyses. We can think of it as a general-purpose HPC cluster, which is suitable for many different kinds of research.

Armis2 is similar in feel to the Great Lakes cluster, except it is configured with specific security measures in place to enable analysis of sensitive data, such as export-controlled or HIPAA protected data. When filling out the UMRCP form, you can make selections for sensitive data needs, which will provide CPU hours on Armis2 and associated storage. We’ll see later, that we have flexibility in how we allocate resources between e.g. Great Lakes and Armis2.

Note: There is a separate, security-enhanced Turbo allocation that is also HIPAA aligned that should be used with Armis2.

Lighthouse is also similar in feel to the Great Lakes cluster, except it is a cluster comprised entirely of researcher-owned hardware. Contrasting this with Great Lakes where we are only responsible for the cost of the resources we use, on Lighthouse, a researcher will fund the entirety of the hardware and receive 100% of its availability. This can be a good choice for researchers who are expected to have near-constant compute usage needs, or who require instant availability of HPC resources.


Main ideas:

  • PI must be the one to fill out form
  • PI will automatically become an administrator
  • Others can become administrators (lab manager) or members


Administrators vs Users

Change Allocations Add/Remove Users Use GL compute time Read/Write access to Turbo Globus Admin
PI
Lab Manager
Grad Student

Legend:

✅ = Frequent

⏳ = Occasional


Resource Management Portal

A key part of how we will manage our ARC resources is through their Resource Management Portal, shown here.

This portal can be found at https://portal.arc.umich.edu.

Let’s not go there just yet, but discuss what we see in this screenshot, and then move on to the exercise. We’ll learn about some of the differences that we may see depending on our current status and existing resources, and we’ll learn that there are some differences in the best way to request UMRCP resources depending on these details.


Exercise: Make a Game Plan for UMRCP

In this exercise we will determine the needs for UMRCP enrollment by audience & their PIs.

There are two video links below. There’s a decent amount of overlap in the content, and the main ideas are pretty similar. In either case, we will be filling out the UMRCP web forms as shown in the videos. Depending on our current status though, we may have different optimal starting points and different things to consider.


UMRCP How to Enroll - New to ARC Services


UMRCP How to Enroll - Existing Owner of ARC Services



Previous lesson Top of this lesson Next lesson
LS0tCnRpdGxlOiAiU3RvcmFnZSBCZXN0IFByYWN0aWNlcyBhbmQgdGhlIFVNUkNQIgphdXRob3I6ICJVTSBCaW9pbmZvcm1hdGljcyBDb3JlIgpvdXRwdXQ6CiAgICAgICAgaHRtbF9kb2N1bWVudDoKICAgICAgICAgICAgaW5jbHVkZXM6CiAgICAgICAgICAgICAgICBpbl9oZWFkZXI6IGhlYWRlci5odG1sCiAgICAgICAgICAgIHRoZW1lOiBwYXBlcgogICAgICAgICAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlCiAgICAgICAgICAgIGZpZ19jYXB0aW9uOiB0cnVlCiAgICAgICAgICAgIG1hcmtkb3duOiBHRk0KICAgICAgICAgICAgY29kZV9kb3dubG9hZDogdHJ1ZQotLS0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KYm9keXsgLyogTm9ybWFsICAqLwogICAgICBmb250LXNpemU6IDE0cHQ7CiAgfQpwcmUgewogIGZvbnQtc2l6ZTogMTJwdAp9Cjwvc3R5bGU+CgpJbiB0aGlzIG1vZHVsZSwgd2Ugd2lsbDoKCiogZGlzY3VzcyByZXByb2R1Y2libGUgY29tcHV0aW5nIGluIGdlbmVyYWwKKiBkaXNjdXNzIHN0b3JhZ2UgYmVzdCBwcmFjdGljZXMgZm9yIHJhdyBkYXRhLCBhbmxheXNpcyBmaWxlcywgc2NyaXB0cywgZXRjLgoqIGxlYXJuIGFib3V0IHNldmVyYWwgaW5zdGl0dXRpb25hbCBzdG9yYWdlIG9wdGlvbnMgKGFuZCBhc3NvY2lhdGVkIGNvbXB1dGUgcmVzb3VyY2VzKQoqIGxlYXJuIGFib3V0IHRoZSBVTVJDUCBhbmQgaG93IHRvIHJlcXVlc3QgaXQKKiBtYWtlIGEgcGxhbiBmb3IgZW5yb2xsaW5nIFBJcyBpbiBVTVJDUCBhbmQgZW5hYmxpbmcgYWNjZXNzIHRvIGFsbCByZXNlYXJjaGVycwoKPGJyPgoKIyMgUmVwcm9kdWNpYmxlIENvbXB1dGluZwoKUmVwcm9kdWNpYmxlIGNvbXB1dGluZyBoYXMgYmVjb21lIGluY3JlYXNpbmdseSBpbXBvcnRhbnQgaW4gcmVjZW50IHllYXJzLiBBcyBleHBlcmltZW50YWwgZGF0YSB2b2x1bWVzIGhhdmUgaW5jcmVhc2VkIGV4cG9uZW50aWFsbHksIGFuZCBhcyByZXNlYXJjaCBlbmRlYXZvcnMgaGF2ZSBlbXBsb3llZCBtb3JlIGNvbXBsaWNhdGVkIGFuYWx5c2VzIG92ZXIgdGltZSwgY29tcHV0YXRpb24gaGFzIGJlY29tZSBhIGZ1bmRhbWVudGFsIGFzcGVjdCBvZiB2aXJ0dWFsbHkgZXZlcnkgdHlwZSBvZiByZXNlYXJjaC4KClJlcHJvZHVjaWJpbGl0eSBpdHNlbGYgaXMgYW4gaW50ZWdyYWwgcGFydCBvZiB0aGUgc2NpZW50aWZpYyBwcm9jZXNzLiBXZSBkZXNjcmliZSBvdXIgZXhwZXJpbWVudHMgd2l0aCBzdWZmaWNpZW50IGRldGFpbCBzbyB0aGF0IHRoZXkgY2FuIGJlIHJlcGxpY2F0ZWQgYW5kIG91ciBmaW5kaW5ncyBjYW4gYmUgY29uZmlybWVkIGJ5IG90aGVycywgYW5kIHNvIHRoYXQgZXZlbnR1YWxseSBvdGhlcnMgbWF5IGJ1aWxkIHVwb24gdGhlbS4KClNvIHRha2luZyB0aGVzZSB0d28gdGhpbmdzIHRvZ2V0aGVyLCB0aGUgaW5jcmVhc2luZyB1c2Ugb2YgY29tcHV0aW5nIGluIHJlc2VhcmNoIGFuZCB0aGUgaW5oZXJlbnQgbmVlZCBmb3IgcmVwcm9kdWNpYmlsaXR5IGluIHRoZSBzY2llbnRpZmljIHByb2Nlc3MsIHdlIGNhbiBzdGFydCB0byB1bmRlcnN0YW5kIHRoZSBpbXBvcnRhbmNlIG9mIHJlcHJvZHVjaWJsZSBjb21wdXRpbmcuCgpUaGVyZSBhcmUgc29tZSBjaGFsbGVuZ2VzIHdlIG11c3Qgb3ZlcmNvbWUgaW4gdGhpcyByZWFsbS4gV2hlbiB3ZSB0cnkgdG8gZW1wbG95IG91ciB0eXBpY2FsIG1ldGhvZG9sb2dpZXMgZm9yIGdlbmVyYWwgc2NpZW50aWZpYyByZXByb2R1Y2liaWxpdHksIHRoZXkgbWF5IG5vdCBiZSBzdWZmaWNpZW50IHRvIHRydWx5IGVuYWJsZSBvdGhlcnMgdG8gcmVjcmVhdGUgb3VyIHdvcmsuIEluIG1hbnkgY2FzZXMsIGluIG9yZGVyIHRvIGNyZWRpYmx5IHZhbGlkYXRlIGFuIGFuYWx5c2lzLCB3ZSBtdXN0IGJlIGFibGUgdG8gbm90IG9ubHkgc2VlIGFuZCB1bmRlcnN0YW5kIHRoZSBzdGVwcyBvZiBhbiBhbmFseXNpcywgYnV0IGFsc28gdG8gdXNlIHRoZSBzYW1lIHNvZnR3YXJlIHdpdGggdGhlIHNhbWUgaW5wdXQgZGF0YSBhbmQgcGVyZm9ybSB0aGVzZSBzYW1lIGRhdGEgbWFuaXB1bGF0aW9ucyBvdXJzZWx2ZXMuIFRyeWluZyB0byBhY2hpZXZlIHRoaXMgdGFzayB3aXRoIG9ubHkgYSBkZXNjcmlwdGl2ZSBzdW1tYXJ5IG9mIG91ciBhbmFseXNpcyBtZXRob2RzLCBwYXJ0aWN1bGFybHkgd2hlbiB1c2luZyBjdXR0aW5nLWVkZ2UgYWNhZGVtaWMgc29mdHdhcmUsIG1heSBvZnRlbiBwcm9kdWNlIGxpdHRsZSBtb3JlIHRoYW4gZnJ1c3RyYXRpb24uCgpMZXQncyB0YWtlIGEgbW9tZW50IHRvIHRoaW5rIGFib3V0IG91ciBvd24gZXhwZXJpZW5jZXMgd2l0aCB0aGlzIHRvcGljLiBDYW4gd2UgdGhpbmsgb2YgZXhwZXJpZW5jZXMgd2hlcmUgd2UgZW5jb3VudGVyZWQgY2hhbGxlbmdlcyB3aGlsZSB0cnlpbmcgdG8gcmVwcm9kdWNlIHRoZSBhbmFseXNpcyBvZiBvdGhlcnM/IE9yIHdoaWxlIHRyeWluZyB0byBzaGFyZSBvdXIgb3duIGFuYWx5c2VzIHdpdGggY29sbGVhZ3Vlcz8KClRoZXJlIGFyZSBhIG51bWJlciBvZiB0b29scyBhbmQgdGVjaG5pcXVlcyB0aGF0IGhhdmUgZW1lcmdlZCB0byBhZGRyZXNzIHNvbWUgb2YgdGhlc2UgY2hhbGxlbmdlcywgYW5kIHRvIHJlYWxseSBsb3dlciB0aGUgYmFycmllciB0byBzaGFyaW5nIGFuZCByZXByb2R1Y2luZyBvdXIgcmVzdWx0cy4KCkluIHRoaXMgd29ya3Nob3Agd2UnbGwgZGlzY3VzcyB0aGVzZSB0b29scyBhbmQgdGVjaG5pcXVlcywgd2UnbGwgcHJvdmlkZSBzcGVjaWZpYyBndWlkYW5jZSBmb3IgVW5pdmVyc2l0eSBvZiBNaWNoaWdhbiByZXNlYXJjaGVycyB0byBhZGRyZXNzIHJlcHJvZHVjaWJpbGl0eSBjb25jZXJucywgYW5kIHdlJ2xsIHVzZSBwcmFjdGljYWwgZXhhbXBsZXMgYWxvbmcgdGhlIHdheSB0byBnYWluIGV4cGVyaWVuY2UgYW5kIGVtcGhhc2l6ZSB0aGUgY29uY2VwdHMgdGhhdCB3ZSBsZWFybi4KCjxicj4KCiMjIFN0b3JhZ2UgQmVzdCBQcmFjdGljZXMKCk9uZSBzaW1wbGUgd2F5IHRvIG9yZ2FuaXplIG91ciB0aGlua2luZyBhYm91dCBzdG9yYWdlIGJlc3QgcHJhY3RpY2VzIGlzIHRvIGRpdmlkZSB0aGUgdG9waWMgaW50byByYXcgZGF0YSBjb25zaWRlcmF0aW9ucywgYW5kIGNvbnNpZGVyYXRpb25zIGZvciBhbmFseXNpcyBwcm9qZWN0cy4gQnkgc2VwYXJhdGluZyBhbmQgZm9jdXNpbmcgb24gdGhvc2UgdHdvIGFzcGVjdHMsIHdlIGNhbiBlZmZlY3RpdmVseSBhZGRyZXNzIG1hbnkgb2YgdGhlIGNoYWxsZW5nZXMgYXNzb2NpYXRlZCB3aXRoIGVhY2guCgo+Tm90ZTogVGhlIGltcG9ydGFuY2Ugb2YgZG9jdW1lbnRhdGlvbiBpcyB1bml2ZXJzYWwgdG8gYWxsIGFzcGVjdHMgb2YgcmVwcm9kdWNpYmxlIHJlc2VhcmNoLiBJbiBjb25zaWRlcmluZyBiZXN0IHByYWN0aWNlcyBib3RoIGZvciBvdXIgcmF3IGRhdGEgYW5kIGZvciBvdXIgYW5hbHlzaXMgcHJvamVjdHMsIHdlIHdpbGwgZW1waGFzaXplIHRoZSBpbXBvcnRhbmNlIG9mIGRvY3VtZW50YXRpb24hCgojIyMgQSBHZW5lcmFsaXplZCBEYXRhIEZsb3cKCiFbXShpbWFnZXMvTW9kdWxlMDFfZ2VuZXJhbF9iZXN0X3ByYWN0aWNlX2RhdGFfZmxvdy5wbmcpCgojIyMgUmF3IERhdGEKCldoZW4gY29uc2lkZXJpbmcgYmVzdCBwcmFjdGljZXMgZm9yIHJhdyBkYXRhIHN0b3JhZ2UsIHdlIGNhbiBnZW5lcmFsbHkgb3JpZW50IG91cnNlbHZlcyBhcm91bmQgb25lIHRhc2sgLSBlbnN1cmUgdGhhdCB0aGUgZGF0YSBhcmUgc2FmZS4KClNhZmUgZnJvbToKCi0gQWNjaWRlbnRhbCBkZWxldGlvbgotIEhhcmR3YXJlIGZhaWx1cmUKLSBMb3NzIG9mIGFjY2VzcwoKV2l0aCB0aGlzIGluIG1pbmQsIHdlIHJlY29tbWVuZCBwbGFjaW5nIHlvdXIgcmF3IGV4cGVyaW1lbnRhbCBkYXRhIGludG8gYSBzcGVjaWZpYyBkZXNpZ25hdGVkIGxvY2F0aW9uIHdoaWNoIGlzICoqc29sZWx5KiogZGVkaWNhdGVkIHRvIHN0b3JpbmcgeW91ciByYXcgZGF0YS4KClNvb24gd2UnbGwgdGFsayBhYm91dCBzcGVjaWZpYyBvcHRpb25zIGZvciBVTWljaCByZXNlYXJjaGVycywgYnV0IGZvciBub3cgd2UnbGwganVzdCBzcGVhayBvZiB0aGUgZ2VuZXJhbCBwcm9jZXNzLiBEYXRhIHRoYXQgY2Fubm90IGVhc2lseSBiZSByZS1vYnRhaW5lZCBzaG91bGQgYmUgdHJlYXRlZCB3aXRoIGdyZWF0IGNhcmUuIEJ5IGZvbGxvd2luZyB0aGUgcmVjb21tZW5kYXRpb25zIGhlcmUsIHdlIGNhbiBhY2hpZXZlIHRoaXMgYW5kIGhhdmUgcGVhY2Ugb2YgbWluZCB0aGF0IHdlIGFyZSBwcmVzZXJ2aW5nIG91ciByYXcgZGF0YSBhbmQgb3VyIGNhcGFiaWxpdGllcyBmb3IgcmVwcm9kdWNpYmxlIHJlc2VhcmNoIHdlbGwgaW50byB0aGUgZnV0dXJlLgoKUmVjb21tZW5kZWQ6CgotIERlc2lnbmF0ZWQgbG9jYXRpb24gZm9yIHN0b3JpbmcgcmF3IGRhdGEKLSBMaW1pdCB3cml0ZSBhY2Nlc3Mgb2Ygc3RvcmVkIGRhdGEgZmlsZXMKLSBVc2UgaW5zdGl0dXRpb25hbCBzdG9yYWdlCiAgLSBMYXJnZSBmaWxlIHNpemVzIGFuZCBsYXJnZSB0b3RhbCBhbGxvY2F0aW9ucwogIC0gTG9uZy10ZXJtIHN1cHBvcnQKICAtIEhhcmR3YXJlIHJlZHVuZGFuY3kKICAtIExvY2F0aW9uIHJlZHVuZGFuY3kKCkFub3RoZXIgdGhpbmcgdG8gbWVudGlvbiBmb3IgcmF3IGRhdGEgYmVzdCBwcmFjdGljZXMgaXMgdGhlIHByb2NlZHVyZSBvZiBjaGVja2luZyBmaWxlIGludGVncml0eS4gV2hlbmV2ZXIgdHJhbnNmZXJyaW5nIGRhdGEgZnJvbSBvbmUgc3RvcmFnZSBsb2NhdGlvbiB0byBhbm90aGVyLCBhbmQgZXNwZWNpYWxseSB3aGlsZSBkb2luZyBzbyBvdmVyIGEgbmV0d29yayBjb25uZWN0aW9uLCBpdCBpcyBnb29kIHByYWN0aWNlIHRvIGZvbGxvdyB1cCB3aXRoIGEgZmlsZSBpbnRlZ3JpdHkgY2hlY2suIEJyaWVmbHksIHdlIHVzZSBzb2Z0d2FyZSB0byBpbnNwZWN0IG91ciBmaWxlcyBhbmQgZGV0ZXJtaW5lIGlmIGFueSBvZiB0aGUgY29udGVudHMgaGF2ZSBjaGFuZ2VkLiBJbiBhIGxhdGVyIG1vZHVsZSB3ZSdsbCBoYXZlIGEgY2hhbmNlIHRvIHRyeSB0aGlzIG91cnNlbHZlcywgdXNpbmcgdGhlIGBtZDVzdW1gIHV0aWxpdHkuIFRoaXMgaXMgYSByZWxhdGl2ZWx5IGVmZmljaWVudCB3YXkgb2YgdmVyaWZ5aW5nIGZpbGUgaW50ZWdyaXR5IGFmdGVyIGEgZmlsZSB0cmFuc2Zlci4KCgojIyMgQW5hbHlzaXMgUHJvamVjdHMKCldlIGNhbiBiZWdpbiB0aGlua2luZyBvZiBvdXIgbmV4dCB0YXNrIC0gaGFuZGxpbmcgZGF0YSBhbmQgb3JnYW5pemluZyBmaWxlcyBhbmQgYXJ0aWZhY3RzIGZvciBvdXIgYW5hbHlzaXMgLSBieSBzdGFydGluZyB3aXRoIHRoZSBpZGVhIG9mIHRoZSBkYXRhIGZsb3cgZGVzY3JpYmVkIGFib3ZlLiBPbmUgb2YgdGhlIGZpcnN0IHRhc2tzIGluIHRoaXMgYXJlYSBpcyB0byBzZXQgdXAgYSBuZXcgbG9jYXRpb24gZm9yIHlvdXIgYW5hbHlzaXMgYW5kIG1ha2UgYSBjb3B5IG9mIHlvdXIgcmF3IGRhdGEgdGhlcmUuCgpTb21lIGNvbnNpZGVyYXRpb25zOgoKIC0gRmFzdCBzdG9yYWdlLCB3ZWxsIHN1aXRlZCBmb3IgY29tcHV0YXRpb24KIC0gUHJvamVjdCBvcmdhbml6YXRpb24gdGhhdCBmYWNpbGl0YXRlcyByZXByb2R1Y2liaWxpdHkKIC0gSW4tcHJvZ3Jlc3MgYW5hbHlzZXMsIGNsZWFudXAgcHJvY2VkdXJlcywgYW5kIGVuZC10by1lbmQgcmVwZWF0YWJsZSBhbmFseXNlcwoKV2hlbiB3ZSB0aGluayBhYm91dCBmYXN0IHN0b3JhZ2UgdGhhdCBpcyB3ZWxsIHN1aXRlZCBmb3IgY29tcHV0YXRpb24sIHdlIG1vc3RseSBjb250cmFzdCB0aGF0IHdpdGggb3VyIGxvbmctdGVybSBhcmNoaXZhbCBzdG9yYWdlLiBBIHN0b3JhZ2Ugb3B0aW9uIGlzIHdlbGwgc3VpdGVkIGZvciBjb21wdXRhdGlvbiBpZiBpdCBpcyBhY2Nlc3NpYmxlIHZpYSBoaWdoLXRocm91Z2hwdXQgY29ubmVjdGlvbiB0byBzdWZmaWNpZW50bHkgcG93ZXJmdWwgcHJvY2Vzc2luZyBoYXJkd2FyZS4gVGhlIHNwZWVkIG9mIHJlYWRpbmcgYW5kIHdyaXRpbmcgZnJvbSB0aGlzIGxvY2F0aW9uIGNhbiBncmVhdGx5IGFmZmVjdCBwcm9jZXNzaW5nIHRpbWVzIG9mIHlvdXIgYW5hbHlzaXMsIGRlcGVuZGluZyBvbiB0aGUgc3RlcHMgaW52b2x2ZWQuCgpJbiB0ZXJtcyBvZiBwcm9qZWN0IG9yZ2FuaXphdGlvbiwgZ2VuZXJhbGx5IHdlIHdhbnQgdG8gaGF2ZSBkaXN0aW5jdCBsb2NhdGlvbnMgZm9yIHNwZWNpZmljIHB1cnBvc2VzLCBhbmQgcHJlZmVyYWJseSBvcmdhbml6aW5nIHRoaW5ncyBpbiBhIGNvbnNpc3RlbnQgbWFubmVyIGZvciBhbGwgb2Ygb3VyIHByb2plY3RzLgoKSW4gYSBwYXJ0aWN1bGFyIHByb2plY3QsIHlvdSBtYXkgd2FudDoKCi0gYGlucHV0X2RhdGFgIGRpcmVjdG9yeSBmb3IgY29weSBvZiByYXcgZGF0YQotIGBzY3JpcHRzYCBkaXJlY3RvcnkgZm9yIGFuYWx5c2lzIHNjcmlwdHMKLSBEaXJlY3RvcmllcyBmb3IgaW50ZXJtZWRpYXRlcywgbG9nIGZpbGVzLCBhbmQgZmluYWwgb3V0cHV0cwotIGBSRUFETUUudHh0YCBmb3IgdGhlIHByb2plY3QKICAtIE9wdGlvbmFsIGBkb2NzYCBkaXJlY3RvcnkgZm9yIGV4dGVuc2l2ZSBkb2N1bWVudGF0aW9uLCBzdXBwb3J0aW5nIHdvcmtzLCBldGMuCgpBIHVzZWZ1bCBpZGVhIGZvciBvdXIgcHJvamVjdCBkaXJlY3RvcnkgbGF5b3V0cyBpcyB0byB0aGluayBhYm91dCB0aGUgcHJvamVjdCBsaWZlIGN5Y2xlIGFuZCB3b3JrIHRvd2FyZHMgYW4gZW5kLWdvYWwgb2YgYSByZXByb2R1Y2libGUgYW5hbHlzaXMuIFdoaWxlIGF0IHRoZSBiZWdpbm5pbmcgb2YgYW4gYW5hbHlzaXMgbWFueSB0aGluZ3MgbWF5IGJlIGZsZXhpYmxlLCBhdCB0aGUgZW5kIHdlIHdpbGwgd2FudCB0byBiZSBhYmxlIHRvIHJlLWV4ZWN1dGUgdGhlIGFuYWx5c2lzIHN0YXJ0aW5nIGZyb20gdGhlIHJhdyBpbnB1dCBkYXRhIGFuZCBydW5uaW5nIGFsbCB0aGUgd2F5IHVudGlsIGl0IHByb2R1Y2VzIHRoZSBmaW5hbCBvdXRwdXRzLgoKVGFraW5nIHRpbWUgdG8gc2VncmVnYXRlIHNwZWNpZmljIGVmZm9ydHMgd2l0aGluIGEgcHJvamVjdCwgZG9jdW1lbnRpbmcgb3VyIHN0ZXBzIGFzIHdlIHBlcmZvcm0gaW4tcHJvZ3Jlc3MgYW5hbHlzZXMsIHBlcmZvcm1pbmcgY2xlYW51cHMgd2hlcmUgbmVlZGVkLCBhbmQgc2ltaWxhciBlZmZvcnRzIHdpbGwgYWlkIHVzIGFzIHdlIHdvcmsgdG93YXJkcyB0aGF0IGdvYWwuCgpUaGluayBhaGVhZCB3aGVuIGRlc2lnbmluZyB0aGUgbGF5b3V0IG9mIHlvdXIgcHJvamVjdHMuIElmIHlvdSB3aWxsIGJlIHRyeWluZyBzZXZlcmFsIHJlbGF0ZWQgYW5hbHlzaXMgYXBwcm9hY2hlcyB1c2luZyB0aGUgc2FtZSBpbnB1dCBkYXRhLCBidXQgaW50ZW5kIG9uIHVzaW5nIHJlc3VsdHMgZnJvbSBvbmx5IG9uZSBvZiB0aGUgZXZhbHVhdGVkIG1ldGhvZHMsIGl0IG1heSBtYWtlIHNlbnNlIHRvIGludGVudGlvbmFsbHkgc3ViZGl2aWRlIHRoZSBjb250ZW50cyBvZiB5b3VyIHByb2plY3QgZGlyZWN0b3J5IGFjY29yZGluZ2x5LiBJZiB5b3UgaGF2ZSBzZXZlcmFsIGRpc3RpbmN0IGFuYWx5c2VzIHRoYXQgbWF5IHVzZSB0aGUgc2FtZSBpbnB1dCBkYXRhLCB0aGVuIHBlcmhhcHMgY3JlYXRpbmcgc2VwYXJhdGUgcHJvamVjdHMgZm9yIGVhY2ggb2YgdGhlbSB3aWxsIG1ha2UgdGhlIG1vc3Qgc2Vuc2UuIEl0J3MgaGFyZCB0byBiZSB0b3RhbGx5IHByZXNjcmlwdGl2ZSB3aGVuIG1ha2luZyByZWNvbW1lbmRhdGlvbnMgaGVyZSwgYnV0IHRocm91Z2ggb3VyIGV4YW1wbGUgd2UgaG9wZSB0byBzcGFyayB0aGUga2luZHMgb2YgY29udmVyc2F0aW9ucyBhbmQgdGhlIHR5cGVzIG9mIHRoaW5raW5nIHRoYXQgYXJlIHJlcXVpcmVkIGhlcmUuCgohW10oaW1hZ2VzL01vZHVsZTAxX3Byb2plY3RzX2xheW91dC5wbmcpCgpPbmUgbGFzdCBub3RlIG9uIGhhbmRsaW5nIGFuZCBvcmdhbml6aW5nIGFuYWx5c2lzIHByb2plY3RzIC0gdXNlIHNvbWUgZm9ybSBvZiBpZGVudGlmaWNhdGlvbiBzeXN0ZW0gZm9yIHByb2plY3RzIGluIHlvdXIgbGFiLiBUaGlzIHNpbXBsaWZpZXMgY29tbXVuaWNhdGlvbiBhbmQgcmVjb3JkIGtlZXBpbmcsIGluIGFkZGl0aW9uIHRvIHRoZSBvcmdhbml6YXRpb25hbCBiZW5lZml0cy4KClNvbWUgaWRlYXMgZm9yIHByb2plY3QgaWRlbnRpZmljYXRpb24gc3lzdGVtczoKCi0gQ29kZW5hbWVzCi0gQWxwaGFudW1lcmljIElEcwoKPGJyPgoKIyMgU3RvcmFnZSBPcHRpb25zIGZvciBVTWljaCBSZXNlYXJjaGVycwoKV2UndmUgZGlzY3Vzc2VkIGJlc3QgcHJhY3RpY2VzIGZvciBkYXRhLCBhbmFseXNpcyBpbnRlcm1lZGlhdGVzIGFuZCBzY3JpcHRzLCBldGMuIGluIGdlbmVyYWwgdGVybXMsIGJ1dCBub3cgd2UnbGwgaGF2ZSB0aGUgb3Bwb3J0dW5pdHkgdG8gcmV2aXNpdCB0aGVzZSBpZGVhcyB3aGlsZSBoaWdobGlnaHRpbmcgc3BlY2lmaWMgb3B0aW9ucyBhbmQgcmVjb21tZW5kYXRpb25zIGZvciBVTWljaCByZXNlYXJjaGVycy4gQnkgdGhlIGVuZCBvZiB0aGlzIG1vZHVsZSwgd2Ugd2lsbCB1bmRlcnN0YW5kIG91ciBudW1lcm91cyBzdG9yYWdlIG9wdGlvbnMgYXZhaWxhYmxlIHRvIHVzLiBMb29raW5nIGZvcndhcmQgdG8gZnV0dXJlIG1vZHVsZXMsIHdlJ2xsIGFsc28gcnVuIGV4ZXJjaXNlcyB0aGF0IGludGVyYWN0IHdpdGggc29tZSBvZiB0aGVzZSBzdG9yYWdlIGFsbG9jYXRpb25zIGFzIHdlIHByb2NlZWQsIGluY2x1ZGluZyBEYXRhIERlbiBhbmQgaXRzIHVuaXF1ZSBjaGFyYWN0ZXJpc3RpY3MgYW5kIHVzYWdlIHBhdHRlcm5zLgoKCiMjIyBXaGF0IGlzIEFSQz8KClRoZSB2YXN0IG1ham9yaXR5IG9mIGNvbXB1dGluZyByZXNvdXJjZXMgd2UnbGwgYmUgZGlzY3Vzc2luZyBpbiB0aGUgd29ya3Nob3AgYXJlIHByb3ZpZGVkIGFuZCBtYW5hZ2VkIGJ5IEFSQyAtIEFkdmFuY2VkIFJlc2VhcmNoIENvbXB1dGluZyBhdCBVbml2ZXJzaXR5IG9mIE1pY2hpZ2FuLiBUaGUgc2hhcmVkIGNvbXB1dGluZyBjbHVzdGVyIHRoYXQgd2UnbGwgYmUgdXNpbmcgaW4gdGhlIHdvcmtzaG9wIGlzIHJ1biBieSBBUkMsIGFuZCB0aGUgc3RvcmFnZSBhbGxvY2F0aW9ucyBsaWtld2lzZSBhcmUgcHJvdmlkZWQgYnkgQVJDLiBUaGVpciBtaXNzaW9uIGlzIHRvIHByb3ZpZGUgdW5pdmVyc2l0eSByZXNlYXJjaGVycyB3aXRoIHRoZSBhZHZhbmNlZCBjb21wdXRpbmcgcmVzb3VyY2VzIHRoYXQgdGhleSBuZWVkLCBhbmQgdGhleSd2ZSBiZWVuIHdvcmtpbmcgd2l0aCByZXNlYXJjaCBncm91cHMgaW4gdmFyaW91cyBjb21wdXRlIGludGVuc2l2ZSBmaWVsZHMgdG8gYWNoaWV2ZSB0aGlzLiAKCkxhdGVyIGluIHRoaXMgbW9kdWxlIHdlJ2xsIGRpc2N1c3MgaW4gZGV0YWlsIGhvdyB0byByZXF1ZXN0IHJlc291cmNlcyB0aHJvdWdoIEFSQywgYnV0IGZvciBub3cgd2UnbGwgZm9jdXMgb24gdGhlIHN0b3JhZ2UgdG9waWMgYW5kIGNvdmVyIHNvbWUgaW1wb3J0YW50IHN0b3JhZ2Ugb3B0aW9ucyB0aGF0IEFSQyBwcm92aWRlcy4KCiMjIyBEYXRhIERlbgoKRGF0YSBEZW4gaXMgYSBsb3ctY29zdCwgaGlnaGx5IGR1cmFibGUgc3RvcmFnZSBzeXN0ZW0gb3BlcmF0ZWQgYnkgQVJDLgoKLSBUYXBlLWJhc2VkIGFyY2hpdmFsIHN0b3JhZ2UKLSBUaGUgbGFyZ2VzdCBhbmQgbW9zdCBhZmZvcmRhYmxlIHN0b3JhZ2UgYXZhaWxhYmxlIHRocm91Z2ggQVJDLgotIENhbiBvbmx5IGFjY2VzcyB0aGlzIGluZGlyZWN0bHkKICAtIGkuZS4gdXNlIEdsb2J1cyB0byBpbnRlcmZhY2Ugd2l0aCB0aGlzIHN0b3JhZ2UuIAogIAo8IS0tIER1ZSB0byBpdHMgYXJjaGl0ZWN0dXJlLCBzbG93IHNwZWVkcywgYW5kIG5lZWQgdG8gZWxpbWluYXRlIHVubmVjZXNzYXJ5IHJlYWQvd3JpdGUgb3BlcmF0aW9ucyAtLT4KCj4gTm90ZTogRGF0YSBEZW4gaGFzIGEgZmlsZSBzaXplIGxpbWl0YXRpb24gLSBpdCBkb2VzIG5vdCBoYW5kbGUgbGFyZ2UgYW1vdW50cyBvZiBzbWFsbCBmaWxlcy4gT3B0aW1hbCBmaWxlIHNpemUgaXMgaW4gdGhlIG11bHRpLWdpZ2FieXRlIHJhbmdlLgo+IFRoZSBsaW1pdGF0aW9uIDEwLDAwMCBmaWxlcyBwZXIgVEIgb2Ygc3RvcmFnZS4KCgojIyMgVHVyYm8KClR1cmJvIGlzIGEgaGlnaC1jYXBhY2l0eSwgcmVsaWFibGUsIGFuZCBmYXN0IHN0b3JhZ2Ugc3lzdGVtIG9wZXJhdGVkIGJ5IEFSQy4gSXQgaXMgbW9yZSBjb3N0bHkgdGhhbiBEYXRhIERlbi4KCi0gTW9yZSBjb3N0bHkgdGhhbiBEYXRhIERlbgotIFR1bmVkIGZvciBmaWxlcyBtb2RlcmF0ZSB0byBsYXJnZSBpbiBzaXplLCBidXQgY2FuIGFsc28gZWFzaWx5IGFjY29tb2RhdGUgc21hbGwgZmlsZXMKLSBDYW4gYmUgYWNjZXNzZWQgdGhyb3VnaCB0aGUgSGlnaC1QZXJmb3JtYW5jZSBDb21wdXRpbmcgKEhQQykgY2x1c3RlcgoKRmFzdCBzdG9yYWdlIGxpa2UgVHVyYm8gaXMgd2VsbC1lcXVpcHBlZCBmb3IgY29tcHV0aW5nIGRpcmVjbHkgZnJvbSBpdC4gVHVyYm8gc3VwcG9ydHMgZmFzdCByZWFkL3dyaXRlIHRpbWVzLCBhbmQgaXMgYW4gZXhjZWxsZW50IHBsYWNlIHRvIHBlcmZvcm0gYW5hbHlzZXMuCgoKIyMjIFR1cmJvIGFuZCBEYXRhIERlbiAtIENvc3QgRGlmZmVyZW5jZQoKV2UgZGlzY3Vzc2VkIGFib3ZlIHRoYXQgRGF0YSBEZW4gaXMgc2xvdywgdW5zdWl0ZWQgZm9yIGFuYWx5c2lzLCB5ZXQgY29zdC1lZmZlY3RpdmUsIHdoaWxlIFR1cmJvIGlzIGZhc3QsIHdlbGwtdHVuZWQgZm9yIGFuYWx5c2lzLCBhbmQgbW9yZSBjb3N0bHkuIFRvIHB1dCBzb21lIG51bWJlcnMgdG8gdGhpcyBwcmljZSBkaXNjdXNzaW9uLCBzZWUgdGhlIGZvbGxvd2luZyB0YWJsZSBvZiBjb3N0IHBlciBUQiBwZXIgeWVhcjoKCnwgICAgICAgICAgfCBVbnJlcGxpY2F0ZWQgfCBSZXBsaWNhdGVkIHwKfCAtLS0tLS0tLTp8IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tOnwgLS0tLS0tLS0tLTp8CnwgVHVyYm8gICAgfCAkNzcuODggICAgICAgICAgICAgICAgICB8ICQxNTYuMjIgICAgfAp8IERhdGEgRGVuIHwgTkEgICAgICAgICAgICAgICAgICAgICAgfCAkMjAuMDQgICAgIHwKCk5vdGljZSB0aGF0IFR1cmJvIHN0b3JhZ2UgaXMgYWJvdXQgOHggbW9yZSBjb3N0bHkgdGhhbiBEYXRhIERlbiBmb3IgdGhlIHNhbWUgYW1vdW50IG9mIHJlcGxpY2F0ZWQgc3RvcmFnZS4KCj5Ob3RlOiBEYXRhIERlbiBpcyBvbmx5IGF2YWlsYWJsZSBpbiB0aGUgcmVwbGljYXRlZCBmb3JtYXQuCgoKIyMjIEhvbWUsIFNjcmF0Y2gsIHRtcCwgYW5kIG90aGVycwoKLSBIb21lIGRpcmVjdG9yeSAoODAgR0IgcXVvdGEpCiAgLSAvaG9tZS91bmlxbmFtZQotIFNjcmF0Y2ggZGlyZWN0b3J5ICgxMCBUQiBhbmQgMSwwMDAsMDAwIGZpbGUgcXVvdGEpCiAgLSAvc2NyYXRjaC9hY2NvdW50X3Jvb3QvYWNjb3VudC91bmlxbmFtZQogIC0gTm90IHBlcnNpc3RlbnQgb3ZlciB0aW1lCiAgICAtIEF1dG9tYXRpY2FsbHkgZGVsZXRlZCBpZiBub3QgYWNjZXNzZWQgaW4gNjAgZGF5cwotIExvY2FsIGRpc2sgKDQgVEIgc2hhcmVkKQogIC0gL3RtcAogIC0gTm90IHBlcnNpc3RlbnQgYWNyb3NzIG1hY2hpbmVzCgoKIyMjIEluc3RpdHV0aW9uYWwgU3RvcmFnZSB2cyBPdGhlciBTdG9yYWdlCgp8IEluc3RpdHV0aW9uYWwgfCBPdGhlciB8Cnw6LS0tLS0tLS0tLS0tLS0tIHw6LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIHwKfCBUdXJibyAgICAgICAgICAgfCBMYXB0b3AgU3RvcmFnZSAgICAgICAgICAgICAgICAgICAgfAp8IERhdGEgRGVuICAgICAgICB8IFN0b3JhZ2Ugb24gYSBTaGFyZWQgTGFiIENvbXB1dGVyICB8CnwgSG9tZSAvIFNjcmF0Y2gqIHwgUG9ydGFibGUgSGFyZCBEcml2ZSAvIEZsYXNoIERyaXZlIHwKfCBNaVN0b3JhZ2UgICAgICAgfCBDbG91ZCBTdG9yYWdlICAgICAgICAgICAgICAgICAgICAgfAoKPGJyPgoKIyMgVU1SQ1AKCiFbXShpbWFnZXMvTW9kdWxlMDFfVU1SQ1BfcHJvdmlkZXMucG5nKQoKVGhlIGZpZ3VyZSBhYm92ZSBoaWdobGlnaHRzIHRoZSBtb3N0IGltcG9ydGFudCBhbmQgaW1wcmVzc2l2ZSBkZXRhaWxzIG9mIHRoZSBVTVJDUCwgYnV0IHlvdSBjYW4gZmluZCBmdWxsIGRldGFpbHMgb2YgdGhlIHJlc291cmNlcyBvZmZlcmVkIHRocm91Z2ggdGhpcyBwcm9ncmFtIG9uIFt0aGUgVU1SQ1AgcGFnZSBvZiBBUkMncyB3ZWJzaXRlXShodHRwczovL2FyYy51bWljaC5lZHUvdW1yY3AvKS4KCiMjIyBTaWduaW5nIHVwIGZvciB0aGUgVU1SQ1AKCldpdGhpbiB0aGF0IHNpdGUsIHRoZXJlIGlzIGFub3RoZXIgcGFnZSB0aGF0IEkgaGlnaGx5IHJlY29tbWVuZCBhcyBhIGdyZWF0IHBsYWNlIHRvIHN0YXJ0IC0gdGhlIFtVTVJDUCBSZXF1ZXN0aW5nIFJlc291cmNlcyBHdWlkZV0oaHR0cHM6Ly9hcmMudW1pY2guZWR1L3VtcmNwLXJlcXVlc3RpbmctcmVzb3VyY2VzLWd1aWRlLykuIFRoZXJlIHlvdSdsbCBmaW5kIGRldGFpbHMgYWJvdXQgdGhlIHNpZ251cCBwcm9jZXNzLiBBZnRlciBzaWduaW5nIHVwLCB5b3UnbGwgYmUgYWJsZSB0byB1c2Ugc29tZSBvZiB0aGUgbnVtZXJvdXMgY29tcHV0ZSBub2RlcyBhdmFpbGFibGUgdGhyb3VnaCBBUkMsIGFzIHdlbGwgYXMgdGhlIHZhcmlvdXMgc3RvcmFnZSB0aWVycyBkZXNjcmliZWQgYWJvdmUuCgo8YnI+CgohW10oaW1hZ2VzL01vZHVsZTAxX3N0ZXBzX2dldHRpbmdfVU1SQ1AucG5nKQoKPGJyPgoKPGRldGFpbHM+CjxzdW1tYXJ5PkFkZGl0aW9uYWwgUmVzb3VyY2VzIEF2YWlsYWJsZSBUaHJvdWdoIEhJVFMgUkNJPC9zdW1tYXJ5PgoKIVtdKGltYWdlcy9Nb2R1bGUwMV91bXJjcF9wbHVzX3VtcmNpX3Byb3ZpZGVzLnBuZykKCkluIGFkZGl0aW9uIHRvIHRoZSByZXNvdXJjZXMgcHJvdmlkZWQgdGhyb3VnaCB0aGUgVU1SQ1AsIHNvbWUgcmVzZWFyY2hlcnMgd2l0aGluIHRoZSBtZWRpY2FsIHN5c3RlbSB3aWxsIGhhdmUgYWRkaXRvbmFsIHJlc291cmNlcyBhdmFpbGFibGUgdGhyb3VnaCBVTSBIZWFsdGggSW5mb3JtYXRpb24gVGVjaG5vbG9neSAmIFNlcnZpY2VzIChISVRTKS4gVGhyb3VnaCBzdHJhdGVnaWMgaW52ZXN0bWVudHMgaW4gSGlnaCBQZXJmb3JtYW5jZSBDb21wdXRpbmcgYnkgTWljaGlnYW4gTWVkaWNpbmUsIGVsaWdpYmxlIHJlc2VhcmNoZXJzIGNhbiBlbmpveSBhZGRpdGlvbmFsIGFsbG9jYXRpb25zIGZvciB0aGUgZGVzY3JpYmVkIHJlc291cmNlcyAtIG1vc3Qgbm90YWJseSB1bmxpbWl0ZWQgRGF0YSBEZW4gc3RvcmFnZS4KCkluIHRoZSBkb2N1bWVudGF0aW9uIGZvciB0aGUgVU1SQ1AgYW5kIHRoZSBVTVJDSSwgeW91J2xsIHNlZSB0aGF0IHRoZXkgcmVjb21tZW5kIGZpcnN0IHVzaW5nIHRoZSBVTVJDUCByZXNvdXJjZXMgKGF2YWlsYWJsZSB0byBhbGwgdW5pdmVyc2l0eSByZXNlYXJjaGVycykgYW5kIHRoZW4gdHJhbnNpdGlvbmluZyB0byB0aGVzZSBhZGRpdGlvbmFsIEhJVFMgVU1SQ0kgcmVzb3VyY2VzIChhdmFpbGFibGUgdG8gTWljaGlnYW4gTWVkaWNpbmUgcmVzZWFyY2hlcnMpIHdoZW4gcG9zc2libGUuIEluIGFueSBjYXNlLCBzaW5jZSB0aGVzZSBhbGxvY2F0aW9ucyBhcmUgbWFuYWdlZCBieSBBUkMgZm9yIGFsbCB1bml2ZXJpc2l0eSByZXNlYXJjaGVycyAtIE1pY2hpZ2FuIE1lZGljbmUgb3Igb3RoZXJ3aXNlIC0geW91J2xsIGJlIHVzaW5nIHRoZSBzYW1lIGZvcm1zIGFuZCBwcm9jZWR1cmVzIHRvIHJlcXVlc3QgcmVzb3VyY2VzIGFuZCB1c2UgdGhlbS4gSG93ZXZlciwgdGhlIGJpbGxpbmcgZGV0YWlscyBtYXkgY2hhbmdlIGRlcGVuZGluZyBvbiB0aGlzIGVsaWdpYmlsaXR5LgoKW0xpbmsgdG8gSElUUyBwYWdlIG9uIFVNUkNJXShodHRwczovL2hpdHMubWVkaWNpbmUudW1pY2guZWR1L3Jlc2VhcmNoLWVkdWNhdGlvbi9yZXNlYXJjaC1jb21wdXRpbmctZGF0YS1zdG9yYWdlL3Jlc2VhcmNoLWNvbXB1dGluZy1wYWNrYWdlKQoKPC9kZXRhaWxzPgoKPGJyPgoKIyMjIEdyZWF0IExha2VzLCBBcm1pczIsIGFuZCBMaWdodGhvdXNlIENsdXN0ZXJzCgpUaGlzIG1vZHVsZSBvdmVyYWxsIGlzIHByaW1hcmlseSBmb2N1c2VkIG9uIHN0b3JhZ2UtcmVsYXRlZCB0b3BpY3MuIFdlJ3ZlIGJyaWVmbHkgbWVudGlvbmVkIHRoYXQgaW4gYWRkaXRpb24gdG8gc3RvcmFnZSByZXNvdXJjZXMsIEFSQyBhbHNvIHByb3ZpZGVzIGFjY2VzcyB0byBoaWdoLXBlcmZvcm1hbmNlIGNvbXB1dGluZyAoSFBDKSBoYXJkd2FyZSBhcyB3ZWxsLiBXaGlsZSBpbiB0aGlzIHdvcmtzaG9wIHdlJ2xsIGp1c3QgYmUgZm9jdXNpbmcgb24gb25lIG9mIHRoZW0sIGluIGZhY3QgdGhlcmUgYXJlIHNldmVyYWwgSFBDIGNsdXN0ZXJzIHRoYXQgYXJlIGF2YWlsYWJsZSB0byBVTWljaCByZXNlYXJjaGVycywgaW4gb3JkZXIgdG8gbWVldCB2YXJpb3VzIG5lZWRzLgoKV2hlbiBkaXNjdXNzaW5nIHJlc2VhcmNoIG5lZWRzLCBlc3BlY2lhbGx5IGluIGFudGljaXBhdGlvbiBvZiByZXF1ZXN0aW5nIFVNUkNQIHJlc291cmNlcyBhbmQgZmlsbGluZyBvdXQgdGhlIHJlcXVpcmVkIGZvcm0sIHdlIHNob3VsZCBkaXNjdXNzIGEgbGl0dGxlIGJpdCBhYm91dCB0aHJlZSBIUEMgb3B0aW9ucyBwcm92aWRlZCB0aHJvdWdoIEFSQzoKCi0gR3JlYXQgTGFrZXMKLSBBcm1pczIgKEhJUEFBLWFsaWduZWQpCi0gTGlnaHRob3VzZSAoUmVzZWFyY2hlci1vd25lZCBoYXJkd2FyZSkKCldlJ2xsIGJlIGRpc2N1c3NpbmcgR3JlYXQgTGFrZXMgYXQgbGVuZ3RoIHRocm91Z2hvdXQgdGhpcyB3b3Jrc2hvcCBhbmQgdXNpbmcgaXQgZm9yIG91ciBleGFtcGxlIGFuYWx5c2VzLiBXZSBjYW4gdGhpbmsgb2YgaXQgYXMgYSBnZW5lcmFsLXB1cnBvc2UgSFBDIGNsdXN0ZXIsIHdoaWNoIGlzIHN1aXRhYmxlIGZvciBtYW55IGRpZmZlcmVudCBraW5kcyBvZiByZXNlYXJjaC4KCkFybWlzMiBpcyBzaW1pbGFyIGluIGZlZWwgdG8gdGhlIEdyZWF0IExha2VzIGNsdXN0ZXIsIGV4Y2VwdCBpdCBpcyBjb25maWd1cmVkIHdpdGggc3BlY2lmaWMgc2VjdXJpdHkgbWVhc3VyZXMgaW4gcGxhY2UgdG8gZW5hYmxlIGFuYWx5c2lzIG9mIHNlbnNpdGl2ZSBkYXRhLCBzdWNoIGFzIGV4cG9ydC1jb250cm9sbGVkIG9yIEhJUEFBIHByb3RlY3RlZCBkYXRhLiAgV2hlbiBmaWxsaW5nIG91dCB0aGUgVU1SQ1AgZm9ybSwgeW91IGNhbiBtYWtlIHNlbGVjdGlvbnMgZm9yIHNlbnNpdGl2ZSBkYXRhIG5lZWRzLCB3aGljaCB3aWxsIHByb3ZpZGUgQ1BVIGhvdXJzIG9uIEFybWlzMiBhbmQgYXNzb2NpYXRlZCBzdG9yYWdlLiBXZSdsbCBzZWUgbGF0ZXIsIHRoYXQgd2UgaGF2ZSBmbGV4aWJpbGl0eSBpbiBob3cgd2UgYWxsb2NhdGUgcmVzb3VyY2VzIGJldHdlZW4gZS5nLiBHcmVhdCBMYWtlcyBhbmQgQXJtaXMyLgoKPk5vdGU6IFRoZXJlIGlzIGEgc2VwYXJhdGUsIHNlY3VyaXR5LWVuaGFuY2VkIFR1cmJvIGFsbG9jYXRpb24gdGhhdCBpcyBhbHNvIEhJUEFBIGFsaWduZWQgdGhhdCBzaG91bGQgYmUgdXNlZCB3aXRoIEFybWlzMi4KCkxpZ2h0aG91c2UgaXMgYWxzbyBzaW1pbGFyIGluIGZlZWwgdG8gdGhlIEdyZWF0IExha2VzIGNsdXN0ZXIsIGV4Y2VwdCBpdCBpcyBhIGNsdXN0ZXIgY29tcHJpc2VkIGVudGlyZWx5IG9mIHJlc2VhcmNoZXItb3duZWQgaGFyZHdhcmUuIENvbnRyYXN0aW5nIHRoaXMgd2l0aCBHcmVhdCBMYWtlcyB3aGVyZSB3ZSBhcmUgb25seSByZXNwb25zaWJsZSBmb3IgdGhlIGNvc3Qgb2YgdGhlIHJlc291cmNlcyB3ZSB1c2UsIG9uIExpZ2h0aG91c2UsIGEgcmVzZWFyY2hlciB3aWxsIGZ1bmQgdGhlIGVudGlyZXR5IG9mIHRoZSBoYXJkd2FyZSBhbmQgcmVjZWl2ZSAxMDAlIG9mIGl0cyBhdmFpbGFiaWxpdHkuIFRoaXMgY2FuIGJlIGEgZ29vZCBjaG9pY2UgZm9yIHJlc2VhcmNoZXJzIHdobyBhcmUgZXhwZWN0ZWQgdG8gaGF2ZSBuZWFyLWNvbnN0YW50IGNvbXB1dGUgdXNhZ2UgbmVlZHMsIG9yIHdobyByZXF1aXJlIGluc3RhbnQgYXZhaWxhYmlsaXR5IG9mIEhQQyByZXNvdXJjZXMuCgo8YnI+CgpNYWluIGlkZWFzOgoKIC0gUEkgbXVzdCBiZSB0aGUgb25lIHRvIGZpbGwgb3V0IGZvcm0KIC0gUEkgd2lsbCBhdXRvbWF0aWNhbGx5IGJlY29tZSBhbiBhZG1pbmlzdHJhdG9yCiAtIE90aGVycyBjYW4gYmVjb21lIGFkbWluaXN0cmF0b3JzIChsYWIgbWFuYWdlcikgb3IgbWVtYmVycwoKPGJyPgoKIyMjIEFkbWluaXN0cmF0b3JzIHZzIFVzZXJzCgp8ICAgICAgICAgICAgICB8IENoYW5nZSBBbGxvY2F0aW9ucyB8IEFkZC9SZW1vdmUgVXNlcnMgfCBVc2UgR0wgY29tcHV0ZSB0aW1lIHwgUmVhZC9Xcml0ZSBhY2Nlc3MgdG8gVHVyYm8gfCBHbG9idXMgQWRtaW4gfAp8IC0tLS0tLS0tLS0tLSB8Oi0tLS0tLS0tLS0tLS0tLS0tLSB8Oi0tLS0tLS0tLS0tLS0tLS0gfDotLS0tLS0tLS0tLS0tLS0tLS0tIHw6LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gfDotLS0tLS0tLS0tLS0tIHwKfCBQSSAgICAgICAgICAgfCDinIUgICAgICAgICAgICAgICAgICB8IOKchSAgICAgICAgICAgICAgICB8IOKPsyAgICAgICAgICAgICAgICAgICB8IOKPsyAgICAgICAgICAgICAgICAgICAgICAgICAgfCDinIUgICAgICAgICAgICAgfAp8IExhYiBNYW5hZ2VyICB8IOKchSAgICAgICAgICAgICAgICAgIHwg4pyFICAgICAgICAgICAgICAgIHwg4o+zICAgICAgICAgICAgICAgICAgIHwg4o+zICAgICAgICAgICAgICAgICAgICAgICAgICB8IOKchSAgICAgICAgICAgICB8CnwgR3JhZCBTdHVkZW50IHwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICB8IOKchSAgICAgICAgICAgICAgICAgICB8IOKchSAgICAgICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgIHwKCj4gTGVnZW5kOgo+Cj4g4pyFID0gRnJlcXVlbnQKPgo+IOKPsyA9IE9jY2FzaW9uYWwKCjxicj4KCiMjIyBSZXNvdXJjZSBNYW5hZ2VtZW50IFBvcnRhbAoKIVtdKGltYWdlcy9Nb2R1bGUwMV9yZXNvdXJjZV9tYW5hZ2VtZW50X3BvcnRhbC5wbmcpCgpBIGtleSBwYXJ0IG9mIGhvdyB3ZSB3aWxsIG1hbmFnZSBvdXIgQVJDIHJlc291cmNlcyBpcyB0aHJvdWdoIHRoZWlyIFJlc291cmNlIE1hbmFnZW1lbnQgUG9ydGFsLCBzaG93biBoZXJlLiAKClRoaXMgcG9ydGFsIGNhbiBiZSBmb3VuZCBhdCBbaHR0cHM6Ly9wb3J0YWwuYXJjLnVtaWNoLmVkdV0oaHR0cHM6Ly9wb3J0YWwuYXJjLnVtaWNoLmVkdSkuCgpMZXQncyBub3QgZ28gdGhlcmUganVzdCB5ZXQsIGJ1dCBkaXNjdXNzIHdoYXQgd2Ugc2VlIGluIHRoaXMgc2NyZWVuc2hvdCwgYW5kIHRoZW4gbW92ZSBvbiB0byB0aGUgZXhlcmNpc2UuIFdlJ2xsIGxlYXJuIGFib3V0IHNvbWUgb2YgdGhlIGRpZmZlcmVuY2VzIHRoYXQgd2UgbWF5IHNlZSBkZXBlbmRpbmcgb24gb3VyIGN1cnJlbnQgc3RhdHVzIGFuZCBleGlzdGluZyByZXNvdXJjZXMsIGFuZCB3ZSdsbCBsZWFybiB0aGF0IHRoZXJlIGFyZSBzb21lIGRpZmZlcmVuY2VzIGluIHRoZSBiZXN0IHdheSB0byByZXF1ZXN0IFVNUkNQIHJlc291cmNlcyBkZXBlbmRpbmcgb24gdGhlc2UgZGV0YWlscy4KCjxicj4KCgojIyBFeGVyY2lzZTogTWFrZSBhIEdhbWUgUGxhbiBmb3IgVU1SQ1AKCkluIHRoaXMgZXhlcmNpc2Ugd2Ugd2lsbCBkZXRlcm1pbmUgdGhlIG5lZWRzIGZvciBVTVJDUCBlbnJvbGxtZW50IGJ5IGF1ZGllbmNlICYgdGhlaXIgUElzLgoKVGhlcmUgYXJlIHR3byB2aWRlbyBsaW5rcyBiZWxvdy4gVGhlcmUncyBhIGRlY2VudCBhbW91bnQgb2Ygb3ZlcmxhcCBpbiB0aGUgY29udGVudCwgYW5kIHRoZSBtYWluIGlkZWFzIGFyZSBwcmV0dHkgc2ltaWxhci4gSW4gZWl0aGVyIGNhc2UsIHdlIHdpbGwgYmUgZmlsbGluZyBvdXQgdGhlIFVNUkNQIHdlYiBmb3JtcyBhcyBzaG93biBpbiB0aGUgdmlkZW9zLiBEZXBlbmRpbmcgb24gb3VyIGN1cnJlbnQgc3RhdHVzIHRob3VnaCwgd2UgbWF5IGhhdmUgZGlmZmVyZW50IG9wdGltYWwgc3RhcnRpbmcgcG9pbnRzIGFuZCBkaWZmZXJlbnQgdGhpbmdzIHRvIGNvbnNpZGVyLgoKPGJyPgoKW1VNUkNQIEhvdyB0byBFbnJvbGwgLSBOZXcgdG8gQVJDIFNlcnZpY2VzXShodHRwczovL3d3dy5taXZpZGVvLml0LnVtaWNoLmVkdS9tZWRpYS90LzFfaThqNXB1anovMTgxODYwNTYxKQoKPGJyPgoKW1VNUkNQIEhvdyB0byBFbnJvbGwgLSBFeGlzdGluZyBPd25lciBvZiBBUkMgU2VydmljZXNdKGh0dHBzOi8vd3d3Lm1pdmlkZW8uaXQudW1pY2guZWR1L21lZGlhL3QvMV96bmY2eWdrMC8xODE4NjA1NjEpCgo8YnI+Cjxicj4KCnwgW1ByZXZpb3VzIGxlc3Nvbl0oTW9kdWxlMDFfV2FybWluZ19VcC5odG1sKSB8IFtUb3Agb2YgdGhpcyBsZXNzb25dKCN0b3ApIHwgW05leHQgbGVzc29uXShNb2R1bGUwMl90cmFuc2ZlcnJpbmdfZGF0YV9nbG9idXMuaHRtbCkgfAp8IDotLS0gfCA6LS0tLTogfCAtLS06IHwK