Introduction

The hosting solutions below are fully free or free with limits. However, some of the services have significant feature restriction, so be sure the restrictions will not be limiting for your use case.

Service Cost Limits
dbfree.net free does not allow bulk insertion with dbWriteTable(); can be slow
freemysqlhosting.net free 5MB max database size
aiven.io free

These hosting services have a semi-free option where credits are provided that can be used to pay the services for a limited time. However, some services will immediately charge for overage if the free credits are exhausted. This is particularly true for AWS and it is possible to end up with significant charges.

  • AWS RDS
  • Google Cloud
  • Microsoft Azure

Setup Guides

This section provides setup guides for two free or semi-free MySQL cloud databases:

db4free.net

This section explains how to create a remote instance of a MySQL database on db4free.net connect to the database from R.

Configure db4free

The tutorial below demonstrates how to create a new database on db4free.net.

Connecting to db4free.net MySQL from R

You need to follow the steps above first and create your database first. Be sure to write down the name of the database, your user name, and your password. If you are attempting to run the code below yourself, comment out the database you did not set up.

# 1. Library
library(RMySQL)

# 2. Settings
db_user <- 'cs5200'            # use your value from the setup
db_password <- 'khour#2021'    # use your value from the setup
db_name <- 'cs5200db1'         # use your value from the setup

db_host <- 'db4free.net'       # for db4free.net

db_port <- 3306

# 3. Connect to remote server database

mydb.db4free <-  dbConnect(RMySQL::MySQL(), user = db_user, password = db_password,
                           dbname = db_name, host = db_host, port = db_port)

Next, we will test the connection by creating a table, inserting rows, and then querying the table.

drop table if exists courses
create table if not exists courses (
  cid INTEGER NOT NULL PRIMARY KEY,
  title varchar(32) NOT NULL,
  credits INTEGER NOT NULL
)
insert into courses (cid,title,credits) values 
  (1100,"CS and Application", 4),
  (2000,"Princ Info Sci", 4),
  (5200,"DBMS", 4),
  (5030,"Intro ML", 3)
select * from courses limit 3
Table 1: 3 records
cid title credits
1100 CS and Application 4
2000 Princ Info Sci 4
5030 Intro ML 3
select count(*) from courses;
Table 2: 1 records
count(*)
4

The key drawback to db4free is that is does not allow bulk insertion of data via dbWriteTable() as the code below causes the error [“Loading local data is disabled”]{color:red}. So, insert data one or more rows at a time using SQL INSERT statements.

df <- data.frame(cid = 2000:3000)

df$title <- "no title"
df$credits <- 4

status <- dbWriteTable(mydb.db4free, "courses", df, 
                       overwrite = F, append = T, 
                       row.names=FALSE)
status <- dbDisconnect(mydb.db4free)

Common Problems

  • not activating the account after creation by clicking on link sent in an email
  • If you cannot connect to the MySQL server, check that you do not have a firerwall enabled that might prohibit connections via port 3306. Try turning off your firewall settings
  • Be sure you have the correct database, user name, password, and connection IP (for db4free it is always ‘db4free.net’)
  • inserting data with dbWriteTable() which is not supported; so, insert data one or more rows at a time using SQL INSERT statements
  • local firewall or anti-virus software that blocks port 3306; disable if there are connection issues

freemysqlhosting.net

This section explains how to create a remote instance of a MySQL database on freemysqlhosting.net connect to the database from R.

Configure freemysqlhosting.net

Visit freemysqlhosting.net and set up an account and then configure a database. Be sure to write down the name of the database, your user name, and your password. Check your email for activation links.

Connecting to freemysqlhosting.net MySQL from R

You need to follow the steps above first and create your database first. If you are attempting to run the code below yourself, comment out the database you did not set up.

# 1. Library
library(RMySQL)

# 2. Settings freemysqlhosting.net (max 5MB)
db_name_fh <- "sql9612301"
db_user_fh <- "sql9612301"
db_host_fh <- "sql9.freemysqlhosting.net"
db_pwd_fh <- "5bARWSaBig"
db_port_fh <- 3306

# 3. Connect to remote server database
mydb.fh <-  dbConnect(RMySQL::MySQL(), user = db_user_fh, password = db_pwd_fh,
                      dbname = db_name_fh, host = db_host_fh, port = db_port_fh)

mydb <- mydb.fh

Next, we will test the connection by creating a table, inserting rows, and then querying the table.

drop table if exists courses
create table if not exists courses (
  cid INTEGER NOT NULL PRIMARY KEY,
  title varchar(32) NOT NULL,
  credits INTEGER NOT NULL
)
insert into courses (cid,title,credits) values 
  (1100,"CS and Application", 4),
  (2000,"Princ Info Sci", 4),
  (5200,"DBMS", 4),
  (5030,"Intro ML", 3)
select * from courses limit 3
Table 3: 3 records
cid title credits
1100 CS and Application 4
2000 Princ Info Sci 4
5030 Intro ML 3
select count(*) from courses;
Table 4: 1 records
count(*)
4

The key drawback to db4free was that is does not allow bulk insertion of data via dbWriteTable(), but freemysqlhosting does support bulk loading as demonstrated in the example below.

df <- data.frame(cid = 9000:9999)

df$title <- "no title"
df$credits <- 4

status <- dbWriteTable(mydb.fh, "courses", df, 
                       overwrite = F, append = T, 
                       row.names=FALSE)

Note that the new rows have been inserted:

select count(*) from courses;
Table 5: 1 records
count(*)
4
status <- dbDisconnect(mydb.fh)

Common Problems

  • the free account has a maximum database capacity of 5MB
  • local firewall or anti-virus software that blocks port 3306; disable if there are connection issues

