Introduction
SQLite is a popular software library that provides a relational database management system (RDBMS) that is designed to be embedded into software applications. It is a self-contained, serverless, zero-configuration, transactional SQL database engine. SQLite is a file-based database system, which means that the entire database is stored in a single file on the file system of the host computer.
SQLite supports most of the standard SQL syntax and provides a lightweight and fast alternative to larger, more complex database systems. It is a widely used database technology in embedded systems, mobile applications, desktop software, and web applications. SQLite is often used for small to medium-sized applications or as a local data store for larger applications that use a more powerful database server for remote data storage and retrieval.
Serverless Architecture
When we say that SQLite is “serverless”, it means that it doesn’t require a separate server process to be running in order to access and manipulate the data in the database. Instead, SQLite is designed to be embedded directly into the application that uses it. This means that the database operations are performed directly by the application, without the need for a separate server process to be running in the background.
Additionally, SQLite is a “file-based” database system, which means that the entire database is stored in a single file on the file system of the host computer. This makes it easy to move the database between different machines or to back it up, since it’s just a matter of copying the file. The file-based approach also makes it easy to set up and use SQLite, since there is no need to install or configure a separate database server or create a separate database instance.
SQLite being serverless and file-based makes it a lightweight, self-contained, and easy-to-use database system that can be embedded into a wide range of applications, without the need for a separate database server or complex setup.
SQLite can be integrated into information systems through:
- Language-specific APIs
- JDBC for Java applications
- Python’s sqlite3 module
- Node.js adapters
- Embedded Applications
- Mobile applications
- Edge computing systems
- IoT devices
- Development Tools
- GUI administration tools
- Command-line utilities
- ORM frameworks
Creating a New Database
Creating a new database is SQLite is simple: open a database file that does not exist and SQLite will create a new database with that file name.
% sqlite3 customerDB.sqlitedb
SQLite database files can have any extension, but .sqlitedb and .db are most common.
Worked Example
In the worked example below, we create a new database using a creation script through the management console for SQLite. The script is generic and standard SQL, so it will work just as well on any other relational database, including MySQL, Oracle, and SQL Server. After creation of the database, sample data is added to the database via the script, although this could have also been done via imports of CSV files. Finally, we execute a set of queries against the sample data in the database.
Create Database
Download the organization database creation script: create-orgdb.sql. A script is a plain text file containing SQL statements.
Using either the command line tools sqlite3 or the cloud version of SQLite, source (run) the script to execute all of the SQL statements in the script. This will create the database with sample data.
Inspect the tables in the database either by studying the SQL creation code or listing the tables. It is a useful practice to visualize the database structure by drawing an Entity-Relationship or UML diagram.
The tutorial below will show you how to create the database, connect to it, and inspect the tables. Watch it only after you attempted to do this yourself. It assumes that you have the SQLite tools installed locally on your computer.
Build Queries
Once you are familiar with the database, use the interactive command line tool to build SQL queries for the following questions:
Query 1
Find the distinct number of workers who work in the HR department and who earn more than ₹225,000.
Click for Solution
select distinct count(*) as 'NumWorkers'
from Worker as w
where w.department = 'HR'
and w.salary > 250000;
Query 2
Find the last name and title of all workers and the department they work in who earn less than the average salary.
Click for Solution
select last_name, worker_title
from Worker AS w JOIN Title AS t ON (w.WORKER_ID = t.WORKER_REF_ID)
and w.salary < (select avg(salary) from Worker);
Query 3
What is the average salary paid for all workers in each department? List the department, the average salary for the department, and the number of workers in each department. Name the average column ‘AvgSal’ and the number of workers column to ‘Num’.
Click for Solution
select department, AVG(salary) as 'AvgSalary', count(*) as 'NumWorkers'
from Worker
group by department;
Query 4
What is the total compensation for each worker (salary and bonus) on a per monthly basis? List the name of the worker, their title, and the their monthly compensation (annual compensation divided by 12). Change the header for compensation to ‘MonthlyComp’ and round it to the nearest whole number.
Click for Solution
select last_name, ((salary + bonus_amount) / 12) as 'MonthlyComp'
from Worker as w join Bonus as b on (w.WORKER_ID = b.WORKER_REF_ID)
Query 5
List the full names of all workers in all capital letters who did not get a bonus.
Click for Solution
select upper(last_name || ", " || first_name) as 'FullName'
from Worker
where worker_id not in (select worker_ref_id from Bonus)
order by last_name;
Query 6
What are the full names of all workers who have ‘Manager’ in their title. Do not “hard code” the titles; use string searching.
Click for Solution
select upper(last_name || ", " || first_name) as 'FullName', t.WORKER_TITLE
from Worker w, Title t
WHERE w.WORKER_ID = t.WORKER_REF_ID
and t.WORKER_TITLE LIKE '%Manager%';
Tutorial
SQLite CLI
SQLite’s command-line interface (CLI) provides direct access to SQLite’s core functionality through a terminal-based interface. While graphical tools exist, understanding the CLI is fundamental for database administrators and developers requiring programmatic database interactions.
The SQLite CLI can be initiated in two distinct modes. For transient operations:
The % above indicates that the command is typed from your operating system’s command shell or a terminal.
This creates an ephemeral, in-memory database. For persistent storage, specify a database file:
Once you have launched the SQLite CLI, you are in the CLI’s command shell and no longer the operating system’s command shell. We indicate the SQLite CLI command shell with >. Note that SQLite CLI commands always start with a period (.). Any SQL statement would not start with a period.
Session termination is accomplished via the .exit
meta-command:
Database Administration Commands
SQLite provides meta-commands for database administration:
/* List all attached databases */
>.databases
main: C:\path\to\library.db r/w
/* Display available tables */
>.tables
BOOKS AUTHORS BORROWERS
/* Examine schema definitions */
>.schema
SQL Scripts
To execute a SQLite “script”, i.e., a sequence of SQL statements separated by semi-colons and contained in a text file, from the command-line using the sqlite3 program (download and install from sqlite.com), you can either feed the script to the sqlite3 management console program or use the .read
command within the sqlite3 shell.
1. Feeding the script to sqlite3 using redirection
You can pipe the contents of your SQL script file directly to the sqlite3 program. For example, if you have a script named “my_script.sql”, you can execute it like this:
sqlite3 my_database.db < my_script.sql
This opens the specified database (“my_database.db”), reads the SQL commands from the script file (separated by semi-colons), and executes them in sequence.
2. Using Get-Content (PowerShell)
In PowerShell on Windows, you can use Get-Content
to read the script and then pipe the output to sqlite3:
Get-Content my_script.sql -Raw | sqlite3 my_database.db
This opens the database and executes the SQL script.
3. Using the .read command within the sqlite3 shell
Start the sqlite3 management console shell by open a terminal or command prompt and running sqlite3 my_database.db
to connect to your database (“my_database.db”). Then use the .read SQLite management command inside the sqlite3 management shell to execute the script.
sqlite3 my_database.db
sqlite> .read my_script.sql
This opens the database “my_database.db”, then reads and executes the SQL commands from text file “my_script.sql”.
Hints
- Make sure to specify the database file when using the command-line interface (e.g.,
sqlite3 my_database.db
)
- Ensure that your SQL script file is accessible by the sqlite3 program
- Commands starting with a period (.) are special commands within the sqlite3 shell and are management commands and not SQL statements
- The SQL script file must be a plain text file containing valid SQL commands separated by semicolons
Summary
Management consoles, available for every database, are an essential tool for database development and administration. Some are command-line oriented and some have graphical user interfaces. Some even allow database design through integrated diagramming tools.
Aside from allowing us to create databases and perform ad hoc queries, the provide a number of additional benefits.
Centralized control: A management console provides a centralized interface for managing and monitoring a database, allowing administrators to configure and monitor the database more easily and efficiently.
Efficient performance monitoring: A management console provides real-time monitoring of the database’s performance, enabling administrators to quickly identify and troubleshoot performance issues. This can help improve the overall performance of the database, reducing downtime and improving the end user experience.
Enhanced security: A management console can help to enhance the security of a database by providing tools to manage users and permissions, set up auditing, and monitor the database for suspicious activity. This can help prevent unauthorized access to the database and protect sensitive data.
Automated backup and recovery: Many management consoles include tools for automated backup and recovery of the database, helping to ensure data is protected in the event of a disaster or other unforeseen circumstances.
Simplified administration: A management console can simplify database administration by providing a graphical user interface that simplifies complex database tasks. This can help reduce the need for specialized skills or knowledge, making it easier for a wider range of staff to manage and maintain the database.
Overall, a management console for a database can help streamline database management, facilitate ad hoc querying, improve performance and security, and simplify administration, making it an essential tool for database development.
LS0tCnRpdGxlOiAiSW50ZXJhY3Rpbmcgd2l0aCBTUUxpdGUgdGhyb3VnaCBDb25zb2xlIGFuZCBTY3JpcHRzIgpwYXJhbXM6CiAgY2F0ZWdvcnk6IDcwCiAgbnVtYmVyOiA4MDMKICB0aW1lOiA2MAogIGxldmVsOiBpbnRlcm1lZGlhdGUKICB0YWdzOiAic3FsaXRlLHNjcmlwdHMiCiAgZGVzY3JpcHRpb246ICJFeHBsYWlucyBob3cgdG8gY3JlYXRlIGRhdGFiYXNlcyB0aHJvdWdoIFNRTGl0ZSBTUUwgc2NyaXB0cy4gU2hvd3MKICAgICAgICAgICAgICAgIGhvdyB0byBpbnN0YWxsIGFuZCB1c2UgbWFuYWdlbWVudCBjb25zb2xlIHRocm91Z2ggdGVybWluIHNoZWxsLiIKZGF0ZTogIjxzbWFsbD5gciBTeXMuRGF0ZSgpYDwvc21hbGw+IgphdXRob3I6ICI8c21hbGw+TWFydGluIFNjaGVkbGJhdWVyPC9zbWFsbD4iCmVtYWlsOiAibS5zY2hlZGxiYXVlckBuZXUuZWR1IgphZmZpbGl0YXRpb246ICJOb3J0aGVhc3Rlcm4gVW5pdmVyc2l0eSIKb3V0cHV0OiAKICBib29rZG93bjo6aHRtbF9kb2N1bWVudDI6CiAgICB0b2M6IHRydWUKICAgIHRvY19kZXB0aDogMwogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICB0aGVtZTogc3BhY2VsYWIKICAgIGhpZ2hsaWdodDogdGFuZ28KLS0tCgotLS0KdGl0bGU6ICI8c21hbGw+YHIgcGFyYW1zJGNhdGVnb3J5YC5gciBwYXJhbXMkbnVtYmVyYDwvc21hbGw+PGJyLz48c3BhbiBzdHlsZT0nY29sb3I6ICMyRTQwNTM7IGZvbnQtc2l6ZTogMC45ZW0nPmByIHJtYXJrZG93bjo6bWV0YWRhdGEkdGl0bGVgPC9zcGFuPiIKLS0tCgpgYGB7ciBjb2RlPXhmdW46OnJlYWRfdXRmOChwYXN0ZTAoaGVyZTo6aGVyZSgpLCcvUi9faW5zZXJ0MkRCLlInKSksIGluY2x1ZGUgPSBGQUxTRX0KYGBgCgojIyBJbnRyb2R1Y3Rpb24KClNRTGl0ZSBpcyBhIHBvcHVsYXIgc29mdHdhcmUgbGlicmFyeSB0aGF0IHByb3ZpZGVzIGEgcmVsYXRpb25hbCBkYXRhYmFzZSBtYW5hZ2VtZW50IHN5c3RlbSAoUkRCTVMpIHRoYXQgaXMgZGVzaWduZWQgdG8gYmUgZW1iZWRkZWQgaW50byBzb2Z0d2FyZSBhcHBsaWNhdGlvbnMuIEl0IGlzIGEgc2VsZi1jb250YWluZWQsIHNlcnZlcmxlc3MsIHplcm8tY29uZmlndXJhdGlvbiwgdHJhbnNhY3Rpb25hbCBTUUwgZGF0YWJhc2UgZW5naW5lLiBTUUxpdGUgaXMgYSBmaWxlLWJhc2VkIGRhdGFiYXNlIHN5c3RlbSwgd2hpY2ggbWVhbnMgdGhhdCB0aGUgZW50aXJlIGRhdGFiYXNlIGlzIHN0b3JlZCBpbiBhIHNpbmdsZSBmaWxlIG9uIHRoZSBmaWxlIHN5c3RlbSBvZiB0aGUgaG9zdCBjb21wdXRlci4KClNRTGl0ZSBzdXBwb3J0cyBtb3N0IG9mIHRoZSBzdGFuZGFyZCBTUUwgc3ludGF4IGFuZCBwcm92aWRlcyBhIGxpZ2h0d2VpZ2h0IGFuZCBmYXN0IGFsdGVybmF0aXZlIHRvIGxhcmdlciwgbW9yZSBjb21wbGV4IGRhdGFiYXNlIHN5c3RlbXMuIEl0IGlzIGEgd2lkZWx5IHVzZWQgZGF0YWJhc2UgdGVjaG5vbG9neSBpbiBlbWJlZGRlZCBzeXN0ZW1zLCBtb2JpbGUgYXBwbGljYXRpb25zLCBkZXNrdG9wIHNvZnR3YXJlLCBhbmQgd2ViIGFwcGxpY2F0aW9ucy4gU1FMaXRlIGlzIG9mdGVuIHVzZWQgZm9yIHNtYWxsIHRvIG1lZGl1bS1zaXplZCBhcHBsaWNhdGlvbnMgb3IgYXMgYSBsb2NhbCBkYXRhIHN0b3JlIGZvciBsYXJnZXIgYXBwbGljYXRpb25zIHRoYXQgdXNlIGEgbW9yZSBwb3dlcmZ1bCBkYXRhYmFzZSBzZXJ2ZXIgZm9yIHJlbW90ZSBkYXRhIHN0b3JhZ2UgYW5kIHJldHJpZXZhbC4KCiMjIFNlcnZlcmxlc3MgQXJjaGl0ZWN0dXJlCgpXaGVuIHdlIHNheSB0aGF0IFNRTGl0ZSBpcyAic2VydmVybGVzcyIsIGl0IG1lYW5zIHRoYXQgaXQgZG9lc24ndCByZXF1aXJlIGEgc2VwYXJhdGUgc2VydmVyIHByb2Nlc3MgdG8gYmUgcnVubmluZyBpbiBvcmRlciB0byBhY2Nlc3MgYW5kIG1hbmlwdWxhdGUgdGhlIGRhdGEgaW4gdGhlIGRhdGFiYXNlLiBJbnN0ZWFkLCBTUUxpdGUgaXMgZGVzaWduZWQgdG8gYmUgZW1iZWRkZWQgZGlyZWN0bHkgaW50byB0aGUgYXBwbGljYXRpb24gdGhhdCB1c2VzIGl0LiBUaGlzIG1lYW5zIHRoYXQgdGhlIGRhdGFiYXNlIG9wZXJhdGlvbnMgYXJlIHBlcmZvcm1lZCBkaXJlY3RseSBieSB0aGUgYXBwbGljYXRpb24sIHdpdGhvdXQgdGhlIG5lZWQgZm9yIGEgc2VwYXJhdGUgc2VydmVyIHByb2Nlc3MgdG8gYmUgcnVubmluZyBpbiB0aGUgYmFja2dyb3VuZC4KCkFkZGl0aW9uYWxseSwgU1FMaXRlIGlzIGEgImZpbGUtYmFzZWQiIGRhdGFiYXNlIHN5c3RlbSwgd2hpY2ggbWVhbnMgdGhhdCB0aGUgZW50aXJlIGRhdGFiYXNlIGlzIHN0b3JlZCBpbiBhIHNpbmdsZSBmaWxlIG9uIHRoZSBmaWxlIHN5c3RlbSBvZiB0aGUgaG9zdCBjb21wdXRlci4gVGhpcyBtYWtlcyBpdCBlYXN5IHRvIG1vdmUgdGhlIGRhdGFiYXNlIGJldHdlZW4gZGlmZmVyZW50IG1hY2hpbmVzIG9yIHRvIGJhY2sgaXQgdXAsIHNpbmNlIGl0J3MganVzdCBhIG1hdHRlciBvZiBjb3B5aW5nIHRoZSBmaWxlLiBUaGUgZmlsZS1iYXNlZCBhcHByb2FjaCBhbHNvIG1ha2VzIGl0IGVhc3kgdG8gc2V0IHVwIGFuZCB1c2UgU1FMaXRlLCBzaW5jZSB0aGVyZSBpcyBubyBuZWVkIHRvIGluc3RhbGwgb3IgY29uZmlndXJlIGEgc2VwYXJhdGUgZGF0YWJhc2Ugc2VydmVyIG9yIGNyZWF0ZSBhIHNlcGFyYXRlIGRhdGFiYXNlIGluc3RhbmNlLgoKU1FMaXRlIGJlaW5nIHNlcnZlcmxlc3MgYW5kIGZpbGUtYmFzZWQgbWFrZXMgaXQgYSBsaWdodHdlaWdodCwgc2VsZi1jb250YWluZWQsIGFuZCBlYXN5LXRvLXVzZSBkYXRhYmFzZSBzeXN0ZW0gdGhhdCBjYW4gYmUgZW1iZWRkZWQgaW50byBhIHdpZGUgcmFuZ2Ugb2YgYXBwbGljYXRpb25zLCB3aXRob3V0IHRoZSBuZWVkIGZvciBhIHNlcGFyYXRlIGRhdGFiYXNlIHNlcnZlciBvciBjb21wbGV4IHNldHVwLgoKU1FMaXRlIGNhbiBiZSBpbnRlZ3JhdGVkIGludG8gaW5mb3JtYXRpb24gc3lzdGVtcyB0aHJvdWdoOgoKMS4gICoqTGFuZ3VhZ2Utc3BlY2lmaWMgQVBJcyoqCiAgICAtICAgSkRCQyBmb3IgSmF2YSBhcHBsaWNhdGlvbnMKICAgIC0gICBQeXRob24ncyBzcWxpdGUzIG1vZHVsZQogICAgLSAgIE5vZGUuanMgYWRhcHRlcnMKMi4gICoqRW1iZWRkZWQgQXBwbGljYXRpb25zKioKICAgIC0gICBNb2JpbGUgYXBwbGljYXRpb25zCiAgICAtICAgRWRnZSBjb21wdXRpbmcgc3lzdGVtcwogICAgLSAgIElvVCBkZXZpY2VzCjMuICAqKkRldmVsb3BtZW50IFRvb2xzKioKICAgIC0gICBHVUkgYWRtaW5pc3RyYXRpb24gdG9vbHMKICAgIC0gICBDb21tYW5kLWxpbmUgdXRpbGl0aWVzCiAgICAtICAgT1JNIGZyYW1ld29ya3MKCiMjIEluc3RhbGxpbmcgU1FMaXRlIENvbW1hbmQgTGluZSBUb29scwoKVGhlIHRvb2xzIGJlbG93IGRvIG5vdCBuZWVkIHRvIGJlIGluc3RhbGxlZCB3aGVuIGFjY2Vzc2luZyBhIFNRTGl0ZSBkYXRhYmFzZSBmcm9tIGFuIGFwcGxpY2F0aW9uIHdyaXR0ZW4gaW4gSmF2YSwgQysrLCBSLCBQeXRob24sIGFuZCBtb3N0IG90aGVyIGxhbmd1YWdlcy4gVGhlc2UgbGFuZ3VhZ2UgaW5jbHVkZSBhIHBhY2thZ2Ugb3IgbGlicmFyeSB0aGF0IGNvbnRhaW5zIGFsbCB0aGUgY29kZSBuZWNlc3NhcnkgdG8gYWNjZXNzIGEgU1FMaXRlIGRhdGFiYXNlLgoKSG93ZXZlciwgdG8gcnVuIHNjcmlwdHMsIHlvdSBtdXN0IGluc3RhbGwgdGhlIGNvbW1hbmQgbGluZSB0b29scy4gT2YgY291cnNlLCB5b3UgY2FuIGFjY2VzcyB0aGUgc2FtZSBkYXRhYmFzZSBmcm9tIGFuIGFwcGxpY2F0aW9uLCBSIHByb2dyYW1zLCBSIE5vdGVib29rcywgYW5kIHRoZSBjb21tYW5kIGxpbmUuIFRoaXMgaXMgb2Z0ZW4gdXNlZnVsIHRvIGluc3BlY3QgYSBkYXRhYmFzZSB0aGF0J3MgY3JlYXRlZCBieSBhbiBhcHBsaWNhdGlvbi4KClRoZSBwcm9jZXNzIG9mIGluc3RhbGxpbmcgU1FMaXRlIGNhbiB2YXJ5IGRlcGVuZGluZyBvbiB5b3VyIG9wZXJhdGluZyBzeXN0ZW0gYW5kIGhvdyB5b3UgcGxhbiB0byB1c2UgaXQuIEhlcmUgYXJlIHNvbWUgZ2VuZXJhbCBzdGVwcyB0byBmb2xsb3c6CgojIyMgSW5zdGFsbGluZyBTUUxpdGUgb24gV2luZG93cwoKLSAgIEdvIHRvIHRoZSBTUUxpdGUgZG93bmxvYWQgcGFnZTogPGh0dHBzOi8vd3d3LnNxbGl0ZS5vcmcvZG93bmxvYWQuaHRtbD4KLSAgIFVuZGVyIHRoZSAiUHJlY29tcGlsZWQgQmluYXJpZXMgZm9yIFdpbmRvd3MiIHNlY3Rpb24sIGRvd25sb2FkIHRoZSBhcHByb3ByaWF0ZSB2ZXJzaW9uIG9mIFNRTGl0ZSBmb3IgeW91ciBXaW5kb3dzIG9wZXJhdGluZyBzeXN0ZW0gKDMyLWJpdCBvciA2NC1iaXQpLgotICAgVW56aXAgdGhlIGRvd25sb2FkZWQgZmlsZSBhbmQgZXh0cmFjdCB0aGUgY29udGVudHMgdG8gYSBkaXJlY3Rvcnkgb24geW91ciBjb21wdXRlci4KLSAgIEFkZCB0aGUgZGlyZWN0b3J5IHdoZXJlIHlvdSBleHRyYWN0ZWQgU1FMaXRlIHRvIHRoZSBzeXN0ZW0ncyBQQVRIIGVudmlyb25tZW50IHZhcmlhYmxlLgoKIyMjIEluc3RhbGxpbmcgU1FMaXRlIG9uIE1hYwoKLSAgIEluc3RhbGwgSG9tZWJyZXcsIGlmIHlvdSBkb24ndCBoYXZlIGl0IGFscmVhZHksIGJ5IGZvbGxvd2luZyB0aGUgaW5zdHJ1Y3Rpb25zIG9uIHRoZSBIb21lYnJldyB3ZWJzaXRlOiA8aHR0cHM6Ly9icmV3LnNoLz4KLSAgIE9wZW4gYSB0ZXJtaW5hbCB3aW5kb3cgYW5kIHJ1biB0aGUgZm9sbG93aW5nIGNvbW1hbmQ6IGJyZXcgaW5zdGFsbCBzcWxpdGUKLSAgIFdhaXQgZm9yIEhvbWVicmV3IHRvIGRvd25sb2FkIGFuZCBpbnN0YWxsIFNRTGl0ZS4KCiMjIyBJbnN0YWxsaW5nIFNRTGl0ZSBvbiBMaW51eAoKLSAgIE9wZW4gYSB0ZXJtaW5hbCB3aW5kb3cgYW5kIHJ1biB0aGUgZm9sbG93aW5nIGNvbW1hbmQgdG8gdXBkYXRlIHRoZSBwYWNrYWdlIGxpc3Q6CgogICAgW3N1ZG8gYXB0LWdldCB1cGRhdGVde3N0eWxlPSJmb250LWZhbWlseTpDb3VyaWVyIn0KCi0gICBSdW4gdGhlIGZvbGxvd2luZyBjb21tYW5kIHRvIGluc3RhbGwgU1FMaXRlOgoKICAgIFtzdWRvIGFwdC1nZXQgaW5zdGFsbCBzcWxpdGUzXXtzdHlsZT0iZm9udC1mYW1pbHk6Q291cmllciJ9CgotICAgV2FpdCBmb3IgdGhlIGluc3RhbGxhdGlvbiB0byBjb21wbGV0ZS4KCkFmdGVyIGluc3RhbGxhdGlvbiwgeW91IGNhbiBzdGFydCB1c2luZyBTUUxpdGUgYnkgcnVubmluZyB0aGUgW3NxbGl0ZTNde3N0eWxlPSJmb250LWZhbWlseTpDb3VyaWVyIn0gY29tbWFuZCBpbiB5b3VyIHRlcm1pbmFsIG9yIGNvbW1hbmQgcHJvbXB0LiBUaGlzIHdpbGwgbGF1bmNoIHRoZSBTUUxpdGUgc2hlbGwsIHdoZXJlIHlvdSBjYW4gY3JlYXRlLCBvcGVuLCBhbmQgbWFuaXB1bGF0ZSBTUUxpdGUgZGF0YWJhc2VzLgoKIyMjIENsb3VkIFNRTGl0ZQoKQXMgYW4gYWx0ZXJuYXRpdmUgdG8gaW5zdGFsbGluZyBTUUxpdGUgbG9jYWxseSwgeW91IGNhbiB1cGxvYWQgU1FMaXRlIGRhdGFiYXNlIGZpbGVzIHRvIFtzcWxpdGVvbmxpbmUuY29tXShodHRwOi8vc3FsaXRlb25saW5lLmNvbSksIG9yLCB1c2UgW3NxbGl0ZW9ubGluZS5jb21dKGh0dHA6Ly9zcWxpdGVvbmxpbmUuY29tKSB0byBjcmVhdGUgZGF0YWJhc2VzLCBydW4gc2NyaXB0cywgYW5kIGRvd25sb2FkIGRhdGFiYXNlIGZpbGVzLgoKIyMgQ3JlYXRpbmcgYSBOZXcgRGF0YWJhc2UKCkNyZWF0aW5nIGEgbmV3IGRhdGFiYXNlIGlzIFNRTGl0ZSBpcyBzaW1wbGU6IG9wZW4gYSBkYXRhYmFzZSBmaWxlIHRoYXQgZG9lcyBub3QgZXhpc3QgYW5kIFNRTGl0ZSB3aWxsIGNyZWF0ZSBhIG5ldyBkYXRhYmFzZSB3aXRoIHRoYXQgZmlsZSBuYW1lLgoKWyUgc3FsaXRlMyBjdXN0b21lckRCLnNxbGl0ZWRiXXtzdHlsZT0iZm9udC1mYW1pbHk6Q291cmllciJ9CgpTUUxpdGUgZGF0YWJhc2UgZmlsZXMgY2FuIGhhdmUgYW55IGV4dGVuc2lvbiwgYnV0ICouc3FsaXRlZGIqIGFuZCAqLmRiKiBhcmUgbW9zdCBjb21tb24uCgojIyBXb3JrZWQgRXhhbXBsZQoKSW4gdGhlIHdvcmtlZCBleGFtcGxlIGJlbG93LCB3ZSBjcmVhdGUgYSBuZXcgZGF0YWJhc2UgdXNpbmcgYSBjcmVhdGlvbiBzY3JpcHQgdGhyb3VnaCB0aGUgbWFuYWdlbWVudCBjb25zb2xlIGZvciBTUUxpdGUuIFRoZSBzY3JpcHQgaXMgZ2VuZXJpYyBhbmQgc3RhbmRhcmQgU1FMLCBzbyBpdCB3aWxsIHdvcmsganVzdCBhcyB3ZWxsIG9uIGFueSBvdGhlciByZWxhdGlvbmFsIGRhdGFiYXNlLCBpbmNsdWRpbmcgTXlTUUwsIE9yYWNsZSwgYW5kIFNRTCBTZXJ2ZXIuIEFmdGVyIGNyZWF0aW9uIG9mIHRoZSBkYXRhYmFzZSwgc2FtcGxlIGRhdGEgaXMgYWRkZWQgdG8gdGhlIGRhdGFiYXNlIHZpYSB0aGUgc2NyaXB0LCBhbHRob3VnaCB0aGlzIGNvdWxkIGhhdmUgYWxzbyBiZWVuIGRvbmUgdmlhIGltcG9ydHMgb2YgQ1NWIGZpbGVzLiBGaW5hbGx5LCB3ZSBleGVjdXRlIGEgc2V0IG9mIHF1ZXJpZXMgYWdhaW5zdCB0aGUgc2FtcGxlIGRhdGEgaW4gdGhlIGRhdGFiYXNlLgoKIyMjIENyZWF0ZSBEYXRhYmFzZQoKRG93bmxvYWQgdGhlIG9yZ2FuaXphdGlvbiBkYXRhYmFzZSBjcmVhdGlvbiBzY3JpcHQ6IFtjcmVhdGUtb3JnZGIuc3FsXShjcmVhdGUtb3JnZGIuc3FsKS4gQSBzY3JpcHQgaXMgYSBwbGFpbiB0ZXh0IGZpbGUgY29udGFpbmluZyBTUUwgc3RhdGVtZW50cy4KClVzaW5nIGVpdGhlciB0aGUgY29tbWFuZCBsaW5lIHRvb2xzICpzcWxpdGUzKiBvciB0aGUgW2Nsb3VkIHZlcnNpb24gb2YgU1FMaXRlXShodHRwOi8vc3FsaXRlb25saW5lLmNvbSksIHNvdXJjZSAocnVuKSB0aGUgc2NyaXB0IHRvIGV4ZWN1dGUgYWxsIG9mIHRoZSBTUUwgc3RhdGVtZW50cyBpbiB0aGUgc2NyaXB0LiBUaGlzIHdpbGwgY3JlYXRlIHRoZSBkYXRhYmFzZSB3aXRoIHNhbXBsZSBkYXRhLgoKSW5zcGVjdCB0aGUgdGFibGVzIGluIHRoZSBkYXRhYmFzZSBlaXRoZXIgYnkgc3R1ZHlpbmcgdGhlIFNRTCBjcmVhdGlvbiBjb2RlIG9yIGxpc3RpbmcgdGhlIHRhYmxlcy4gSXQgaXMgYSB1c2VmdWwgcHJhY3RpY2UgdG8gdmlzdWFsaXplIHRoZSBkYXRhYmFzZSBzdHJ1Y3R1cmUgYnkgZHJhd2luZyBhbiBFbnRpdHktUmVsYXRpb25zaGlwIG9yIFVNTCBkaWFncmFtLgoKVGhlIHR1dG9yaWFsIGJlbG93IHdpbGwgc2hvdyB5b3UgaG93IHRvIGNyZWF0ZSB0aGUgZGF0YWJhc2UsIGNvbm5lY3QgdG8gaXQsIGFuZCBpbnNwZWN0IHRoZSB0YWJsZXMuIFdhdGNoIGl0IG9ubHkgYWZ0ZXIgeW91IGF0dGVtcHRlZCB0byBkbyB0aGlzIHlvdXJzZWxmLiBJdCBhc3N1bWVzIHRoYXQgeW91IGhhdmUgdGhlIFNRTGl0ZSB0b29scyBpbnN0YWxsZWQgbG9jYWxseSBvbiB5b3VyIGNvbXB1dGVyLgoKPGlmcmFtZSBzcmM9Imh0dHBzOi8vcGxheWVyLnZpbWVvLmNvbS92aWRlby83OTk5ODk5NTk/aD0wNjM1N2M4MDVmJmFtcDt0aXRsZT0wJmFtcDtieWxpbmU9MCZhbXA7cG9ydHJhaXQ9MCZhbXA7c3BlZWQ9MCZhbXA7YmFkZ2U9MCZhbXA7YXV0b3BhdXNlPTAmYW1wO3BsYXllcl9pZD0wJmFtcDthcHBfaWQ9NTg0NzkiIHdpZHRoPSI0ODAiIGhlaWdodD0iMzE4IiBmcmFtZWJvcmRlcj0iMSIgYWxsb3c9ImF1dG9wbGF5OyBmdWxsc2NyZWVuOyBwaWN0dXJlLWluLXBpY3R1cmUiIGFsbG93ZnVsbHNjcmVlbiB0aXRsZT0iV29ya2luZyB3aXRoIFNRTGl0ZSBNYW5hZ2VtZW50IENvbnNvbGUiIGRhdGEtZXh0ZXJuYWw9IjEiPgoKPC9pZnJhbWU+CgojIyMgQnVpbGQgUXVlcmllcwoKT25jZSB5b3UgYXJlIGZhbWlsaWFyIHdpdGggdGhlIGRhdGFiYXNlLCB1c2UgdGhlIGludGVyYWN0aXZlIGNvbW1hbmQgbGluZSB0b29sIHRvIGJ1aWxkIFNRTCBxdWVyaWVzIGZvciB0aGUgZm9sbG93aW5nIHF1ZXN0aW9uczoKCiMjIyMgUXVlcnkgMQoKKkZpbmQgdGhlIGRpc3RpbmN0IG51bWJlciBvZiB3b3JrZXJzIHdobyB3b3JrIGluIHRoZSBIUiBkZXBhcnRtZW50IGFuZCB3aG8gZWFybiBtb3JlIHRoYW4g4oK5MjI1LDAwMC4qCgpgYGB7PWh0bWx9CjxwPgogIDxhIGNsYXNzPSJidG4gYnRuLXByaW1hcnkiIGRhdGEtdG9nZ2xlPSJjb2xsYXBzZSIgaHJlZj0iI2NvbGxhcHNlLWxpZC03MC04MDMtUTEiIHJvbGU9ImJ1dHRvbiIgYXJpYS1leHBhbmRlZD0iZmFsc2UiIGFyaWEtY29udHJvbHM9ImNvbGxhcHNlRXhhbXBsZSI+CiAgICBDbGljayBmb3IgU29sdXRpb24KICA8L2E+CjwvcD4KPGRpdiBjbGFzcz0iY29sbGFwc2UiIGlkPSJjb2xsYXBzZS1saWQtNzAtODAzLVExIj4KICA8ZGl2IGNsYXNzPSJjYXJkIGNhcmQtYm9keSI+CiAgICA8cHJlPgpzZWxlY3QgZGlzdGluY3QgY291bnQoKikgYXMgJ051bVdvcmtlcnMnCiAgZnJvbSBXb3JrZXIgYXMgdwogd2hlcmUgdy5kZXBhcnRtZW50ID0gJ0hSJwogICBhbmQgdy5zYWxhcnkgPiAyNTAwMDA7CiAgICA8L3ByZT4KICA8L2Rpdj4KPC9kaXY+CmBgYAoKIyMjIyBRdWVyeSAyCgoqRmluZCB0aGUgbGFzdCBuYW1lIGFuZCB0aXRsZSBvZiBhbGwgd29ya2VycyBhbmQgdGhlIGRlcGFydG1lbnQgdGhleSB3b3JrIGluIHdobyBlYXJuIGxlc3MgdGhhbiB0aGUgYXZlcmFnZSBzYWxhcnkuKgoKYGBgez1odG1sfQo8cD4KICA8YSBjbGFzcz0iYnRuIGJ0bi1wcmltYXJ5IiBkYXRhLXRvZ2dsZT0iY29sbGFwc2UiIGhyZWY9IiNjb2xsYXBzZS1saWQtNzAtODAzLVEyIiByb2xlPSJidXR0b24iIGFyaWEtZXhwYW5kZWQ9ImZhbHNlIiBhcmlhLWNvbnRyb2xzPSJjb2xsYXBzZUV4YW1wbGUiPgogICAgQ2xpY2sgZm9yIFNvbHV0aW9uCiAgPC9hPgo8L3A+CjxkaXYgY2xhc3M9ImNvbGxhcHNlIiBpZD0iY29sbGFwc2UtbGlkLTcwLTgwMy1RMiI+CiAgPGRpdiBjbGFzcz0iY2FyZCBjYXJkLWJvZHkiPgogICAgPHByZT4Kc2VsZWN0IGxhc3RfbmFtZSwgd29ya2VyX3RpdGxlCiAgZnJvbSBXb3JrZXIgQVMgdyBKT0lOIFRpdGxlIEFTIHQgT04gKHcuV09SS0VSX0lEID0gdC5XT1JLRVJfUkVGX0lEKQogICBhbmQgdy5zYWxhcnkgPCAoc2VsZWN0IGF2ZyhzYWxhcnkpIGZyb20gV29ya2VyKTsKICAgIDwvcHJlPgogIDwvZGl2Pgo8L2Rpdj4KYGBgCgojIyMjIFF1ZXJ5IDMKCipXaGF0IGlzIHRoZSBhdmVyYWdlIHNhbGFyeSBwYWlkIGZvciBhbGwgd29ya2VycyBpbiBlYWNoIGRlcGFydG1lbnQ/IExpc3QgdGhlIGRlcGFydG1lbnQsIHRoZSBhdmVyYWdlIHNhbGFyeSBmb3IgdGhlIGRlcGFydG1lbnQsIGFuZCB0aGUgbnVtYmVyIG9mIHdvcmtlcnMgaW4gZWFjaCBkZXBhcnRtZW50LiBOYW1lIHRoZSBhdmVyYWdlIGNvbHVtbiAnQXZnU2FsJyBhbmQgdGhlIG51bWJlciBvZiB3b3JrZXJzIGNvbHVtbiB0byAnTnVtJy4qCgpgYGB7PWh0bWx9CjxwPgogIDxhIGNsYXNzPSJidG4gYnRuLXByaW1hcnkiIGRhdGEtdG9nZ2xlPSJjb2xsYXBzZSIgaHJlZj0iI2NvbGxhcHNlLWxpZC03MC04MDMtUTMiIHJvbGU9ImJ1dHRvbiIgYXJpYS1leHBhbmRlZD0iZmFsc2UiIGFyaWEtY29udHJvbHM9ImNvbGxhcHNlRXhhbXBsZSI+CiAgICBDbGljayBmb3IgU29sdXRpb24KICA8L2E+CjwvcD4KPGRpdiBjbGFzcz0iY29sbGFwc2UiIGlkPSJjb2xsYXBzZS1saWQtNzAtODAzLVEzIj4KICA8ZGl2IGNsYXNzPSJjYXJkIGNhcmQtYm9keSI+CiAgICA8cHJlPgpzZWxlY3QgZGVwYXJ0bWVudCwgQVZHKHNhbGFyeSkgYXMgJ0F2Z1NhbGFyeScsIGNvdW50KCopIGFzICdOdW1Xb3JrZXJzJwogIGZyb20gV29ya2VyCiBncm91cCBieSBkZXBhcnRtZW50OwogICAgPC9wcmU+CiAgPC9kaXY+CjwvZGl2PgpgYGAKCiMjIyMgUXVlcnkgNAoKKldoYXQgaXMgdGhlIHRvdGFsIGNvbXBlbnNhdGlvbiBmb3IgZWFjaCB3b3JrZXIgKHNhbGFyeSBhbmQgYm9udXMpIG9uIGEgcGVyIG1vbnRobHkgYmFzaXM/IExpc3QgdGhlIG5hbWUgb2YgdGhlIHdvcmtlciwgdGhlaXIgdGl0bGUsIGFuZCB0aGUgdGhlaXIgbW9udGhseSBjb21wZW5zYXRpb24gKGFubnVhbCBjb21wZW5zYXRpb24gZGl2aWRlZCBieSAxMikuIENoYW5nZSB0aGUgaGVhZGVyIGZvciBjb21wZW5zYXRpb24gdG8gJ01vbnRobHlDb21wJyBhbmQgcm91bmQgaXQgdG8gdGhlIG5lYXJlc3Qgd2hvbGUgbnVtYmVyLioKCmBgYHs9aHRtbH0KPHA+CiAgPGEgY2xhc3M9ImJ0biBidG4tcHJpbWFyeSIgZGF0YS10b2dnbGU9ImNvbGxhcHNlIiBocmVmPSIjY29sbGFwc2UtbGlkLTcwLTgwMy1RNCIgcm9sZT0iYnV0dG9uIiBhcmlhLWV4cGFuZGVkPSJmYWxzZSIgYXJpYS1jb250cm9scz0iY29sbGFwc2VFeGFtcGxlIj4KICAgIENsaWNrIGZvciBTb2x1dGlvbgogIDwvYT4KPC9wPgo8ZGl2IGNsYXNzPSJjb2xsYXBzZSIgaWQ9ImNvbGxhcHNlLWxpZC03MC04MDMtUTQiPgogIDxkaXYgY2xhc3M9ImNhcmQgY2FyZC1ib2R5Ij4KICAgIDxwcmU+CnNlbGVjdCBsYXN0X25hbWUsICgoc2FsYXJ5ICsgYm9udXNfYW1vdW50KSAvIDEyKSBhcyAnTW9udGhseUNvbXAnCiAgZnJvbSBXb3JrZXIgYXMgdyBqb2luIEJvbnVzIGFzIGIgb24gKHcuV09SS0VSX0lEID0gYi5XT1JLRVJfUkVGX0lEKQogICAgPC9wcmU+CiAgPC9kaXY+CjwvZGl2PgpgYGAKCiMjIyMgUXVlcnkgNQoKKkxpc3QgdGhlIGZ1bGwgbmFtZXMgb2YgYWxsIHdvcmtlcnMgaW4gYWxsIGNhcGl0YWwgbGV0dGVycyB3aG8gZGlkIG5vdCBnZXQgYSBib251cy4qCgpgYGB7PWh0bWx9CjxwPgogIDxhIGNsYXNzPSJidG4gYnRuLXByaW1hcnkiIGRhdGEtdG9nZ2xlPSJjb2xsYXBzZSIgaHJlZj0iI2NvbGxhcHNlLWxpZC03MC04MDMtUTUiIHJvbGU9ImJ1dHRvbiIgYXJpYS1leHBhbmRlZD0iZmFsc2UiIGFyaWEtY29udHJvbHM9ImNvbGxhcHNlRXhhbXBsZSI+CiAgICBDbGljayBmb3IgU29sdXRpb24KICA8L2E+CjwvcD4KPGRpdiBjbGFzcz0iY29sbGFwc2UiIGlkPSJjb2xsYXBzZS1saWQtNzAtODAzLVE1Ij4KICA8ZGl2IGNsYXNzPSJjYXJkIGNhcmQtYm9keSI+CiAgICA8cHJlPgpzZWxlY3QgdXBwZXIobGFzdF9uYW1lIHx8ICIsICIgfHwgZmlyc3RfbmFtZSkgYXMgJ0Z1bGxOYW1lJwogIGZyb20gV29ya2VyCiB3aGVyZSB3b3JrZXJfaWQgbm90IGluIChzZWxlY3Qgd29ya2VyX3JlZl9pZCBmcm9tIEJvbnVzKQogb3JkZXIgYnkgbGFzdF9uYW1lOwogICAgPC9wcmU+CiAgPC9kaXY+CjwvZGl2PgpgYGAKCiMjIyMgUXVlcnkgNgoKKldoYXQgYXJlIHRoZSBmdWxsIG5hbWVzIG9mIGFsbCB3b3JrZXJzIHdobyBoYXZlICdNYW5hZ2VyJyBpbiB0aGVpciB0aXRsZS4gRG8gbm90ICJoYXJkIGNvZGUiIHRoZSB0aXRsZXM7IHVzZSBzdHJpbmcgc2VhcmNoaW5nLioKCmBgYHs9aHRtbH0KPHA+CiAgPGEgY2xhc3M9ImJ0biBidG4tcHJpbWFyeSIgZGF0YS10b2dnbGU9ImNvbGxhcHNlIiBocmVmPSIjY29sbGFwc2UtbGlkLTcwLTgwMy1RNiIgcm9sZT0iYnV0dG9uIiBhcmlhLWV4cGFuZGVkPSJmYWxzZSIgYXJpYS1jb250cm9scz0iY29sbGFwc2VFeGFtcGxlIj4KICAgIENsaWNrIGZvciBTb2x1dGlvbgogIDwvYT4KPC9wPgo8ZGl2IGNsYXNzPSJjb2xsYXBzZSIgaWQ9ImNvbGxhcHNlLWxpZC03MC04MDMtUTYiPgogIDxkaXYgY2xhc3M9ImNhcmQgY2FyZC1ib2R5Ij4KICAgIDxwcmU+CnNlbGVjdCB1cHBlcihsYXN0X25hbWUgfHwgIiwgIiB8fCBmaXJzdF9uYW1lKSBhcyAnRnVsbE5hbWUnLCB0LldPUktFUl9USVRMRQogIGZyb20gV29ya2VyIHcsIFRpdGxlIHQgCiBXSEVSRSB3LldPUktFUl9JRCA9IHQuV09SS0VSX1JFRl9JRAogICBhbmQgdC5XT1JLRVJfVElUTEUgTElLRSAnJU1hbmFnZXIlJzsKICAgIDwvcHJlPgogIDwvZGl2Pgo8L2Rpdj4KYGBgCgojIyMgVHV0b3JpYWwKCjxpZnJhbWUgc3JjPSJodHRwczovL3BsYXllci52aW1lby5jb20vdmlkZW8vODAwNTI4MTU3P2g9ZTM1OTg4NTAxZiZhbXA7dGl0bGU9MCZhbXA7YnlsaW5lPTAmYW1wO3BvcnRyYWl0PTAmYW1wO3NwZWVkPTAmYW1wO2JhZGdlPTAmYW1wO2F1dG9wYXVzZT0wJmFtcDtwbGF5ZXJfaWQ9MCZhbXA7YXBwX2lkPTU4NDc5IiB3aWR0aD0iNDgwIiBoZWlnaHQ9IjMwNSIgZnJhbWVib3JkZXI9IjAiIGFsbG93PSJhdXRvcGxheTsgZnVsbHNjcmVlbjsgcGljdHVyZS1pbi1waWN0dXJlIiBhbGxvd2Z1bGxzY3JlZW4gdGl0bGU9IlNRTCBRdWVyaWVzOiBFeGFtcGxlcyIgZGF0YS1leHRlcm5hbD0iMSI+Cgo8L2lmcmFtZT4KCiMjIFNRTGl0ZSBDTEkKClNRTGl0ZSdzIGNvbW1hbmQtbGluZSBpbnRlcmZhY2UgKENMSSkgcHJvdmlkZXMgZGlyZWN0IGFjY2VzcyB0byBTUUxpdGUncyBjb3JlIGZ1bmN0aW9uYWxpdHkgdGhyb3VnaCBhIHRlcm1pbmFsLWJhc2VkIGludGVyZmFjZS4gV2hpbGUgZ3JhcGhpY2FsIHRvb2xzIGV4aXN0LCB1bmRlcnN0YW5kaW5nIHRoZSBDTEkgaXMgZnVuZGFtZW50YWwgZm9yIGRhdGFiYXNlIGFkbWluaXN0cmF0b3JzIGFuZCBkZXZlbG9wZXJzIHJlcXVpcmluZyBwcm9ncmFtbWF0aWMgZGF0YWJhc2UgaW50ZXJhY3Rpb25zLgoKVGhlIFNRTGl0ZSBDTEkgY2FuIGJlIGluaXRpYXRlZCBpbiB0d28gZGlzdGluY3QgbW9kZXMuIEZvciB0cmFuc2llbnQgb3BlcmF0aW9uczoKCmBgYCBiYXNoCiUgc3FsaXRlMwpgYGAKClRoZSAlIGFib3ZlIGluZGljYXRlcyB0aGF0IHRoZSBjb21tYW5kIGlzIHR5cGVkIGZyb20geW91ciBvcGVyYXRpbmcgc3lzdGVtJ3MgY29tbWFuZCBzaGVsbCBvciBhIHRlcm1pbmFsLgoKVGhpcyBjcmVhdGVzIGFuIGVwaGVtZXJhbCwgaW4tbWVtb3J5IGRhdGFiYXNlLiBGb3IgcGVyc2lzdGVudCBzdG9yYWdlLCBzcGVjaWZ5IGEgZGF0YWJhc2UgZmlsZToKCmBgYCBiYXNoCiUgc3FsaXRlMyBsaWJyYXJ5LmRiCmBgYAoKT25jZSB5b3UgaGF2ZSBsYXVuY2hlZCB0aGUgU1FMaXRlIENMSSwgeW91IGFyZSBpbiB0aGUgQ0xJJ3MgY29tbWFuZCBzaGVsbCBhbmQgbm8gbG9uZ2VyIHRoZSBvcGVyYXRpbmcgc3lzdGVtJ3MgY29tbWFuZCBzaGVsbC4gV2UgaW5kaWNhdGUgdGhlIFNRTGl0ZSBDTEkgY29tbWFuZCBzaGVsbCB3aXRoIFw+LiBOb3RlIHRoYXQgU1FMaXRlIENMSSBjb21tYW5kcyBhbHdheXMgc3RhcnQgd2l0aCBhIHBlcmlvZCAoLikuIEFueSBTUUwgc3RhdGVtZW50IHdvdWxkIG5vdCBzdGFydCB3aXRoIGEgcGVyaW9kLgoKU2Vzc2lvbiB0ZXJtaW5hdGlvbiBpcyBhY2NvbXBsaXNoZWQgdmlhIHRoZSBgLmV4aXRgIG1ldGEtY29tbWFuZDoKCmBgYCBzcWwKPi5leGl0CmBgYAoKIyMjIERhdGFiYXNlIEFkbWluaXN0cmF0aW9uIENvbW1hbmRzCgpTUUxpdGUgcHJvdmlkZXMgbWV0YS1jb21tYW5kcyBmb3IgZGF0YWJhc2UgYWRtaW5pc3RyYXRpb246CgpgYGAgc3FsCi8qIExpc3QgYWxsIGF0dGFjaGVkIGRhdGFiYXNlcyAqLwo+LmRhdGFiYXNlcwptYWluOiBDOlxwYXRoXHRvXGxpYnJhcnkuZGIgci93CgovKiBEaXNwbGF5IGF2YWlsYWJsZSB0YWJsZXMgKi8KPi50YWJsZXMKQk9PS1MgIEFVVEhPUlMgIEJPUlJPV0VSUwoKLyogRXhhbWluZSBzY2hlbWEgZGVmaW5pdGlvbnMgKi8KPi5zY2hlbWEKYGBgCgojIyBTUUwgU2NyaXB0cwoKVG8gZXhlY3V0ZSBhIFNRTGl0ZSAic2NyaXB0IiwgKmkuZS4qLCBhIHNlcXVlbmNlIG9mIFNRTCBzdGF0ZW1lbnRzIHNlcGFyYXRlZCBieSBzZW1pLWNvbG9ucyBhbmQgY29udGFpbmVkIGluIGEgdGV4dCBmaWxlLCBmcm9tIHRoZSBjb21tYW5kLWxpbmUgdXNpbmcgdGhlICpzcWxpdGUzKiBwcm9ncmFtIChkb3dubG9hZCBhbmQgaW5zdGFsbCBmcm9tIFtzcWxpdGUuY29tXShodHRwOi8vc3FsaXRlLmNvbSkpLCB5b3UgY2FuIGVpdGhlciBmZWVkIHRoZSBzY3JpcHQgdG8gdGhlICpzcWxpdGUzKiBtYW5hZ2VtZW50IGNvbnNvbGUgcHJvZ3JhbSBvciB1c2UgdGhlIGAucmVhZGAgY29tbWFuZCB3aXRoaW4gdGhlICpzcWxpdGUzKiBzaGVsbC4KCiMjIyAxLiBGZWVkaW5nIHRoZSBzY3JpcHQgdG8gKnNxbGl0ZTMqIHVzaW5nIHJlZGlyZWN0aW9uCgpZb3UgY2FuIHBpcGUgdGhlIGNvbnRlbnRzIG9mIHlvdXIgU1FMIHNjcmlwdCBmaWxlIGRpcmVjdGx5IHRvIHRoZSBzcWxpdGUzIHByb2dyYW0uIEZvciBleGFtcGxlLCBpZiB5b3UgaGF2ZSBhIHNjcmlwdCBuYW1lZCAibXlfc2NyaXB0LnNxbCIsIHlvdSBjYW4gZXhlY3V0ZSBpdCBsaWtlIHRoaXM6CgpgYGAgYmFzaApzcWxpdGUzIG15X2RhdGFiYXNlLmRiIDwgbXlfc2NyaXB0LnNxbApgYGAKClRoaXMgb3BlbnMgdGhlIHNwZWNpZmllZCBkYXRhYmFzZSAoIm15X2RhdGFiYXNlLmRiIiksIHJlYWRzIHRoZSBTUUwgY29tbWFuZHMgZnJvbSB0aGUgc2NyaXB0IGZpbGUgKHNlcGFyYXRlZCBieSBzZW1pLWNvbG9ucyksIGFuZCBleGVjdXRlcyB0aGVtIGluIHNlcXVlbmNlLgoKIyMjIDIuIFVzaW5nIEdldC1Db250ZW50IChQb3dlclNoZWxsKQoKSW4gUG93ZXJTaGVsbCBvbiBXaW5kb3dzLCB5b3UgY2FuIHVzZSBgR2V0LUNvbnRlbnRgIHRvIHJlYWQgdGhlIHNjcmlwdCBhbmQgdGhlbiBwaXBlIHRoZSBvdXRwdXQgdG8gKnNxbGl0ZTMqOgoKYGBgIGJhc2gKR2V0LUNvbnRlbnQgbXlfc2NyaXB0LnNxbCAtUmF3IHwgc3FsaXRlMyBteV9kYXRhYmFzZS5kYgpgYGAKClRoaXMgb3BlbnMgdGhlIGRhdGFiYXNlIGFuZCBleGVjdXRlcyB0aGUgU1FMIHNjcmlwdC4KCiMjIyAzLiBVc2luZyB0aGUgLnJlYWQgY29tbWFuZCB3aXRoaW4gdGhlIHNxbGl0ZTMgc2hlbGwKClN0YXJ0IHRoZSAqc3FsaXRlMyogbWFuYWdlbWVudCBjb25zb2xlIHNoZWxsIGJ5IG9wZW4gYSB0ZXJtaW5hbCBvciBjb21tYW5kIHByb21wdCBhbmQgcnVubmluZyBgc3FsaXRlMyBteV9kYXRhYmFzZS5kYmAgdG8gY29ubmVjdCB0byB5b3VyIGRhdGFiYXNlICgibXlfZGF0YWJhc2UuZGIiKS4gVGhlbiB1c2UgdGhlICoucmVhZCogU1FMaXRlIG1hbmFnZW1lbnQgY29tbWFuZCBpbnNpZGUgdGhlICpzcWxpdGUzKiBtYW5hZ2VtZW50IHNoZWxsIHRvIGV4ZWN1dGUgdGhlIHNjcmlwdC4KCmBgYCBiYXNoCnNxbGl0ZTMgbXlfZGF0YWJhc2UuZGIKCnNxbGl0ZT4gLnJlYWQgbXlfc2NyaXB0LnNxbApgYGAKClRoaXMgb3BlbnMgdGhlIGRhdGFiYXNlICJteV9kYXRhYmFzZS5kYiIsIHRoZW4gcmVhZHMgYW5kIGV4ZWN1dGVzIHRoZSBTUUwgY29tbWFuZHMgZnJvbSB0ZXh0IGZpbGUgIm15X3NjcmlwdC5zcWwiLgoKIyMjIEhpbnRzCgotICAgTWFrZSBzdXJlIHRvIHNwZWNpZnkgdGhlIGRhdGFiYXNlIGZpbGUgd2hlbiB1c2luZyB0aGUgY29tbWFuZC1saW5lIGludGVyZmFjZSAoKmUuZy4qLCBgc3FsaXRlMyBteV9kYXRhYmFzZS5kYmApCi0gICBFbnN1cmUgdGhhdCB5b3VyIFNRTCBzY3JpcHQgZmlsZSBpcyBhY2Nlc3NpYmxlIGJ5IHRoZSAqc3FsaXRlMyogcHJvZ3JhbQotICAgQ29tbWFuZHMgc3RhcnRpbmcgd2l0aCBhIHBlcmlvZCAoLikgYXJlIHNwZWNpYWwgY29tbWFuZHMgd2l0aGluIHRoZSAqc3FsaXRlMyogc2hlbGwgYW5kIGFyZSBtYW5hZ2VtZW50IGNvbW1hbmRzIGFuZCAqKm5vdCoqIFNRTCBzdGF0ZW1lbnRzCi0gICBUaGUgU1FMIHNjcmlwdCBmaWxlIG11c3QgYmUgYSBwbGFpbiB0ZXh0IGZpbGUgY29udGFpbmluZyB2YWxpZCBTUUwgY29tbWFuZHMgc2VwYXJhdGVkIGJ5IHNlbWljb2xvbnMKCiMjIFN1bW1hcnkKCk1hbmFnZW1lbnQgY29uc29sZXMsIGF2YWlsYWJsZSBmb3IgZXZlcnkgZGF0YWJhc2UsIGFyZSBhbiBlc3NlbnRpYWwgdG9vbCBmb3IgZGF0YWJhc2UgZGV2ZWxvcG1lbnQgYW5kIGFkbWluaXN0cmF0aW9uLiBTb21lIGFyZSBjb21tYW5kLWxpbmUgb3JpZW50ZWQgYW5kIHNvbWUgaGF2ZSBncmFwaGljYWwgdXNlciBpbnRlcmZhY2VzLiBTb21lIGV2ZW4gYWxsb3cgZGF0YWJhc2UgZGVzaWduIHRocm91Z2ggaW50ZWdyYXRlZCBkaWFncmFtbWluZyB0b29scy4KCkFzaWRlIGZyb20gYWxsb3dpbmcgdXMgdG8gY3JlYXRlIGRhdGFiYXNlcyBhbmQgcGVyZm9ybSAqYWQgaG9jKiBxdWVyaWVzLCB0aGUgcHJvdmlkZSBhIG51bWJlciBvZiBhZGRpdGlvbmFsIGJlbmVmaXRzLgoKLSAgICoqQ2VudHJhbGl6ZWQgY29udHJvbCoqOiBBIG1hbmFnZW1lbnQgY29uc29sZSBwcm92aWRlcyBhIGNlbnRyYWxpemVkIGludGVyZmFjZSBmb3IgbWFuYWdpbmcgYW5kIG1vbml0b3JpbmcgYSBkYXRhYmFzZSwgYWxsb3dpbmcgYWRtaW5pc3RyYXRvcnMgdG8gY29uZmlndXJlIGFuZCBtb25pdG9yIHRoZSBkYXRhYmFzZSBtb3JlIGVhc2lseSBhbmQgZWZmaWNpZW50bHkuCgotICAgKipFZmZpY2llbnQgcGVyZm9ybWFuY2UgbW9uaXRvcmluZyoqOiBBIG1hbmFnZW1lbnQgY29uc29sZSBwcm92aWRlcyByZWFsLXRpbWUgbW9uaXRvcmluZyBvZiB0aGUgZGF0YWJhc2UncyBwZXJmb3JtYW5jZSwgZW5hYmxpbmcgYWRtaW5pc3RyYXRvcnMgdG8gcXVpY2tseSBpZGVudGlmeSBhbmQgdHJvdWJsZXNob290IHBlcmZvcm1hbmNlIGlzc3Vlcy4gVGhpcyBjYW4gaGVscCBpbXByb3ZlIHRoZSBvdmVyYWxsIHBlcmZvcm1hbmNlIG9mIHRoZSBkYXRhYmFzZSwgcmVkdWNpbmcgZG93bnRpbWUgYW5kIGltcHJvdmluZyB0aGUgZW5kIHVzZXIgZXhwZXJpZW5jZS4KCi0gICAqKkVuaGFuY2VkIHNlY3VyaXR5Kio6IEEgbWFuYWdlbWVudCBjb25zb2xlIGNhbiBoZWxwIHRvIGVuaGFuY2UgdGhlIHNlY3VyaXR5IG9mIGEgZGF0YWJhc2UgYnkgcHJvdmlkaW5nIHRvb2xzIHRvIG1hbmFnZSB1c2VycyBhbmQgcGVybWlzc2lvbnMsIHNldCB1cCBhdWRpdGluZywgYW5kIG1vbml0b3IgdGhlIGRhdGFiYXNlIGZvciBzdXNwaWNpb3VzIGFjdGl2aXR5LiBUaGlzIGNhbiBoZWxwIHByZXZlbnQgdW5hdXRob3JpemVkIGFjY2VzcyB0byB0aGUgZGF0YWJhc2UgYW5kIHByb3RlY3Qgc2Vuc2l0aXZlIGRhdGEuCgotICAgKipBdXRvbWF0ZWQgYmFja3VwIGFuZCByZWNvdmVyeSoqOiBNYW55IG1hbmFnZW1lbnQgY29uc29sZXMgaW5jbHVkZSB0b29scyBmb3IgYXV0b21hdGVkIGJhY2t1cCBhbmQgcmVjb3Zlcnkgb2YgdGhlIGRhdGFiYXNlLCBoZWxwaW5nIHRvIGVuc3VyZSBkYXRhIGlzIHByb3RlY3RlZCBpbiB0aGUgZXZlbnQgb2YgYSBkaXNhc3RlciBvciBvdGhlciB1bmZvcmVzZWVuIGNpcmN1bXN0YW5jZXMuCgotICAgKipTaW1wbGlmaWVkIGFkbWluaXN0cmF0aW9uKio6IEEgbWFuYWdlbWVudCBjb25zb2xlIGNhbiBzaW1wbGlmeSBkYXRhYmFzZSBhZG1pbmlzdHJhdGlvbiBieSBwcm92aWRpbmcgYSBncmFwaGljYWwgdXNlciBpbnRlcmZhY2UgdGhhdCBzaW1wbGlmaWVzIGNvbXBsZXggZGF0YWJhc2UgdGFza3MuIFRoaXMgY2FuIGhlbHAgcmVkdWNlIHRoZSBuZWVkIGZvciBzcGVjaWFsaXplZCBza2lsbHMgb3Iga25vd2xlZGdlLCBtYWtpbmcgaXQgZWFzaWVyIGZvciBhIHdpZGVyIHJhbmdlIG9mIHN0YWZmIHRvIG1hbmFnZSBhbmQgbWFpbnRhaW4gdGhlIGRhdGFiYXNlLgoKT3ZlcmFsbCwgYSBtYW5hZ2VtZW50IGNvbnNvbGUgZm9yIGEgZGF0YWJhc2UgY2FuIGhlbHAgc3RyZWFtbGluZSBkYXRhYmFzZSBtYW5hZ2VtZW50LCBmYWNpbGl0YXRlICphZCBob2MqIHF1ZXJ5aW5nLCBpbXByb3ZlIHBlcmZvcm1hbmNlIGFuZCBzZWN1cml0eSwgYW5kIHNpbXBsaWZ5IGFkbWluaXN0cmF0aW9uLCBtYWtpbmcgaXQgYW4gZXNzZW50aWFsIHRvb2wgZm9yIGRhdGFiYXNlIGRldmVsb3BtZW50LgoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIyBGaWxlcyAmIFJlc291cmNlcwoKYGBge3IgemlwRmlsZXMsIGVjaG89RkFMU0V9CnppcE5hbWUgPSBzcHJpbnRmKCJMZXNzb25GaWxlcy0lcy0lcy56aXAiLCAKICAgICAgICAgICAgICAgICBwYXJhbXMkY2F0ZWdvcnksCiAgICAgICAgICAgICAgICAgcGFyYW1zJG51bWJlcikKCnRleHRBTGluayA9IHBhc3RlMCgiQWxsIEZpbGVzIGZvciBMZXNzb24gIiwgCiAgICAgICAgICAgICAgIHBhcmFtcyRjYXRlZ29yeSwiLiIscGFyYW1zJG51bWJlcikKCiMgZG93bmxvYWRGaWxlc0xpbmsoKSBpcyBpbmNsdWRlZCBmcm9tIF9pbnNlcnQyREIuUgprbml0cjo6cmF3X2h0bWwoZG93bmxvYWRGaWxlc0xpbmsoIi4iLCB6aXBOYW1lLCB0ZXh0QUxpbmspKQpgYGAKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMgUmVmZXJlbmNlcwoKW0NvbW1hbmQgTGluZSBTaGVsbCBGb3IgU1FMaXRlXShodHRwczovL3d3dy5zcWxpdGUub3JnL2NsaS5odG1sKQoKS3JlaWJpY2gsIEouIEEuICgyMDEwKS4gKlVzaW5nIFNRTGl0ZSogKDFzdCBlZC4pLiBPJ1JlaWxseSBNZWRpYS4KClNRTGl0ZSBEZXZlbG9wbWVudCBUZWFtLiAoMjAyNCkuICpTUUxpdGUgRG9jdW1lbnRhdGlvbiouIFNRTGl0ZSBDb25zb3J0aXVtLiA8aHR0cHM6Ly9zcWxpdGUub3JnL2RvY3MuaHRtbD4KCiMjIEVycmF0YQoKTm9uZSBjb2xsZWN0ZWQgeWV0LiBMZXQgdXMga25vdy4KCltMZXQgdXMga25vd10oaHR0cHM6Ly9mb3JtLmpvdGZvcm0uY29tLzIxMjE4NzA3Mjc4NDE1Nyl7dGFyZ2V0PSJfYmxhbmsifS4K