Disconnect from Database

Disconnect from the database (important as database servers have limited numbers of connection and each connection uses a resource). Use dbDisconnect().

MySQL Workbench

MySQL Workbench You should always install MySQL Workbench (Links to an external site.) to help administer any local or remote database. Use the same connection information to connect to your database.

About MySQL Workbench

From the creators of MySQL Workbench…

MySQL Workbench is a unified visual tool for database architects, developers, and DBAs. MySQL Workbench provides data modeling, SQL development, and comprehensive administration tools for server configuration, user administration, backup, and much more. MySQL Workbench is available on Windows, Linux and Mac OS X.

Design

MySQL Workbench enables a DBA, developer, or data architect to visually design, model, generate, and manage databases. It includes everything a data modeler needs for creating complex ER models, forward and reverse engineering, and also delivers key features for performing difficult change management and documentation tasks that normally require much time and effort.

Develop

MySQL Workbench delivers visual tools for creating, executing, and optimizing SQL queries. The SQL Editor provides color syntax highlighting, auto-complete, reuse of SQL snippets, and execution history of SQL. The Database Connections Panel enables developers to easily manage standard database connections, including MySQL Fabric. The Object Browser provides instant access to database schema and objects.

Administer

MySQL Workbench provides a visual console to easily administer MySQL environments and gain better visibility into databases. Developers and DBAs can use the visual tools for configuring servers, administering users, performing backup and recovery, inspecting audit data, and viewing database health.

Database Migration

MySQL Workbench now provides a complete, easy to use solution for migrating Microsoft SQL Server, Microsoft Access, Sybase ASE, PostreSQL, and other RDBMS tables, objects and data to MySQL. Developers and DBAs can quickly and easily convert existing applications to run on MySQL both on Windows and other platforms. Migration also supports migrating from earlier versions of MySQL to the latest releases.


Files & Resources

All Files for Lesson 6.304

References

None.

Errata

None collected yet. Let us know.

LS0tCnRpdGxlOiAiQ29uZmlndXJlIGFuZCBDb25uZWN0IHRvIENsb3VkIE15U1FMIGZyb20gUiIKcGFyYW1zOgogIGNhdGVnb3J5OiA2CiAgbnVtYmVyOiAzMDQKICB0aW1lOiAyNQogIGxldmVsOiBiZWdpbm5lcgogIHRhZ3M6ICJyLE15U1FMLGRiNGZyZWUsQVdTLEFXUyBSRFMsYWl2ZW4sZnJlZW15c3FsaG9zdGluZyIKICBkZXNjcmlwdGlvbjogIkRlbW9uc3RyYXRlcyBob3cgdG8gY3JlYXRlIGEgY2xvdWQgTXlTUUwgaW5zdGFuY2Ugb24KICAgICAgICAgICAgICAgIGRiNGZyZWUubmV0LCBBV1MgUkRTLGFpdmVuLmlvLCBhbmQgZnJlZW15c3FsaG9zdGluZy5uZXQKICAgICAgICAgICAgICAgIGFuZCB0aGVuIGNvbm5lY3QgdG8gZWFjaCBkYXRhYmFzZSBmcm9tIFIuIgpkYXRlOiAiPHNtYWxsPmByIFN5cy5EYXRlKClgPC9zbWFsbD4iCmF1dGhvcjogIjxzbWFsbD5NYXJ0aW4gU2NoZWRsYmF1ZXI8L3NtYWxsPiIKZW1haWw6ICJtLnNjaGVkbGJhdWVyQG5ldS5lZHUiCmFmZmlsaXRhdGlvbjogIk5vcnRoZWFzdGVybiBVbml2ZXJzaXR5IgpvdXRwdXQ6IAogIGJvb2tkb3duOjpodG1sX2RvY3VtZW50MjoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICB0aGVtZTogc3BhY2VsYWIKICAgIGhpZ2hsaWdodDogdGFuZ28KLS0tCgotLS0KdGl0bGU6ICI8c21hbGw+YHIgcGFyYW1zJGNhdGVnb3J5YC5gciBwYXJhbXMkbnVtYmVyYDwvc21hbGw+PGJyLz48c3BhbiBzdHlsZT0nY29sb3I6ICMyRTQwNTM7IGZvbnQtc2l6ZTogMC45ZW0nPmByIHJtYXJrZG93bjo6bWV0YWRhdGEkdGl0bGVgPC9zcGFuPiIKLS0tCgpgYGB7ciBjb2RlPXhmdW46OnJlYWRfdXRmOChwYXN0ZTAoaGVyZTo6aGVyZSgpLCcvUi9faW5zZXJ0MkRCLlInKSksIGluY2x1ZGUgPSBGQUxTRX0KYGBgCgpgYGB7ciBjb25maWcsIGluY2x1ZGU9RkFMU0V9Cm9wdGlvbnMoYm9va2Rvd24ucmVuZGVyLmZpbGVfc2NvcGUgPSBGQUxTRSkKCiMjIERlZmF1bHQgcmVwbwpsb2NhbCh7ciA8LSBnZXRPcHRpb24oInJlcG9zIikKICAgICAgIHJbIkNSQU4iXSA8LSAiaHR0cDovL2NyYW4uci1wcm9qZWN0Lm9yZyIgCiAgICAgICBvcHRpb25zKHJlcG9zPXIpCn0pCgpsaXN0Lm9mLnBhY2thZ2VzIDwtIGMoIlJNeVNRTCIsICJzcWxkZiIpCm5ldy5wYWNrYWdlcyA8LSBsaXN0Lm9mLnBhY2thZ2VzWyEobGlzdC5vZi5wYWNrYWdlcyAlaW4lIGluc3RhbGxlZC5wYWNrYWdlcygpWywiUGFja2FnZSJdKV0KaWYobGVuZ3RoKG5ldy5wYWNrYWdlcykpIGluc3RhbGwucGFja2FnZXMobmV3LnBhY2thZ2VzKQpgYGAKCiMjIEludHJvZHVjdGlvbgoKVGhlIGhvc3Rpbmcgc29sdXRpb25zIGJlbG93IGFyZSBmdWxseSBmcmVlIG9yIGZyZWUgd2l0aCBsaW1pdHMuIEhvd2V2ZXIsIHNvbWUgb2YgdGhlIHNlcnZpY2VzIGhhdmUgc2lnbmlmaWNhbnQgZmVhdHVyZSByZXN0cmljdGlvbiwgc28gYmUgc3VyZSB0aGUgcmVzdHJpY3Rpb25zIHdpbGwgbm90IGJlIGxpbWl0aW5nIGZvciB5b3VyIHVzZSBjYXNlLgoKfCBTZXJ2aWNlICAgICAgICAgICAgICB8IENvc3QgfCBMaW1pdHMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwKfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS18LS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLXwKfCBkYmZyZWUubmV0ICAgICAgICAgICB8IGZyZWUgfCBkb2VzIG5vdCBhbGxvdyBidWxrIGluc2VydGlvbiB3aXRoIGBkYldyaXRlVGFibGUoKWA7IGNhbiBiZSBzbG93IHwKfCBmcmVlbXlzcWxob3N0aW5nLm5ldCB8IGZyZWUgfCA1TUIgbWF4IGRhdGFiYXNlIHNpemUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwKfCBhaXZlbi5pbyAgICAgICAgICAgICB8IGZyZWUgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwKClRoZXNlIGhvc3Rpbmcgc2VydmljZXMgaGF2ZSBhIHNlbWktZnJlZSBvcHRpb24gd2hlcmUgY3JlZGl0cyBhcmUgcHJvdmlkZWQgdGhhdCBjYW4gYmUgdXNlZCB0byBwYXkgdGhlIHNlcnZpY2VzIGZvciBhIGxpbWl0ZWQgdGltZS4gSG93ZXZlciwgc29tZSBzZXJ2aWNlcyB3aWxsIGltbWVkaWF0ZWx5IGNoYXJnZSBmb3Igb3ZlcmFnZSBpZiB0aGUgZnJlZSBjcmVkaXRzIGFyZSBleGhhdXN0ZWQuIFRoaXMgaXMgcGFydGljdWxhcmx5IHRydWUgZm9yIEFXUyBhbmQgaXQgaXMgcG9zc2libGUgdG8gZW5kIHVwIHdpdGggc2lnbmlmaWNhbnQgY2hhcmdlcy4KCi0gICBBV1MgUkRTCi0gICBHb29nbGUgQ2xvdWQKLSAgIE1pY3Jvc29mdCBBenVyZQoKIyMgU2V0dXAgR3VpZGVzCgpUaGlzIHNlY3Rpb24gcHJvdmlkZXMgc2V0dXAgZ3VpZGVzIGZvciB0d28gZnJlZSBvciBzZW1pLWZyZWUgTXlTUUwgY2xvdWQgZGF0YWJhc2VzOgoKLSAgIFtkYjRmcmVlLm5ldF0oaHR0cDovL2RiNGZyZWUubmV0KQotICAgW2ZyZWVteXNxbGhvc3RpbmcubmV0XShodHRwOi8vZnJlZW15c3FsaG9zdGluZy5uZXQpCgojIyMgKmRiNGZyZWUubmV0KgoKVGhpcyBzZWN0aW9uIGV4cGxhaW5zIGhvdyB0byBjcmVhdGUgYSByZW1vdGUgaW5zdGFuY2Ugb2YgYSBNeVNRTCBkYXRhYmFzZSBvbiBbZGI0ZnJlZS5uZXRdKGh0dHA6Ly9kYjRmcmVlLm5ldCkgY29ubmVjdCB0byB0aGUgZGF0YWJhc2UgZnJvbSBSLgoKIyMjIyBDb25maWd1cmUgKmRiNGZyZWUqCgpUaGUgdHV0b3JpYWwgYmVsb3cgZGVtb25zdHJhdGVzIGhvdyB0byBjcmVhdGUgYSBuZXcgZGF0YWJhc2Ugb24gW2RiNGZyZWUubmV0XShodHRwOi8vZGI0ZnJlZS5uZXQpLgoKYGBgez1odG1sfQo8aWZyYW1lIHNyYz0iaHR0cHM6Ly9ub3J0aGVhc3Rlcm4uaG9zdGVkLnBhbm9wdG8uY29tL1Bhbm9wdG8vUGFnZXMvRW1iZWQuYXNweD9pZD1mM2E5NTkzZC1kYjM2LTRlMzUtOWVkNi1hY2Q4MDBmYmY2ZTUmYW1wO2F1dG8lMjBsYXk9ZmFsc2UmYW1wO29mZmVydmlld2VyPWZhbHNlJmFtcDtzaG93dGl0bGU9ZmFsc2UmYW1wO3Nob3dicmFuZD1mYWxzZSZhbXA7c3RhcnQ9MCZhbXA7aW50ZXJhY3Rpdml0eT1hbGwiIGZyYW1lYm9yZGVyPSIwIiBhbGxvdz0iYXV0b3BsYXk7IGZ1bGxzY3JlZW47IHBpY3R1cmUtaW4tcGljdHVyZSIgYWxsb3dmdWxsc2NyZWVuIHdpZHRoPSI0ODAiIGhlaWdodD0iMjcwIiB0aXRsZT0iZGI0ZnJlZSBpbiBSIiBkYXRhLWV4dGVybmFsPSIxIj48L2lmcmFtZT4KYGBgCiMjIyMgQ29ubmVjdGluZyB0byAqZGI0ZnJlZS5uZXQqIE15U1FMIGZyb20gUgoKWW91IG5lZWQgdG8gZm9sbG93IHRoZSBzdGVwcyBhYm92ZSBmaXJzdCBhbmQgY3JlYXRlIHlvdXIgZGF0YWJhc2UgZmlyc3QuIEJlIHN1cmUgdG8gd3JpdGUgZG93biB0aGUgbmFtZSBvZiB0aGUgZGF0YWJhc2UsIHlvdXIgdXNlciBuYW1lLCBhbmQgeW91ciBwYXNzd29yZC4gSWYgeW91IGFyZSBhdHRlbXB0aW5nIHRvIHJ1biB0aGUgY29kZSBiZWxvdyB5b3Vyc2VsZiwgY29tbWVudCBvdXQgdGhlIGRhdGFiYXNlIHlvdSBkaWQgbm90IHNldCB1cC4KCmBgYHtyIG1lc3NhZ2U9Riwgd2FybmluZz1GfQojIDEuIExpYnJhcnkKbGlicmFyeShSTXlTUUwpCgojIDIuIFNldHRpbmdzCmRiX3VzZXIgPC0gJ2NzNTIwMCcgICAgICAgICAgICAjIHVzZSB5b3VyIHZhbHVlIGZyb20gdGhlIHNldHVwCmRiX3Bhc3N3b3JkIDwtICdraG91ciMyMDIxJyAgICAjIHVzZSB5b3VyIHZhbHVlIGZyb20gdGhlIHNldHVwCmRiX25hbWUgPC0gJ2NzNTIwMGRiMScgICAgICAgICAjIHVzZSB5b3VyIHZhbHVlIGZyb20gdGhlIHNldHVwCgpkYl9ob3N0IDwtICdkYjRmcmVlLm5ldCcgICAgICAgIyBmb3IgZGI0ZnJlZS5uZXQKCmRiX3BvcnQgPC0gMzMwNgoKIyAzLiBDb25uZWN0IHRvIHJlbW90ZSBzZXJ2ZXIgZGF0YWJhc2UKCm15ZGIuZGI0ZnJlZSA8LSAgZGJDb25uZWN0KFJNeVNRTDo6TXlTUUwoKSwgdXNlciA9IGRiX3VzZXIsIHBhc3N3b3JkID0gZGJfcGFzc3dvcmQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGRibmFtZSA9IGRiX25hbWUsIGhvc3QgPSBkYl9ob3N0LCBwb3J0ID0gZGJfcG9ydCkKYGBgCgpOZXh0LCB3ZSB3aWxsIHRlc3QgdGhlIGNvbm5lY3Rpb24gYnkgY3JlYXRpbmcgYSB0YWJsZSwgaW5zZXJ0aW5nIHJvd3MsIGFuZCB0aGVuIHF1ZXJ5aW5nIHRoZSB0YWJsZS4KCmBgYHtzcWwgY29ubmVjdGlvbj1teWRiLmRiNGZyZWV9CmRyb3AgdGFibGUgaWYgZXhpc3RzIGNvdXJzZXMKYGBgCgpgYGB7c3FsIGNvbm5lY3Rpb249bXlkYi5kYjRmcmVlfQpjcmVhdGUgdGFibGUgaWYgbm90IGV4aXN0cyBjb3Vyc2VzICgKICBjaWQgSU5URUdFUiBOT1QgTlVMTCBQUklNQVJZIEtFWSwKICB0aXRsZSB2YXJjaGFyKDMyKSBOT1QgTlVMTCwKICBjcmVkaXRzIElOVEVHRVIgTk9UIE5VTEwKKQpgYGAKCmBgYHtzcWwgY29ubmVjdGlvbj1teWRiLmRiNGZyZWV9Cmluc2VydCBpbnRvIGNvdXJzZXMgKGNpZCx0aXRsZSxjcmVkaXRzKSB2YWx1ZXMgCiAgKDExMDAsIkNTIGFuZCBBcHBsaWNhdGlvbiIsIDQpLAogICgyMDAwLCJQcmluYyBJbmZvIFNjaSIsIDQpLAogICg1MjAwLCJEQk1TIiwgNCksCiAgKDUwMzAsIkludHJvIE1MIiwgMykKYGBgCgpgYGB7c3FsIGNvbm5lY3Rpb249bXlkYi5kYjRmcmVlfQpzZWxlY3QgKiBmcm9tIGNvdXJzZXMgbGltaXQgMwpgYGAKCmBgYHtzcWwgY29ubmVjdGlvbj1teWRiLmRiNGZyZWV9CnNlbGVjdCBjb3VudCgqKSBmcm9tIGNvdXJzZXM7CmBgYAoKVGhlIGtleSBkcmF3YmFjayB0byAqZGI0ZnJlZSogaXMgdGhhdCBpcyBkb2VzIG5vdCBhbGxvdyBidWxrIGluc2VydGlvbiBvZiBkYXRhIHZpYSBgZGJXcml0ZVRhYmxlKClgIGFzIHRoZSBjb2RlIGJlbG93IGNhdXNlcyB0aGUgZXJyb3IgWyJMb2FkaW5nIGxvY2FsIGRhdGEgaXMgZGlzYWJsZWQiXXtjb2xvcjpyZWR9LiBTbywgaW5zZXJ0IGRhdGEgb25lIG9yIG1vcmUgcm93cyBhdCBhIHRpbWUgdXNpbmcgU1FMICpJTlNFUlQqIHN0YXRlbWVudHMuCgpgYGB7ciBldmFsPUZ9CmRmIDwtIGRhdGEuZnJhbWUoY2lkID0gMjAwMDozMDAwKQoKZGYkdGl0bGUgPC0gIm5vIHRpdGxlIgpkZiRjcmVkaXRzIDwtIDQKCnN0YXR1cyA8LSBkYldyaXRlVGFibGUobXlkYi5kYjRmcmVlLCAiY291cnNlcyIsIGRmLCAKICAgICAgICAgICAgICAgICAgICAgICBvdmVyd3JpdGUgPSBGLCBhcHBlbmQgPSBULCAKICAgICAgICAgICAgICAgICAgICAgICByb3cubmFtZXM9RkFMU0UpCmBgYAoKYGBge3J9CnN0YXR1cyA8LSBkYkRpc2Nvbm5lY3QobXlkYi5kYjRmcmVlKQpgYGAKCiMjIyMgQ29tbW9uIFByb2JsZW1zCgotICAgbm90IGFjdGl2YXRpbmcgdGhlIGFjY291bnQgYWZ0ZXIgY3JlYXRpb24gYnkgY2xpY2tpbmcgb24gbGluayBzZW50IGluIGFuIGVtYWlsCi0gICBJZiB5b3UgY2Fubm90IGNvbm5lY3QgdG8gdGhlIE15U1FMIHNlcnZlciwgY2hlY2sgdGhhdCB5b3UgZG8gbm90IGhhdmUgYSBmaXJlcndhbGwgZW5hYmxlZCB0aGF0IG1pZ2h0IHByb2hpYml0IGNvbm5lY3Rpb25zIHZpYSBwb3J0IDMzMDYuIFRyeSB0dXJuaW5nIG9mZiB5b3VyIGZpcmV3YWxsIHNldHRpbmdzCi0gICBCZSBzdXJlIHlvdSBoYXZlIHRoZSBjb3JyZWN0IGRhdGFiYXNlLCB1c2VyIG5hbWUsIHBhc3N3b3JkLCBhbmQgY29ubmVjdGlvbiBJUCAoZm9yIGRiNGZyZWUgaXQgaXMgYWx3YXlzICdkYjRmcmVlLm5ldCcpCi0gICBpbnNlcnRpbmcgZGF0YSB3aXRoIGBkYldyaXRlVGFibGUoKWAgd2hpY2ggaXMgbm90IHN1cHBvcnRlZDsgc28sIGluc2VydCBkYXRhIG9uZSBvciBtb3JlIHJvd3MgYXQgYSB0aW1lIHVzaW5nIFNRTCAqSU5TRVJUKiBzdGF0ZW1lbnRzCi0gICBsb2NhbCBmaXJld2FsbCBvciBhbnRpLXZpcnVzIHNvZnR3YXJlIHRoYXQgYmxvY2tzIHBvcnQgMzMwNjsgZGlzYWJsZSBpZiB0aGVyZSBhcmUgY29ubmVjdGlvbiBpc3N1ZXMKCiMjIGZyZWVteXNxbGhvc3RpbmcubmV0CgpUaGlzIHNlY3Rpb24gZXhwbGFpbnMgaG93IHRvIGNyZWF0ZSBhIHJlbW90ZSBpbnN0YW5jZSBvZiBhIE15U1FMIGRhdGFiYXNlIG9uIFtmcmVlbXlzcWxob3N0aW5nLm5ldF0oaHR0cDovL2ZyZWVteXNxbGhvc3RpbmcubmV0KSBjb25uZWN0IHRvIHRoZSBkYXRhYmFzZSBmcm9tIFIuCgojIyMjIENvbmZpZ3VyZSAqZnJlZW15c3FsaG9zdGluZy5uZXQqCgpWaXNpdCBbZnJlZW15c3FsaG9zdGluZy5uZXRdKGh0dHA6Ly9mcmVlbXlzcWxob3N0aW5nLm5ldCkgYW5kIHNldCB1cCBhbiBhY2NvdW50IGFuZCB0aGVuIGNvbmZpZ3VyZSBhIGRhdGFiYXNlLiBCZSBzdXJlIHRvIHdyaXRlIGRvd24gdGhlIG5hbWUgb2YgdGhlIGRhdGFiYXNlLCB5b3VyIHVzZXIgbmFtZSwgYW5kIHlvdXIgcGFzc3dvcmQuIENoZWNrIHlvdXIgZW1haWwgZm9yIGFjdGl2YXRpb24gbGlua3MuCgojIyMjIENvbm5lY3RpbmcgdG8gKmZyZWVteXNxbGhvc3RpbmcubmV0KiBNeVNRTCBmcm9tIFIKCllvdSBuZWVkIHRvIGZvbGxvdyB0aGUgc3RlcHMgYWJvdmUgZmlyc3QgYW5kIGNyZWF0ZSB5b3VyIGRhdGFiYXNlIGZpcnN0LiBJZiB5b3UgYXJlIGF0dGVtcHRpbmcgdG8gcnVuIHRoZSBjb2RlIGJlbG93IHlvdXJzZWxmLCBjb21tZW50IG91dCB0aGUgZGF0YWJhc2UgeW91IGRpZCBub3Qgc2V0IHVwLgoKYGBge3IgbWVzc2FnZT1GLCB3YXJuaW5nPUZ9CiMgMS4gTGlicmFyeQpsaWJyYXJ5KFJNeVNRTCkKCiMgMi4gU2V0dGluZ3MgZnJlZW15c3FsaG9zdGluZy5uZXQgKG1heCA1TUIpCmRiX25hbWVfZmggPC0gInNxbDk2MTIzMDEiCmRiX3VzZXJfZmggPC0gInNxbDk2MTIzMDEiCmRiX2hvc3RfZmggPC0gInNxbDkuZnJlZW15c3FsaG9zdGluZy5uZXQiCmRiX3B3ZF9maCA8LSAiNWJBUldTYUJpZyIKZGJfcG9ydF9maCA8LSAzMzA2CgojIDMuIENvbm5lY3QgdG8gcmVtb3RlIHNlcnZlciBkYXRhYmFzZQpteWRiLmZoIDwtICBkYkNvbm5lY3QoUk15U1FMOjpNeVNRTCgpLCB1c2VyID0gZGJfdXNlcl9maCwgcGFzc3dvcmQgPSBkYl9wd2RfZmgsCiAgICAgICAgICAgICAgICAgICAgICBkYm5hbWUgPSBkYl9uYW1lX2ZoLCBob3N0ID0gZGJfaG9zdF9maCwgcG9ydCA9IGRiX3BvcnRfZmgpCgpteWRiIDwtIG15ZGIuZmgKYGBgCgpOZXh0LCB3ZSB3aWxsIHRlc3QgdGhlIGNvbm5lY3Rpb24gYnkgY3JlYXRpbmcgYSB0YWJsZSwgaW5zZXJ0aW5nIHJvd3MsIGFuZCB0aGVuIHF1ZXJ5aW5nIHRoZSB0YWJsZS4KCmBgYHtzcWwgY29ubmVjdGlvbj1teWRiLmZofQpkcm9wIHRhYmxlIGlmIGV4aXN0cyBjb3Vyc2VzCmBgYAoKYGBge3NxbCBjb25uZWN0aW9uPW15ZGIuZmh9CmNyZWF0ZSB0YWJsZSBpZiBub3QgZXhpc3RzIGNvdXJzZXMgKAogIGNpZCBJTlRFR0VSIE5PVCBOVUxMIFBSSU1BUlkgS0VZLAogIHRpdGxlIHZhcmNoYXIoMzIpIE5PVCBOVUxMLAogIGNyZWRpdHMgSU5URUdFUiBOT1QgTlVMTAopCmBgYAoKYGBge3NxbCBjb25uZWN0aW9uPW15ZGIuZmh9Cmluc2VydCBpbnRvIGNvdXJzZXMgKGNpZCx0aXRsZSxjcmVkaXRzKSB2YWx1ZXMgCiAgKDExMDAsIkNTIGFuZCBBcHBsaWNhdGlvbiIsIDQpLAogICgyMDAwLCJQcmluYyBJbmZvIFNjaSIsIDQpLAogICg1MjAwLCJEQk1TIiwgNCksCiAgKDUwMzAsIkludHJvIE1MIiwgMykKYGBgCgpgYGB7c3FsIGNvbm5lY3Rpb249bXlkYi5maH0Kc2VsZWN0ICogZnJvbSBjb3Vyc2VzIGxpbWl0IDMKYGBgCgpgYGB7c3FsIGNvbm5lY3Rpb249bXlkYi5maH0Kc2VsZWN0IGNvdW50KCopIGZyb20gY291cnNlczsKYGBgCgpUaGUga2V5IGRyYXdiYWNrIHRvICpkYjRmcmVlKiB3YXMgdGhhdCBpcyBkb2VzIG5vdCBhbGxvdyBidWxrIGluc2VydGlvbiBvZiBkYXRhIHZpYSBgZGJXcml0ZVRhYmxlKClgLCBidXQgKmZyZWVteXNxbGhvc3RpbmcqIGRvZXMgc3VwcG9ydCBidWxrIGxvYWRpbmcgYXMgZGVtb25zdHJhdGVkIGluIHRoZSBleGFtcGxlIGJlbG93LgoKYGBge3IgZXZhbD1GfQpkZiA8LSBkYXRhLmZyYW1lKGNpZCA9IDkwMDA6OTk5OSkKCmRmJHRpdGxlIDwtICJubyB0aXRsZSIKZGYkY3JlZGl0cyA8LSA0CgpzdGF0dXMgPC0gZGJXcml0ZVRhYmxlKG15ZGIuZmgsICJjb3Vyc2VzIiwgZGYsIAogICAgICAgICAgICAgICAgICAgICAgIG92ZXJ3cml0ZSA9IEYsIGFwcGVuZCA9IFQsIAogICAgICAgICAgICAgICAgICAgICAgIHJvdy5uYW1lcz1GQUxTRSkKYGBgCgpOb3RlIHRoYXQgdGhlIG5ldyByb3dzIGhhdmUgYmVlbiBpbnNlcnRlZDoKCmBgYHtzcWwgY29ubmVjdGlvbj1teWRiLmZofQpzZWxlY3QgY291bnQoKikgZnJvbSBjb3Vyc2VzOwpgYGAKCmBgYHtyfQpzdGF0dXMgPC0gZGJEaXNjb25uZWN0KG15ZGIuZmgpCmBgYAoKIyMjIyBDb21tb24gUHJvYmxlbXMKCi0gICB0aGUgZnJlZSBhY2NvdW50IGhhcyBhIG1heGltdW0gZGF0YWJhc2UgY2FwYWNpdHkgb2YgNU1CCi0gICBsb2NhbCBmaXJld2FsbCBvciBhbnRpLXZpcnVzIHNvZnR3YXJlIHRoYXQgYmxvY2tzIHBvcnQgMzMwNjsgZGlzYWJsZSBpZiB0aGVyZSBhcmUgY29ubmVjdGlvbiBpc3N1ZXMKCiMjIERpc2Nvbm5lY3QgZnJvbSBEYXRhYmFzZQoKRGlzY29ubmVjdCBmcm9tIHRoZSBkYXRhYmFzZSAoaW1wb3J0YW50IGFzIGRhdGFiYXNlIHNlcnZlcnMgaGF2ZSBsaW1pdGVkIG51bWJlcnMgb2YgY29ubmVjdGlvbiBhbmQgZWFjaCBjb25uZWN0aW9uIHVzZXMgYSByZXNvdXJjZSkuIFVzZSBgZGJEaXNjb25uZWN0KClgLgoKIyMgTXlTUUwgV29ya2JlbmNoCgpNeVNRTCBXb3JrYmVuY2ggWW91IHNob3VsZCBhbHdheXMgaW5zdGFsbCBNeVNRTCBXb3JrYmVuY2ggKExpbmtzIHRvIGFuIGV4dGVybmFsIHNpdGUuKSB0byBoZWxwIGFkbWluaXN0ZXIgYW55IGxvY2FsIG9yIHJlbW90ZSBkYXRhYmFzZS4gVXNlIHRoZSBzYW1lIGNvbm5lY3Rpb24gaW5mb3JtYXRpb24gdG8gY29ubmVjdCB0byB5b3VyIGRhdGFiYXNlLgoKIyMjIEFib3V0IE15U1FMIFdvcmtiZW5jaAoKRnJvbSB0aGUgY3JlYXRvcnMgb2YgTXlTUUwgV29ya2JlbmNoLi4uCgpNeVNRTCBXb3JrYmVuY2ggaXMgYSB1bmlmaWVkIHZpc3VhbCB0b29sIGZvciBkYXRhYmFzZSBhcmNoaXRlY3RzLCBkZXZlbG9wZXJzLCBhbmQgREJBcy4gTXlTUUwgV29ya2JlbmNoIHByb3ZpZGVzIGRhdGEgbW9kZWxpbmcsIFNRTCBkZXZlbG9wbWVudCwgYW5kIGNvbXByZWhlbnNpdmUgYWRtaW5pc3RyYXRpb24gdG9vbHMgZm9yIHNlcnZlciBjb25maWd1cmF0aW9uLCB1c2VyIGFkbWluaXN0cmF0aW9uLCBiYWNrdXAsIGFuZCBtdWNoIG1vcmUuIE15U1FMIFdvcmtiZW5jaCBpcyBhdmFpbGFibGUgb24gV2luZG93cywgTGludXggYW5kIE1hYyBPUyBYLgoKIyMjIERlc2lnbgoKTXlTUUwgV29ya2JlbmNoIGVuYWJsZXMgYSBEQkEsIGRldmVsb3Blciwgb3IgZGF0YSBhcmNoaXRlY3QgdG8gdmlzdWFsbHkgZGVzaWduLCBtb2RlbCwgZ2VuZXJhdGUsIGFuZCBtYW5hZ2UgZGF0YWJhc2VzLiBJdCBpbmNsdWRlcyBldmVyeXRoaW5nIGEgZGF0YSBtb2RlbGVyIG5lZWRzIGZvciBjcmVhdGluZyBjb21wbGV4IEVSIG1vZGVscywgZm9yd2FyZCBhbmQgcmV2ZXJzZSBlbmdpbmVlcmluZywgYW5kIGFsc28gZGVsaXZlcnMga2V5IGZlYXR1cmVzIGZvciBwZXJmb3JtaW5nIGRpZmZpY3VsdCBjaGFuZ2UgbWFuYWdlbWVudCBhbmQgZG9jdW1lbnRhdGlvbiB0YXNrcyB0aGF0IG5vcm1hbGx5IHJlcXVpcmUgbXVjaCB0aW1lIGFuZCBlZmZvcnQuCgojIyMgRGV2ZWxvcAoKTXlTUUwgV29ya2JlbmNoIGRlbGl2ZXJzIHZpc3VhbCB0b29scyBmb3IgY3JlYXRpbmcsIGV4ZWN1dGluZywgYW5kIG9wdGltaXppbmcgU1FMIHF1ZXJpZXMuIFRoZSBTUUwgRWRpdG9yIHByb3ZpZGVzIGNvbG9yIHN5bnRheCBoaWdobGlnaHRpbmcsIGF1dG8tY29tcGxldGUsIHJldXNlIG9mIFNRTCBzbmlwcGV0cywgYW5kIGV4ZWN1dGlvbiBoaXN0b3J5IG9mIFNRTC4gVGhlIERhdGFiYXNlIENvbm5lY3Rpb25zIFBhbmVsIGVuYWJsZXMgZGV2ZWxvcGVycyB0byBlYXNpbHkgbWFuYWdlIHN0YW5kYXJkIGRhdGFiYXNlIGNvbm5lY3Rpb25zLCBpbmNsdWRpbmcgTXlTUUwgRmFicmljLiBUaGUgT2JqZWN0IEJyb3dzZXIgcHJvdmlkZXMgaW5zdGFudCBhY2Nlc3MgdG8gZGF0YWJhc2Ugc2NoZW1hIGFuZCBvYmplY3RzLgoKIyMjIEFkbWluaXN0ZXIKCk15U1FMIFdvcmtiZW5jaCBwcm92aWRlcyBhIHZpc3VhbCBjb25zb2xlIHRvIGVhc2lseSBhZG1pbmlzdGVyIE15U1FMIGVudmlyb25tZW50cyBhbmQgZ2FpbiBiZXR0ZXIgdmlzaWJpbGl0eSBpbnRvIGRhdGFiYXNlcy4gRGV2ZWxvcGVycyBhbmQgREJBcyBjYW4gdXNlIHRoZSB2aXN1YWwgdG9vbHMgZm9yIGNvbmZpZ3VyaW5nIHNlcnZlcnMsIGFkbWluaXN0ZXJpbmcgdXNlcnMsIHBlcmZvcm1pbmcgYmFja3VwIGFuZCByZWNvdmVyeSwgaW5zcGVjdGluZyBhdWRpdCBkYXRhLCBhbmQgdmlld2luZyBkYXRhYmFzZSBoZWFsdGguCgojIyMgRGF0YWJhc2UgTWlncmF0aW9uCgpNeVNRTCBXb3JrYmVuY2ggbm93IHByb3ZpZGVzIGEgY29tcGxldGUsIGVhc3kgdG8gdXNlIHNvbHV0aW9uIGZvciBtaWdyYXRpbmcgTWljcm9zb2Z0IFNRTCBTZXJ2ZXIsIE1pY3Jvc29mdCBBY2Nlc3MsIFN5YmFzZSBBU0UsIFBvc3RyZVNRTCwgYW5kIG90aGVyIFJEQk1TIHRhYmxlcywgb2JqZWN0cyBhbmQgZGF0YSB0byBNeVNRTC4gRGV2ZWxvcGVycyBhbmQgREJBcyBjYW4gcXVpY2tseSBhbmQgZWFzaWx5IGNvbnZlcnQgZXhpc3RpbmcgYXBwbGljYXRpb25zIHRvIHJ1biBvbiBNeVNRTCBib3RoIG9uIFdpbmRvd3MgYW5kIG90aGVyIHBsYXRmb3Jtcy4gTWlncmF0aW9uIGFsc28gc3VwcG9ydHMgbWlncmF0aW5nIGZyb20gZWFybGllciB2ZXJzaW9ucyBvZiBNeVNRTCB0byB0aGUgbGF0ZXN0IHJlbGVhc2VzLgoKYGBgez1odG1sfQo8aWZyYW1lIHNyYz0iaHR0cHM6Ly93d3cueW91dHViZS5jb20vZW1iZWQvWF91bVlLcUthRjAiIHdpZHRoPSI0ODAiIGhlaWdodD0iMjcwIiBhbGxvd2Z1bGxzY3JlZW49ImFsbG93ZnVsbHNjcmVlbiIgYWxsb3c9ImFjY2VsZXJvbWV0ZXI7IGF1dG9wbGF5OyBjbGlwYm9hcmQtd3JpdGU7IGVuY3J5cHRlZC1tZWRpYTsgZ3lyb3Njb3BlOyBwaWN0dXJlLWluLXBpY3R1cmUid2lkdGg9IjQ4MCIgaGVpZ2h0PSIyNzAiIHRpdGxlPSJkYjRmcmVlIGluIFIiIGRhdGEtZXh0ZXJuYWw9IjEiPjwvaWZyYW1lPgpgYGAKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMgRmlsZXMgJiBSZXNvdXJjZXMKCmBgYHtyIHppcEZpbGVzLCBlY2hvPUZBTFNFfQp6aXBOYW1lID0gc3ByaW50ZigiTGVzc29uRmlsZXMtJXMtJXMuemlwIiwgCiAgICAgICAgICAgICAgICAgcGFyYW1zJGNhdGVnb3J5LAogICAgICAgICAgICAgICAgIHBhcmFtcyRudW1iZXIpCgp0ZXh0QUxpbmsgPSBwYXN0ZTAoIkFsbCBGaWxlcyBmb3IgTGVzc29uICIsIAogICAgICAgICAgICAgICBwYXJhbXMkY2F0ZWdvcnksIi4iLHBhcmFtcyRudW1iZXIpCgojIGRvd25sb2FkRmlsZXNMaW5rKCkgaXMgaW5jbHVkZWQgZnJvbSBfaW5zZXJ0MkRCLlIKa25pdHI6OnJhd19odG1sKGRvd25sb2FkRmlsZXNMaW5rKCIuIiwgemlwTmFtZSwgdGV4dEFMaW5rKSkKYGBgCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMjIFJlZmVyZW5jZXMKCk5vbmUuCgojIyBFcnJhdGEKCk5vbmUgY29sbGVjdGVkIHlldC4gTGV0IHVzIGtub3cuCgpgYGB7PWh0bWx9CjxzY3JpcHQgc3JjPSJodHRwczovL2Zvcm0uam90Zm9ybS5jb20vc3RhdGljL2ZlZWRiYWNrMi5qcyIgdHlwZT0idGV4dC9qYXZhc2NyaXB0Ij4KICBuZXcgSm90Zm9ybUZlZWRiYWNrKHsKICAgIGZvcm1JZDogIjIxMjE4NzA3Mjc4NDE1NyIsCiAgICBidXR0b25UZXh0OiAiRmVlZGJhY2siLAogICAgYmFzZTogImh0dHBzOi8vZm9ybS5qb3Rmb3JtLmNvbS8iLAogICAgYmFja2dyb3VuZDogIiNGNTkyMDIiLAogICAgZm9udENvbG9yOiAiI0ZGRkZGRiIsCiAgICBidXR0b25TaWRlOiAibGVmdCIsCiAgICBidXR0b25BbGlnbjogImNlbnRlciIsCiAgICB0eXBlOiBmYWxzZSwKICAgIHdpZHRoOiA3MDAsCiAgICBoZWlnaHQ6IDUwMCwKICAgIGlzQ2FyZEZvcm06IGZhbHNlCiAgfSk7Cjwvc2NyaXB0PgpgYGAKYGBge3IgY29kZT14ZnVuOjpyZWFkX3V0ZjgocGFzdGUwKGhlcmU6OmhlcmUoKSwnL1IvX2RlcGxveUtuaXQuUicpKSwgaW5jbHVkZSA9IEZBTFNFfQpgYGAK