Prelimaries

We will the two basic examples for a dense and sparse array simply to create array data on disk to refer to later in examples that follow.

library(tiledb)

tdir <- tempdir()
uridense <- file.path(tdir, "dense")
uridensefix <- file.path(tdir, "densefix")
uridensevar <- file.path(tdir, "densevar")

create_array <- function(array_name) {
    # Check if the array already exists.
    if (tiledb_object_type(array_name) == "ARRAY") {
        message("Array already exists.")
        return(invisible(NULL))
    }

    # The array will be 4x4 with dimensions "rows" and "cols", with domain [1,4].
    dom <- tiledb_domain(dims = c(tiledb_dim("rows", c(1L, 4L), 4L, "INT32"),
                                  tiledb_dim("cols", c(1L, 4L), 4L, "INT32")))

    # The array will be dense with a single attribute "a" so each (i,j) cell can store an integer.
    schema <- tiledb_array_schema(dom, attrs = tiledb_attr("a", type = "INT32"))

    # Create the (empty) array on disk.
    tiledb_array_create(array_name, schema)
}

write_array <- function(array_name) {
    data <- array(c(c(1L, 5L, 9L, 13L),
                    c(2L, 6L, 10L, 14L),
                    c(3L, 7L, 11L, 15L),
                    c(4L, 8L, 12L, 16L)), dim = c(4,4))
    # Open the array and write to it.
    A <- tiledb_dense(uri = array_name)
    A[] <- data
}

create_array(uridense)
[1] "/tmp/RtmpHlDB1J/dense"
write_array(uridense)


urisparse <- file.path(tdir, "sparse")

create_array <- function(array_name) {
    # Check if the array already exists.
    if (tiledb_object_type(array_name) == "ARRAY") {
        message("Array already exists.")
        return(invisible(NULL))
    }

    # The array will be 4x4 with dimensions "rows" and "cols", with domain [1,4].
    dom <- tiledb_domain(dims = c(tiledb_dim("rows", c(1L, 4L), 4L, "INT32"),
                                  tiledb_dim("cols", c(1L, 4L), 4L, "INT32")))

    # The array will be dense with a single attribute "a" so each (i,j) cell can store an integer.
    schema = tiledb_array_schema(dom, attrs=tiledb_attr("a", type = "INT32"), sparse = TRUE)

    # Create the (empty) array on disk.
    tiledb_array_create(array_name, schema)
}

write_array <- function(array_name) {
    I <- c(1, 2, 2)
    J <- c(1, 4, 3)
    data <- c(1L, 2L, 3L)
    # Open the array and write to it.
    A <- tiledb_sparse(uri = array_name)
    A[I, J] <- data
}

create_array(urisparse)
[1] "/tmp/RtmpHlDB1J/sparse"
write_array(urisparse)

close_and_reopen <- function(arr, txt) {
  res <- tiledb:::libtiledb_array_close(arr@ptr)
  res <- tiledb:::libtiledb_array_open_with_ptr(arr@ptr, txt)
}

API Usage

Creating Arrays

Create Dimension

library(tiledb)

# Create dimension
# In C++: Dimension::create<T>(...)
dim <- tiledb_dim("dim", c(1L, 4L), 2L, "INT32")

Create Array Domain

library(tiledb)

#  .. create dimensions `dim1`, `dim2`
dim1 <- tiledb_dim("dim1", c(1L, 4L), 2L, "INT32")
dim2 <- tiledb_dim("dim2", c(1L, 2L), 2L, "INT32")

# Create domain with two dimensions
# In C++: domain.add_dimensions(dim1).add_dimension(dim2)
dom <- tiledb_domain(dims = c(dim1, dim2))

Creating Attributes

# Create attribute
# In C++: Attribute::create<T>(ctx, "attr")
attr <- tiledb_attr("attr", "INT32")
# We can also set the number of attributes to a value other than one
tiledb:::libtiledb_attribute_set_cell_val_num(attr@ptr, 3)

# And we can set the a variable number of attributes (using NA to select variable size)
tiledb:::libtiledb_attribute_set_cell_val_num(attr@ptr, NA)
## TODO: R function for level setter

Setting a Compressor

comp <- tiledb_filter("GZIP")
tiledb_filter_set_option(comp,"COMPRESSION_LEVEL", 10)

# Create a filter list with the compressor
filter_list <- tiledb_filter_list(comp)

# Create attribute with the filter list
attr <- tiledb_attr("attr", "INT32", filter_list = filter_list)

Setting Other Filters

# Create filters
f1 <- tiledb_filter("BIT_WIDTH_REDUCTION")
f2 <- tiledb_filter("ZSTD")

# Create a filter list with the two filters
filter_list <- tiledb_filter_list(c(f1,f2))

# Create attribute with the filter list
attr <- tiledb_attr("attr", "INT32", filter_list = filter_list)

Setting the Tile Chunk Size

# ... create filter list
set_max_chunk_size(filter_list, 10000)

Creating the Array Schema

# ... create domain dom
attr1 <- tiledb_attr("attr1", "INT32", filter_list = filter_list)
attr2 <- tiledb_attr("attr2", "FLOAT64", filter_list = filter_list)

# Create a dense array
schema <- tiledb_array_schema(dom, c(attr1, attr2), sparse = FALSE)
# Or, create a spaese array
# schema <- tiledb_array_schema(dom, c(attr1, attr2), sparse = TRUE)

Setting the Tile and Cell Order

# ... create domain dom
# ... create attributes attr1, attr2

# The tile and order can be "ROW_MAJOR" or "COL_MAJOR"
schema <- tiledb_array_schema(dom, c(attr1, attr2),
                              cell_order = "COL_MAJOR",
                              tile_order = "ROW_MAJOR")

Setting the Data Tile Capacity

tiledb:::libtiledb_array_schema_set_capacity(schema@ptr, 100000)
tiledb:::libtiledb_array_schema_get_capacity(schema@ptr)
[1] 100000
## TODO higher-level R functions

Setting Coordinate and Offset Filters

# ... create domain dom
# ... create attributes attr1, attr2
# ... create filter lists fl1, fl2, similar to attributes
f1 <- tiledb_filter("BIT_WIDTH_REDUCTION")
f2 <- tiledb_filter("ZSTD")
fl1 <- tiledb_filter_list(c(f1))
fl2 <- tiledb_filter_list(c(f2))

# Create the schema setting the coordinates and offsets filter lists
schema <- tiledb_array_schema(dom, c(attr1, attr2),
                              coords_filter_list = fl1,
                              offsets_filter_list = fl2)

Checking Correctness

tiledb:::libtiledb_array_schema_check(schema@ptr)
## TODO higher-level R functions

Creating the Array

# ... create array schema

# Create the array
tiledb_array_create(uridense, schema)

Creating Encrypted Arrays

encryption_key <- "0123456789abcdeF0123456789abcdeF"
uridensewkey <- file.path(tdir, "densewkey")
if (dir.exists(uridensewkey)) unlink(uridensewkey, recursive=TRUE)

# shortcut: borrow schema from dense array; could create schema too
schema <- schema(tiledb_dense(uridense))
tiledb:::libtiledb_array_create_with_key(uridensewkey, schema@ptr, encryption_key)
[1] "/tmp/RtmpHlDB1J/densewkey"
##TODO: R support

Writing Arrays

Writing in Dense Subarrays

## prepare a larger 5 x 5 to embed into
tmp <- tempfile()
d1  <- tiledb_dim("d1", domain = c(1L, 5L))
d2  <- tiledb_dim("d2", domain = c(1L, 5L))
dom <- tiledb_domain(c(d1, d2))
val <- tiledb_attr(name="val", type = "INT32")
sch <- tiledb_array_schema(dom, c(val))
tiledb_array_create(tmp, sch)

dat <- matrix(as.integer(rnorm(25)*100), 5, 5)
arr <- tiledb_dense(tmp, as.data.frame=FALSE)
arr[] <- dat


# Prepare a 2x3 dense array
# Contrary to Python, R by default stores arrays in col-major order
data <-  array(c(1L, 4L, 2L, 5L, 3L, 6L), dim=c(2,3))

# Prepare the [1,2] x [2,4] subarray to write to
I <- c(1:2)
J <- c(2:4)

# Open the array and write the data to it
A <- tiledb_dense(uri = tmp)
A[I, J] <- data

unlink(tmp, recursive=TRUE)

Basic Writing using Low-Level Code

ctx <- tiledb_ctx()
arrptr <- tiledb:::libtiledb_array_open(ctx@ptr, uridense, "WRITE")

## data: simple (integer sequence) of 1:16 times 10
vec <- 1:16 * 10L
subarr <- c(1L,4L, 1L,4L)

qryptr <- tiledb:::libtiledb_query(ctx@ptr, arrptr, "WRITE")
qryptr <- tiledb:::libtiledb_query_set_subarray(qryptr, subarr)
qryptr <- tiledb:::libtiledb_query_set_layout(qryptr, "ROW_MAJOR")
qryptr <- tiledb:::libtiledb_query_set_buffer(qryptr, "a", vec)
qryptr <- tiledb:::libtiledb_query_submit(qryptr)
res <- tiledb:::libtiledb_array_close(arrptr)

Writing Sparse Cells

tmp <- urisparse
unlink(tmp, recursive=TRUE)

d1  <- tiledb_dim("d1", domain = c(1L, 5L))
d2  <- tiledb_dim("d2", domain = c(1L, 5L))
dom <- tiledb_domain(c(d1, d2))
val <- tiledb_attr("val", type = "INT32")
sch <- tiledb_array_schema(dom, val, sparse=TRUE)
tiledb_array_create(tmp, sch)
[1] "/tmp/RtmpHlDB1J/sparse"
# Prepare some data
data <- c(3L, 4L, 1L, 2L)

I <- c(3, 4, 1, 2)
J <- c(3, 4, 2, 1)

# Open the array and write the data to it
A <- tiledb_sparse(uri = tmp)
A[I, J] <- data

Writing Encrypted Arrays

ctx <- tiledb_ctx()
arrptr <- tiledb:::libtiledb_array_open_with_key(ctx@ptr, uridensewkey, "WRITE", encryption_key)

## data: simple (integer sequence) of 1:16 times 10
vec <- 1:16 * 10L
subarr <- c(1L,4L, 1L,4L)

qryptr <- tiledb:::libtiledb_query(ctx@ptr, arrptr, "WRITE")
qryptr <- tiledb:::libtiledb_query_set_subarray(qryptr, subarr)
qryptr <- tiledb:::libtiledb_query_set_layout(qryptr, "ROW_MAJOR")
qryptr <- tiledb:::libtiledb_query_set_buffer(qryptr, "a", vec)
qryptr <- tiledb:::libtiledb_query_submit(qryptr)
res <- tiledb:::libtiledb_array_close(arrptr)
# TODO Higher-level R support

Fixed-length Attributes

if (dir.exists(uridensefix)) unlink(uridensefix, recursive=TRUE)
d1  <- tiledb_dim("d1", domain = c(1L, 4L))
d2  <- tiledb_dim("d2", domain = c(1L, 4L))
dom <- tiledb_domain(c(d1, d2))

vec <- 1:32 * 10L
attr <- tiledb_attr("a", type = r_to_tiledb_type(vec))

## set to two values per cell
tiledb:::libtiledb_attribute_set_cell_val_num(attr@ptr, 2)
sch <- tiledb_array_schema(dom, attr)
tiledb_array_create(uridensefix, sch)
[1] "/tmp/RtmpHlDB1J/densefix"
ctx <- tiledb_ctx()
arrptr <- tiledb:::libtiledb_array_open(ctx@ptr, uridensefix, "WRITE")
subarr <- c(1L,4L, 1L,4L)

qryptr <- tiledb:::libtiledb_query(ctx@ptr, arrptr, "WRITE")
qryptr <- tiledb:::libtiledb_query_set_subarray(qryptr, subarr)
qryptr <- tiledb:::libtiledb_query_set_layout(qryptr, "ROW_MAJOR")
qryptr <- tiledb:::libtiledb_query_set_buffer(qryptr, "a", vec)
qryptr <- tiledb:::libtiledb_query_submit(qryptr)
res <- tiledb:::libtiledb_array_close(arrptr)

#TODO Higher-level R support

Var-length Attributes

if (dir.exists(uridensevar)) unlink(uridensevar, recursive=TRUE)
## Define array
## The array will be 4x4 with dimensions "rows" and "cols", with domain [1,4].
dom <- tiledb_domain(dims = c(tiledb_dim("rows", c(1L, 4L), 4L, "INT32"),
                              tiledb_dim("cols", c(1L, 4L), 4L, "INT32")))


attr <- tiledb_attr("a1", type = "CHAR")
## set to variable length
tiledb:::libtiledb_attribute_set_cell_val_num(attr@ptr, NA)

## now set the schema
ctx <- tiledb_ctx()
schptr <- tiledb:::libtiledb_array_schema_create(ctx@ptr, "DENSE")
tiledb:::libtiledb_array_schema_set_domain(schptr, dom@ptr)
tiledb:::libtiledb_array_schema_set_cell_order(schptr, "ROW_MAJOR")
tiledb:::libtiledb_array_schema_set_tile_order(schptr, "ROW_MAJOR")
tiledb:::libtiledb_array_schema_add_attribute(schptr, attr@ptr)



## Create the (empty) array on disk.
tiledb:::libtiledb_array_create(uridensevar, schptr)
[1] "/tmp/RtmpHlDB1J/densevar"
data <- "abbcccddeeefghhhijjjkklmnoop";
offsets <- c(0L, 1L, 3L, 6L, 8L, 11L, 12L, 13L, 16L, 17L, 20L, 22L, 23L, 24L, 25L, 27L)

ctx <- tiledb_ctx()
arrptr <- tiledb:::libtiledb_array_open(ctx@ptr, uridensevar, "WRITE")
qryptr <- tiledb:::libtiledb_query(ctx@ptr, arrptr, "WRITE")
qryptr <- tiledb:::libtiledb_query_set_layout(qryptr, "ROW_MAJOR")

bufptr <- tiledb:::libtiledb_query_buffer_var_char_create(offsets, data)
qryptr <- tiledb:::libtiledb_query_set_buffer_var_char(qryptr, "a1", bufptr)
qryptr <- tiledb:::libtiledb_query_submit(qryptr)
tiledb:::libtiledb_array_close(arrptr)
<pointer: 0x7f256c0127e0>
#TODO Higher-level R support

Getting the Fragment Info

## continuing from previous example on dense variable length array
## (but this works of course with any array after a write is needed
numfrag <- tiledb:::libtiledb_query_get_fragment_num(qryptr)
uritxt <- tiledb:::libtiledb_query_get_fragment_uri(qryptr, 0)

##TODO Higher-level R support

Reading Arrays

Reading the Array Schema

array_name <- urisparse
A <- tiledb_sparse(uri = array_name)
# can also load dense
sch <- schema(A)
# can also open encrypted arrays with key

Inspecting the array schema

array_name <- urisparse

# Get array schema
A <- tiledb_sparse(uri = array_name)
# or use tiledb_dense(uri = array_name) for dense
schema <- schema(A)

# Get array type
sparse <- is.sparse(schema)

# Get tile capacity
tiledb:::libtiledb_array_schema_get_capacity(sch@ptr)
[1] 10000
# TODO: R accessor for tile

# Get tile order
t_order <- tile_order(schema)

# Get cell order
c_order <- cell_order(schema)

# Get coordinates and offset filter list
reslist <- filter_list(schema)

# Get the array domain
dom <- domain(schema)

# Get all attributes as list
attrs <- attrs(schema)

# Get attribute from name
attr <- attrs(schema, "attr")

# Dump the array schema in ASCII format to stdout
show(schema)
- Array type: sparse
- Cell order: col-major
- Tile order: col-major
- Capacity: 10000
- Coordinates compressor: ZSTD
- Coordinates compression level: -1

=== Domain ===
- Dimensions type: INT32

### Dimension ###
- Name: d1
- Domain: [1,5]
- Tile extent: 5

### Dimension ###
- Name: d2
- Domain: [1,5]
- Tile extent: 5

### Attribute ###
- Name: val
- Type: INT32
- Compressor: NO_COMPRESSION
- Compression level: -1
- Cell val num: 1

Inspecting Domain

# ... get array schema
# ... get domain from schema
dom <- domain(schema)

# Get the domain datatype (i.e., the datatype of all dimensions)
type <- datatype(dom)

# Get number of dimensions
dim_num <- dim(dom)

# Get all dimension
dims <- dimensions(dom)

# Dump the domain in ASCII format in the selected output
show(dom)
=== Domain ===
- Dimensions type: INT32

### Dimension ###
- Name: d1
- Domain: [1,5]
- Tile extent: 5

### Dimension ###
- Name: d2
- Domain: [1,5]
- Tile extent: 5

Inspecting Dimensions

# ... get array schema
# ... get domain
# ... get dimension by index or name

#FIXME

# Get dimension name
dim_name <- name(dim)

# Get dimension datatype
dim_type <- datatype(dim)

# Get dimension domain
domain <- domain(dim)

# Get tile extent
tile_extent <- tile(dim)

# Dump the dimension in ASCII format in the selected output
show(dim)

Inspecting Attributes

# ... get array schema
# ... get attribute by index or name

stopifnot(is.null(attr))
# Get attribute name
attr_name <- name(attr)

# Get attribute datatype
attr_type <- datatype(attr)

# Get filter list
filter_list <- filter_list(attr)

# Check if attribute is variable-length
# variable length attribtues are not supported in R currently

# Get number of values per cell
num <- ncells(attr)

# Get cell size for this attribute
sz <-- tiledb:::libtiledb_attribute_get_cell_val(attr@ptr)

# Dump the attribute in ASCII format in the selected output
show(attr)

Inspecting Filters

fl <- tiledb_filter_list()

# get number of filter
tiledb:::libtiledb_filter_list_get_nfilters(fl@ptr)

# get max chunk size
tiledb:::libtiledb_filter_list_get_max_chunk_size(fl@ptr)

# get filter from index
ind <- i
tiledb:::libtiledb_filter_list_get_filter_from_index(fl@ptr, ind)

Basic Reading

# Create a TileDB context
ctx <- tiledb_ctx()

# Open a dense array
A <- tiledb_dense(uri = uridense, ctx=ctx)

# Or, open a sparse array
# A <- tiledb_sparse(uri = "<array-uri>", ctx=ctx)

# Slice only rows 1, 2 and cols 2, 3, 4
data <- A[1:2, 2:4]
show(data)
     [,1] [,2] [,3]
[1,]   20   30   40
[2,]   60   70   80

Basic Reading using Low-Level Code

ctx <- tiledb_ctx()
arrptr <- tiledb:::libtiledb_array_open(ctx@ptr, uridense, "READ")
## subarray of rows 1,2 and cols 2,3,4
subarr <- c(1L,2L, 2L,4L)

qryptr <- tiledb:::libtiledb_query(ctx@ptr, arrptr, "READ")
qryptr <- tiledb:::libtiledb_query_set_subarray(qryptr, subarr)
qryptr <- tiledb:::libtiledb_query_set_layout(qryptr, "ROW_MAJOR")
v <- integer(6)  # reserve space
qryptr <- tiledb:::libtiledb_query_set_buffer(qryptr, "a", v)
qryptr <- tiledb:::libtiledb_query_submit(qryptr)
print(v)         # unformed array, no coordinates
[1] 20 30 40 60 70 80
res <- tiledb:::libtiledb_array_close(arrptr)

Variable-length Attributes

arrptr <- tiledb:::libtiledb_array_open(ctx@ptr, uridensevar, "READ")

subarr <- c(1L,4L, 1L,4L)
bufptr <- tiledb:::libtiledb_query_buffer_var_char_alloc(arrptr, subarr, "a1", 16, 100)

qryptr <- tiledb:::libtiledb_query(ctx@ptr, arrptr, "READ")
qryptr <- tiledb:::libtiledb_query_set_subarray(qryptr, subarr)
qryptr <- tiledb:::libtiledb_query_set_layout(qryptr, "ROW_MAJOR")

qryptr <- tiledb:::libtiledb_query_set_buffer_var_char(qryptr, "a1", bufptr)
qryptr <- tiledb:::libtiledb_query_submit(qryptr)
tiledb:::libtiledb_array_close(arrptr)
<pointer: 0x7f256c002c70>
mat <- tiledb:::libtiledb_query_get_buffer_var_char(bufptr)
print(mat, quote=FALSE)
     [,1] [,2] [,3] [,4]
[1,] a    eee  i    m   
[2,] bb   f    jjj  n   
[3,] ccc  g    kk   oo  
[4,] dd   hhh  l    p   

Getting the Non-empty Domain

arrptr <- tiledb:::libtiledb_array_open(ctx@ptr, uridensevar, "READ")
# returns a list object
reslist <- tiledb:::libtiledb_array_nonempty_domain(arrptr)
tiledb:::libtiledb_array_close(arrptr)
<pointer: 0x7f256c0160a0>

Reading Encrypted Arrays

ctx <- tiledb_ctx()
arrptr <- tiledb:::libtiledb_array_open_with_key(ctx@ptr, uridensewkey, "READ", encryption_key)

## subarray of rows 1,2 and cols 2,3,4
subarr <- c(1L,2L, 2L,4L)

qryptr <- tiledb:::libtiledb_query(ctx@ptr, arrptr, "READ")
qryptr <- tiledb:::libtiledb_query_set_subarray(qryptr, subarr)
qryptr <- tiledb:::libtiledb_query_set_layout(qryptr, "ROW_MAJOR")
v <- integer(6)  # reserve space
qryptr <- tiledb:::libtiledb_query_set_buffer(qryptr, "a", v)
qryptr <- tiledb:::libtiledb_query_submit(qryptr)
print(v)         # unformed array, no coordinates
[1] 20 30 40 60 70 80
res <- tiledb:::libtiledb_array_close(arrptr)

## TODO open at timestamp example

Multi-range Subarrays

ctx <- tiledb_ctx()
arrptr <- tiledb:::libtiledb_array_open(ctx@ptr, uridense, "READ")

qryptr <- tiledb:::libtiledb_query(ctx@ptr, arrptr, "READ")

## range of rows 1 and 2, and 4 for dim 1, all rows for dim 2
qryptr <- tiledb:::libtiledb_query_add_range(qryptr, 0, 1L, 2L)
qryptr <- tiledb:::libtiledb_query_add_range(qryptr, 0, 4L, 4L)
qryptr <- tiledb:::libtiledb_query_add_range(qryptr, 1, 1L, 4L)

qryptr <- tiledb:::libtiledb_query_set_layout(qryptr, "ROW_MAJOR")
v <- integer(12)  # reserve space
qryptr <- tiledb:::libtiledb_query_set_buffer(qryptr, "a", v)
qryptr <- tiledb:::libtiledb_query_submit(qryptr)
print(v)         # unformed array, no coordinates
 [1]  10  20  30  40  50  60  70  80 130 140 150 160
res <- tiledb:::libtiledb_array_close(arrptr)

Incomplete Queries

ctx <- tiledb_ctx()
arrptr <- tiledb:::libtiledb_array_open(ctx@ptr, uridense, "READ")
qryptr <- tiledb:::libtiledb_query(ctx@ptr, arrptr, "READ")
subarr <- c(1L,4L, 1L,4L)
qryptr <- tiledb:::libtiledb_query_set_subarray(qryptr, subarr)
vec <- integer(4)  # reserve (insufficient) space
qryptr <- tiledb:::libtiledb_query_set_buffer(qryptr, "a", vec)
finished <- FALSE
while (!finished) {
  qryptr <- tiledb:::libtiledb_query_submit(qryptr)
  print(vec)
  finished <- tiledb:::libtiledb_query_status(qryptr) == "COMPLETE"
}
[1] 10 20 30 40
[1] 50 60 70 80
[1]  90 100 110 120
[1] 130 140 150 160
res <- tiledb:::libtiledb_array_close(arrptr)

Result Estimation

ctx <- tiledb_ctx()
arrptr <- tiledb:::libtiledb_array_open(ctx@ptr, uridensevar, "READ")
qryptr <- tiledb:::libtiledb_query(ctx@ptr, arrptr, "READ")
estsz <- tiledb:::libtiledb_query_get_est_result_size_var(qryptr, "a1")
res <- tiledb:::libtiledb_array_close(arrptr)
estsz
[1] 16 28

Time Traveling

ctx <- tiledb_ctx()
tstamp <- Sys.time() - 1.0; # one seconds ago (as the arrays created here are in temp.files)
arrptr <- tiledb:::libtiledb_array_open_at(ctx@ptr, uridense, "READ", tstamp)
subarr <- c(1L,2L, 2L,4L)
qryptr <- tiledb:::libtiledb_query(ctx@ptr, arrptr, "READ")
qryptr <- tiledb:::libtiledb_query_set_subarray(qryptr, subarr)
qryptr <- tiledb:::libtiledb_query_set_layout(qryptr, "ROW_MAJOR")
v <- integer(6)  # reserve space
qryptr <- tiledb:::libtiledb_query_set_buffer(qryptr, "a", v)
qryptr <- tiledb:::libtiledb_query_submit(qryptr)
res <- tiledb:::libtiledb_array_close(arrptr)
v
[1] 0 0 0 0 0 0

Embedded SQL

Asynchronous Queries

Configuration

Array Metadata

Writing Array Metadata

arr <- tiledb_dense(uridense)
close_and_reopen(arr, "WRITE")
res <- tiledb_put_metadata(arr, "aaa", 100L)
res <- tiledb_put_metadata(arr, "bb", c(1.1, 2.2))
invisible(tiledb:::libtiledb_array_close(arr@ptr))

Reading Array Metadata

One can read by key:

close_and_reopen(arr, "READ")
tiledb_get_metadata(arr, "aaa")
[1] 100

Or one can retrieve all metadata at once:

md <- tiledb_get_all_metadata(arr)
print(md)
aaa:    100
bb: 1.1, 2.2

Deleting Array Metadata

close_and_reopen(arr, "WRITE")
res <- tiledb_delete_metadata(arr, "aaa")
LS0tCnRpdGxlOiAiVGlsZURCIFIgTm90ZWJvb2siCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKICAgIGRmX3ByaW50OiBwYWdlZAogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwogICAgaGlnaGxpZ2h0OiBweWdtZW50cwogICAgdGhlbWU6IGx1bWVuCi0tLQoKPCEtLVRoaXMgaXMgYW4gW1IgTWFya2Rvd25dKGh0dHA6Ly9ybWFya2Rvd24ucnN0dWRpby5jb20pIE5vdGVib29rLiBXaGVuIHlvdSBleGVjdXRlIGNvZGUgd2l0aGluIHRoZSBub3RlYm9vaywgdGhlIHJlc3VsdHMgYXBwZWFyIGJlbmVhdGggdGhlIGNvZGUuICBUcnkgZXhlY3V0aW5nIHRoaXMgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpSdW4qIGJ1dHRvbiB3aXRoaW4gdGhlIGNodW5rIG9yIGJ5IHBsYWNpbmcgeW91ciBjdXJzb3IgaW5zaWRlIGl0IGFuZCBwcmVzc2luZyAqQ3RybCtTaGlmdCtFbnRlciouICAgQWRkIGEgbmV3IGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqSW5zZXJ0IENodW5rKiBidXR0b24gb24gdGhlIHRvb2xiYXIgb3IgYnkgcHJlc3NpbmcgKkN0cmwrQWx0K0kqLgpXaGVuIHlvdSBzYXZlIHRoZSBub3RlYm9vaywgYW4gSFRNTCBmaWxlIGNvbnRhaW5pbmcgdGhlIGNvZGUgYW5kIG91dHB1dCB3aWxsIGJlIHNhdmVkIGFsb25nc2lkZSBpdCAoY2xpY2sgdGhlICpQcmV2aWV3KiBidXR0b24gb3IgcHJlc3MgKkN0cmwrU2hpZnQrSyogdG8gcHJldmlldyB0aGUgSFRNTCBmaWxlKS4gIFRoZSBwcmV2aWV3IHNob3dzIHlvdSBhIHJlbmRlcmVkIEhUTUwgY29weSBvZiB0aGUgY29udGVudHMgb2YgdGhlIGVkaXRvci4gQ29uc2VxdWVudGx5LCB1bmxpa2UgKktuaXQqLCAqUHJldmlldyogZG9lcyBub3QgcnVuIGFueSBSIGNvZGUgY2h1bmtzLiBJbnN0ZWFkLCB0aGUgb3V0cHV0IG9mIHRoZSBjaHVuayB3aGVuIGl0IHdhcyBsYXN0IHJ1biBpbiB0aGUgZWRpdG9yIGlzIGRpc3BsYXllZC4tLT4KCiMgUHJlbGltYXJpZXMKCldlIHdpbGwgdGhlIHR3byBiYXNpYyBleGFtcGxlcyBmb3IgYSBkZW5zZSBhbmQgc3BhcnNlIGFycmF5IHNpbXBseSB0byBjcmVhdGUKYXJyYXkgZGF0YSBvbiBkaXNrIHRvIHJlZmVyIHRvIGxhdGVyIGluIGV4YW1wbGVzIHRoYXQgZm9sbG93LgoKYGBge3IgcnVuZXhhbXBsZXN9CmxpYnJhcnkodGlsZWRiKQoKdGRpciA8LSB0ZW1wZGlyKCkKdXJpZGVuc2UgPC0gZmlsZS5wYXRoKHRkaXIsICJkZW5zZSIpCnVyaWRlbnNlZml4IDwtIGZpbGUucGF0aCh0ZGlyLCAiZGVuc2VmaXgiKQp1cmlkZW5zZXZhciA8LSBmaWxlLnBhdGgodGRpciwgImRlbnNldmFyIikKCmNyZWF0ZV9hcnJheSA8LSBmdW5jdGlvbihhcnJheV9uYW1lKSB7CiAgICAjIENoZWNrIGlmIHRoZSBhcnJheSBhbHJlYWR5IGV4aXN0cy4KICAgIGlmICh0aWxlZGJfb2JqZWN0X3R5cGUoYXJyYXlfbmFtZSkgPT0gIkFSUkFZIikgewogICAgICAgIG1lc3NhZ2UoIkFycmF5IGFscmVhZHkgZXhpc3RzLiIpCiAgICAgICAgcmV0dXJuKGludmlzaWJsZShOVUxMKSkKICAgIH0KCiAgICAjIFRoZSBhcnJheSB3aWxsIGJlIDR4NCB3aXRoIGRpbWVuc2lvbnMgInJvd3MiIGFuZCAiY29scyIsIHdpdGggZG9tYWluIFsxLDRdLgogICAgZG9tIDwtIHRpbGVkYl9kb21haW4oZGltcyA9IGModGlsZWRiX2RpbSgicm93cyIsIGMoMUwsIDRMKSwgNEwsICJJTlQzMiIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGlsZWRiX2RpbSgiY29scyIsIGMoMUwsIDRMKSwgNEwsICJJTlQzMiIpKSkKCiAgICAjIFRoZSBhcnJheSB3aWxsIGJlIGRlbnNlIHdpdGggYSBzaW5nbGUgYXR0cmlidXRlICJhIiBzbyBlYWNoIChpLGopIGNlbGwgY2FuIHN0b3JlIGFuIGludGVnZXIuCiAgICBzY2hlbWEgPC0gdGlsZWRiX2FycmF5X3NjaGVtYShkb20sIGF0dHJzID0gdGlsZWRiX2F0dHIoImEiLCB0eXBlID0gIklOVDMyIikpCgogICAgIyBDcmVhdGUgdGhlIChlbXB0eSkgYXJyYXkgb24gZGlzay4KICAgIHRpbGVkYl9hcnJheV9jcmVhdGUoYXJyYXlfbmFtZSwgc2NoZW1hKQp9Cgp3cml0ZV9hcnJheSA8LSBmdW5jdGlvbihhcnJheV9uYW1lKSB7CiAgICBkYXRhIDwtIGFycmF5KGMoYygxTCwgNUwsIDlMLCAxM0wpLAogICAgICAgICAgICAgICAgICAgIGMoMkwsIDZMLCAxMEwsIDE0TCksCiAgICAgICAgICAgICAgICAgICAgYygzTCwgN0wsIDExTCwgMTVMKSwKICAgICAgICAgICAgICAgICAgICBjKDRMLCA4TCwgMTJMLCAxNkwpKSwgZGltID0gYyg0LDQpKQogICAgIyBPcGVuIHRoZSBhcnJheSBhbmQgd3JpdGUgdG8gaXQuCiAgICBBIDwtIHRpbGVkYl9kZW5zZSh1cmkgPSBhcnJheV9uYW1lKQogICAgQVtdIDwtIGRhdGEKfQoKY3JlYXRlX2FycmF5KHVyaWRlbnNlKQp3cml0ZV9hcnJheSh1cmlkZW5zZSkKCgp1cmlzcGFyc2UgPC0gZmlsZS5wYXRoKHRkaXIsICJzcGFyc2UiKQoKY3JlYXRlX2FycmF5IDwtIGZ1bmN0aW9uKGFycmF5X25hbWUpIHsKICAgICMgQ2hlY2sgaWYgdGhlIGFycmF5IGFscmVhZHkgZXhpc3RzLgogICAgaWYgKHRpbGVkYl9vYmplY3RfdHlwZShhcnJheV9uYW1lKSA9PSAiQVJSQVkiKSB7CiAgICAgICAgbWVzc2FnZSgiQXJyYXkgYWxyZWFkeSBleGlzdHMuIikKICAgICAgICByZXR1cm4oaW52aXNpYmxlKE5VTEwpKQogICAgfQoKICAgICMgVGhlIGFycmF5IHdpbGwgYmUgNHg0IHdpdGggZGltZW5zaW9ucyAicm93cyIgYW5kICJjb2xzIiwgd2l0aCBkb21haW4gWzEsNF0uCiAgICBkb20gPC0gdGlsZWRiX2RvbWFpbihkaW1zID0gYyh0aWxlZGJfZGltKCJyb3dzIiwgYygxTCwgNEwpLCA0TCwgIklOVDMyIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aWxlZGJfZGltKCJjb2xzIiwgYygxTCwgNEwpLCA0TCwgIklOVDMyIikpKQoKICAgICMgVGhlIGFycmF5IHdpbGwgYmUgZGVuc2Ugd2l0aCBhIHNpbmdsZSBhdHRyaWJ1dGUgImEiIHNvIGVhY2ggKGksaikgY2VsbCBjYW4gc3RvcmUgYW4gaW50ZWdlci4KICAgIHNjaGVtYSA9IHRpbGVkYl9hcnJheV9zY2hlbWEoZG9tLCBhdHRycz10aWxlZGJfYXR0cigiYSIsIHR5cGUgPSAiSU5UMzIiKSwgc3BhcnNlID0gVFJVRSkKCiAgICAjIENyZWF0ZSB0aGUgKGVtcHR5KSBhcnJheSBvbiBkaXNrLgogICAgdGlsZWRiX2FycmF5X2NyZWF0ZShhcnJheV9uYW1lLCBzY2hlbWEpCn0KCndyaXRlX2FycmF5IDwtIGZ1bmN0aW9uKGFycmF5X25hbWUpIHsKICAgIEkgPC0gYygxLCAyLCAyKQogICAgSiA8LSBjKDEsIDQsIDMpCiAgICBkYXRhIDwtIGMoMUwsIDJMLCAzTCkKICAgICMgT3BlbiB0aGUgYXJyYXkgYW5kIHdyaXRlIHRvIGl0LgogICAgQSA8LSB0aWxlZGJfc3BhcnNlKHVyaSA9IGFycmF5X25hbWUpCiAgICBBW0ksIEpdIDwtIGRhdGEKfQoKY3JlYXRlX2FycmF5KHVyaXNwYXJzZSkKd3JpdGVfYXJyYXkodXJpc3BhcnNlKQoKY2xvc2VfYW5kX3Jlb3BlbiA8LSBmdW5jdGlvbihhcnIsIHR4dCkgewogIHJlcyA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfY2xvc2UoYXJyQHB0cikKICByZXMgPC0gdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X29wZW5fd2l0aF9wdHIoYXJyQHB0ciwgdHh0KQp9CmBgYAoKCgojIEFQSSBVc2FnZQoKIyMgQ3JlYXRpbmcgQXJyYXlzCgojIyMgQ3JlYXRlIERpbWVuc2lvbgoKYGBge3IgY3JlYXRlZGltfQpsaWJyYXJ5KHRpbGVkYikKCiMgQ3JlYXRlIGRpbWVuc2lvbgojIEluIEMrKzogRGltZW5zaW9uOjpjcmVhdGU8VD4oLi4uKQpkaW0gPC0gdGlsZWRiX2RpbSgiZGltIiwgYygxTCwgNEwpLCAyTCwgIklOVDMyIikKYGBgCgoKIyMjIENyZWF0ZSBBcnJheSBEb21haW4KCmBgYHtyIGNyZWF0YXJyZG9tfQpsaWJyYXJ5KHRpbGVkYikKCiMgIC4uIGNyZWF0ZSBkaW1lbnNpb25zIGBkaW0xYCwgYGRpbTJgCmRpbTEgPC0gdGlsZWRiX2RpbSgiZGltMSIsIGMoMUwsIDRMKSwgMkwsICJJTlQzMiIpCmRpbTIgPC0gdGlsZWRiX2RpbSgiZGltMiIsIGMoMUwsIDJMKSwgMkwsICJJTlQzMiIpCgojIENyZWF0ZSBkb21haW4gd2l0aCB0d28gZGltZW5zaW9ucwojIEluIEMrKzogZG9tYWluLmFkZF9kaW1lbnNpb25zKGRpbTEpLmFkZF9kaW1lbnNpb24oZGltMikKZG9tIDwtIHRpbGVkYl9kb21haW4oZGltcyA9IGMoZGltMSwgZGltMikpCmBgYAoKIyMjIENyZWF0aW5nIEF0dHJpYnV0ZXMKCmBgYHtyIGNyZWF0ZWF0dHJ9CiMgQ3JlYXRlIGF0dHJpYnV0ZQojIEluIEMrKzogQXR0cmlidXRlOjpjcmVhdGU8VD4oY3R4LCAiYXR0ciIpCmF0dHIgPC0gdGlsZWRiX2F0dHIoImF0dHIiLCAiSU5UMzIiKQpgYGAKCmBgYHtyIGNyZWF0ZWF0dHJ2YXJudW19CiMgV2UgY2FuIGFsc28gc2V0IHRoZSBudW1iZXIgb2YgYXR0cmlidXRlcyB0byBhIHZhbHVlIG90aGVyIHRoYW4gb25lCnRpbGVkYjo6OmxpYnRpbGVkYl9hdHRyaWJ1dGVfc2V0X2NlbGxfdmFsX251bShhdHRyQHB0ciwgMykKCiMgQW5kIHdlIGNhbiBzZXQgdGhlIGEgdmFyaWFibGUgbnVtYmVyIG9mIGF0dHJpYnV0ZXMgKHVzaW5nIE5BIHRvIHNlbGVjdCB2YXJpYWJsZSBzaXplKQp0aWxlZGI6OjpsaWJ0aWxlZGJfYXR0cmlidXRlX3NldF9jZWxsX3ZhbF9udW0oYXR0ckBwdHIsIE5BKQojIyBUT0RPOiBSIGZ1bmN0aW9uIGZvciBsZXZlbCBzZXR0ZXIKYGBgCgojIyMjIFNldHRpbmcgYSBDb21wcmVzc29yCgpgYGB7ciBzZXRjb21wcn0KY29tcCA8LSB0aWxlZGJfZmlsdGVyKCJHWklQIikKdGlsZWRiX2ZpbHRlcl9zZXRfb3B0aW9uKGNvbXAsIkNPTVBSRVNTSU9OX0xFVkVMIiwgMTApCgojIENyZWF0ZSBhIGZpbHRlciBsaXN0IHdpdGggdGhlIGNvbXByZXNzb3IKZmlsdGVyX2xpc3QgPC0gdGlsZWRiX2ZpbHRlcl9saXN0KGNvbXApCgojIENyZWF0ZSBhdHRyaWJ1dGUgd2l0aCB0aGUgZmlsdGVyIGxpc3QKYXR0ciA8LSB0aWxlZGJfYXR0cigiYXR0ciIsICJJTlQzMiIsIGZpbHRlcl9saXN0ID0gZmlsdGVyX2xpc3QpCmBgYAoKCiMjIyMgU2V0dGluZyBPdGhlciBGaWx0ZXJzCgpgYGB7ciBzZXRmaWxyfQojIENyZWF0ZSBmaWx0ZXJzCmYxIDwtIHRpbGVkYl9maWx0ZXIoIkJJVF9XSURUSF9SRURVQ1RJT04iKQpmMiA8LSB0aWxlZGJfZmlsdGVyKCJaU1REIikKCiMgQ3JlYXRlIGEgZmlsdGVyIGxpc3Qgd2l0aCB0aGUgdHdvIGZpbHRlcnMKZmlsdGVyX2xpc3QgPC0gdGlsZWRiX2ZpbHRlcl9saXN0KGMoZjEsZjIpKQoKIyBDcmVhdGUgYXR0cmlidXRlIHdpdGggdGhlIGZpbHRlciBsaXN0CmF0dHIgPC0gdGlsZWRiX2F0dHIoImF0dHIiLCAiSU5UMzIiLCBmaWx0ZXJfbGlzdCA9IGZpbHRlcl9saXN0KQpgYGAKCgojIyMjIFNldHRpbmcgdGhlIFRpbGUgQ2h1bmsgU2l6ZQoKYGBge3Igc2V0dGlsZWNodW5rc2l6ZX0KIyAuLi4gY3JlYXRlIGZpbHRlciBsaXN0CnNldF9tYXhfY2h1bmtfc2l6ZShmaWx0ZXJfbGlzdCwgMTAwMDApCmBgYAoKCiMjIyBDcmVhdGluZyB0aGUgQXJyYXkgU2NoZW1hCgpgYGB7ciBjcmVhdGVhcnJzY2hlbWF9CiMgLi4uIGNyZWF0ZSBkb21haW4gZG9tCmF0dHIxIDwtIHRpbGVkYl9hdHRyKCJhdHRyMSIsICJJTlQzMiIsIGZpbHRlcl9saXN0ID0gZmlsdGVyX2xpc3QpCmF0dHIyIDwtIHRpbGVkYl9hdHRyKCJhdHRyMiIsICJGTE9BVDY0IiwgZmlsdGVyX2xpc3QgPSBmaWx0ZXJfbGlzdCkKCiMgQ3JlYXRlIGEgZGVuc2UgYXJyYXkKc2NoZW1hIDwtIHRpbGVkYl9hcnJheV9zY2hlbWEoZG9tLCBjKGF0dHIxLCBhdHRyMiksIHNwYXJzZSA9IEZBTFNFKQojIE9yLCBjcmVhdGUgYSBzcGFlc2UgYXJyYXkKIyBzY2hlbWEgPC0gdGlsZWRiX2FycmF5X3NjaGVtYShkb20sIGMoYXR0cjEsIGF0dHIyKSwgc3BhcnNlID0gVFJVRSkKYGBgCgojIyMjIFNldHRpbmcgdGhlIFRpbGUgYW5kIENlbGwgT3JkZXIKCmBgYHtyIHNldHRpbGVjZWxsb3JkZXJ9CiMgLi4uIGNyZWF0ZSBkb21haW4gZG9tCiMgLi4uIGNyZWF0ZSBhdHRyaWJ1dGVzIGF0dHIxLCBhdHRyMgoKIyBUaGUgdGlsZSBhbmQgb3JkZXIgY2FuIGJlICJST1dfTUFKT1IiIG9yICJDT0xfTUFKT1IiCnNjaGVtYSA8LSB0aWxlZGJfYXJyYXlfc2NoZW1hKGRvbSwgYyhhdHRyMSwgYXR0cjIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjZWxsX29yZGVyID0gIkNPTF9NQUpPUiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpbGVfb3JkZXIgPSAiUk9XX01BSk9SIikKYGBgCgojIyMjIFNldHRpbmcgdGhlIERhdGEgVGlsZSBDYXBhY2l0eQoKYGBge3Igc2V0dGlsZWNhcGFjaXR5fQp0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfc2NoZW1hX3NldF9jYXBhY2l0eShzY2hlbWFAcHRyLCAxMDAwMDApCnRpbGVkYjo6OmxpYnRpbGVkYl9hcnJheV9zY2hlbWFfZ2V0X2NhcGFjaXR5KHNjaGVtYUBwdHIpCiMjIFRPRE8gaGlnaGVyLWxldmVsIFIgZnVuY3Rpb25zCmBgYAoKIyMjIyBTZXR0aW5nIENvb3JkaW5hdGUgYW5kIE9mZnNldCBGaWx0ZXJzCgpgYGB7ciBzZXRjb29yZG9mZnNldGZpbHR9CiMgLi4uIGNyZWF0ZSBkb21haW4gZG9tCiMgLi4uIGNyZWF0ZSBhdHRyaWJ1dGVzIGF0dHIxLCBhdHRyMgojIC4uLiBjcmVhdGUgZmlsdGVyIGxpc3RzIGZsMSwgZmwyLCBzaW1pbGFyIHRvIGF0dHJpYnV0ZXMKZjEgPC0gdGlsZWRiX2ZpbHRlcigiQklUX1dJRFRIX1JFRFVDVElPTiIpCmYyIDwtIHRpbGVkYl9maWx0ZXIoIlpTVEQiKQpmbDEgPC0gdGlsZWRiX2ZpbHRlcl9saXN0KGMoZjEpKQpmbDIgPC0gdGlsZWRiX2ZpbHRlcl9saXN0KGMoZjIpKQoKIyBDcmVhdGUgdGhlIHNjaGVtYSBzZXR0aW5nIHRoZSBjb29yZGluYXRlcyBhbmQgb2Zmc2V0cyBmaWx0ZXIgbGlzdHMKc2NoZW1hIDwtIHRpbGVkYl9hcnJheV9zY2hlbWEoZG9tLCBjKGF0dHIxLCBhdHRyMiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3Jkc19maWx0ZXJfbGlzdCA9IGZsMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0c19maWx0ZXJfbGlzdCA9IGZsMikKYGBgCgoKIyMjIyBDaGVja2luZyBDb3JyZWN0bmVzcwoKYGBge3IgYXJyYXlzY2hlbWFjaGVja30KdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X3NjaGVtYV9jaGVjayhzY2hlbWFAcHRyKQojIyBUT0RPIGhpZ2hlci1sZXZlbCBSIGZ1bmN0aW9ucwpgYGAKCgoKIyMjIENyZWF0aW5nIHRoZSBBcnJheQoKYGBge3IgY3JlYXRlYXJyYXksIGV2YWw9RkFMU0V9CiMgLi4uIGNyZWF0ZSBhcnJheSBzY2hlbWEKCiMgQ3JlYXRlIHRoZSBhcnJheQp0aWxlZGJfYXJyYXlfY3JlYXRlKHVyaWRlbnNlLCBzY2hlbWEpCmBgYAoKIyMjIENyZWF0aW5nIEVuY3J5cHRlZCBBcnJheXMKCmBgYHtyIGNyZWF0ZXdpdGhrZXl9CmVuY3J5cHRpb25fa2V5IDwtICIwMTIzNDU2Nzg5YWJjZGVGMDEyMzQ1Njc4OWFiY2RlRiIKdXJpZGVuc2V3a2V5IDwtIGZpbGUucGF0aCh0ZGlyLCAiZGVuc2V3a2V5IikKaWYgKGRpci5leGlzdHModXJpZGVuc2V3a2V5KSkgdW5saW5rKHVyaWRlbnNld2tleSwgcmVjdXJzaXZlPVRSVUUpCgojIHNob3J0Y3V0OiBib3Jyb3cgc2NoZW1hIGZyb20gZGVuc2UgYXJyYXk7IGNvdWxkIGNyZWF0ZSBzY2hlbWEgdG9vCnNjaGVtYSA8LSBzY2hlbWEodGlsZWRiX2RlbnNlKHVyaWRlbnNlKSkKdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X2NyZWF0ZV93aXRoX2tleSh1cmlkZW5zZXdrZXksIHNjaGVtYUBwdHIsIGVuY3J5cHRpb25fa2V5KQojI1RPRE86IFIgc3VwcG9ydApgYGAKCgojIyBXcml0aW5nIEFycmF5cwoKIyMjIFdyaXRpbmcgaW4gRGVuc2UgU3ViYXJyYXlzCgpgYGB7ciB3cml0ZWRlbnNlc3ViYXJyLCBldmFsPUZBTFNFfQojIyBwcmVwYXJlIGEgbGFyZ2VyIDUgeCA1IHRvIGVtYmVkIGludG8KdG1wIDwtIHRlbXBmaWxlKCkKZDEgIDwtIHRpbGVkYl9kaW0oImQxIiwgZG9tYWluID0gYygxTCwgNUwpKQpkMiAgPC0gdGlsZWRiX2RpbSgiZDIiLCBkb21haW4gPSBjKDFMLCA1TCkpCmRvbSA8LSB0aWxlZGJfZG9tYWluKGMoZDEsIGQyKSkKdmFsIDwtIHRpbGVkYl9hdHRyKG5hbWU9InZhbCIsIHR5cGUgPSAiSU5UMzIiKQpzY2ggPC0gdGlsZWRiX2FycmF5X3NjaGVtYShkb20sIGModmFsKSkKdGlsZWRiX2FycmF5X2NyZWF0ZSh0bXAsIHNjaCkKCmRhdCA8LSBtYXRyaXgoYXMuaW50ZWdlcihybm9ybSgyNSkqMTAwKSwgNSwgNSkKYXJyIDwtIHRpbGVkYl9kZW5zZSh0bXAsIGFzLmRhdGEuZnJhbWU9RkFMU0UpCmFycltdIDwtIGRhdAoKCiMgUHJlcGFyZSBhIDJ4MyBkZW5zZSBhcnJheQojIENvbnRyYXJ5IHRvIFB5dGhvbiwgUiBieSBkZWZhdWx0IHN0b3JlcyBhcnJheXMgaW4gY29sLW1ham9yIG9yZGVyCmRhdGEgPC0gIGFycmF5KGMoMUwsIDRMLCAyTCwgNUwsIDNMLCA2TCksIGRpbT1jKDIsMykpCgojIFByZXBhcmUgdGhlIFsxLDJdIHggWzIsNF0gc3ViYXJyYXkgdG8gd3JpdGUgdG8KSSA8LSBjKDE6MikKSiA8LSBjKDI6NCkKCiMgT3BlbiB0aGUgYXJyYXkgYW5kIHdyaXRlIHRoZSBkYXRhIHRvIGl0CkEgPC0gdGlsZWRiX2RlbnNlKHVyaSA9IHRtcCkKQVtJLCBKXSA8LSBkYXRhCgp1bmxpbmsodG1wLCByZWN1cnNpdmU9VFJVRSkKYGBgCgoKIyMjIyBCYXNpYyBXcml0aW5nIHVzaW5nIExvdy1MZXZlbCBDb2RlCgpgYGB7ciBiYXNpc2N3cml0aW5nbG93bGV2ZWx9CmN0eCA8LSB0aWxlZGJfY3R4KCkKYXJycHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9hcnJheV9vcGVuKGN0eEBwdHIsIHVyaWRlbnNlLCAiV1JJVEUiKQoKIyMgZGF0YTogc2ltcGxlIChpbnRlZ2VyIHNlcXVlbmNlKSBvZiAxOjE2IHRpbWVzIDEwCnZlYyA8LSAxOjE2ICogMTBMCnN1YmFyciA8LSBjKDFMLDRMLCAxTCw0TCkKCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnkoY3R4QHB0ciwgYXJycHRyLCAiV1JJVEUiKQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3NldF9zdWJhcnJheShxcnlwdHIsIHN1YmFycikKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zZXRfbGF5b3V0KHFyeXB0ciwgIlJPV19NQUpPUiIpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc2V0X2J1ZmZlcihxcnlwdHIsICJhIiwgdmVjKQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3N1Ym1pdChxcnlwdHIpCnJlcyA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfY2xvc2UoYXJycHRyKQpgYGAKCgojIyMgV3JpdGluZyBTcGFyc2UgQ2VsbHMKCmBgYHtyIHdyaXRlc3BhcnNlY2VsbHN9CnRtcCA8LSB1cmlzcGFyc2UKdW5saW5rKHRtcCwgcmVjdXJzaXZlPVRSVUUpCgpkMSAgPC0gdGlsZWRiX2RpbSgiZDEiLCBkb21haW4gPSBjKDFMLCA1TCkpCmQyICA8LSB0aWxlZGJfZGltKCJkMiIsIGRvbWFpbiA9IGMoMUwsIDVMKSkKZG9tIDwtIHRpbGVkYl9kb21haW4oYyhkMSwgZDIpKQp2YWwgPC0gdGlsZWRiX2F0dHIoInZhbCIsIHR5cGUgPSAiSU5UMzIiKQpzY2ggPC0gdGlsZWRiX2FycmF5X3NjaGVtYShkb20sIHZhbCwgc3BhcnNlPVRSVUUpCnRpbGVkYl9hcnJheV9jcmVhdGUodG1wLCBzY2gpCgoKIyBQcmVwYXJlIHNvbWUgZGF0YQpkYXRhIDwtIGMoM0wsIDRMLCAxTCwgMkwpCgpJIDwtIGMoMywgNCwgMSwgMikKSiA8LSBjKDMsIDQsIDIsIDEpCgojIE9wZW4gdGhlIGFycmF5IGFuZCB3cml0ZSB0aGUgZGF0YSB0byBpdApBIDwtIHRpbGVkYl9zcGFyc2UodXJpID0gdG1wKQpBW0ksIEpdIDwtIGRhdGEKCmBgYAoKCiMjIyBXcml0aW5nIEVuY3J5cHRlZCBBcnJheXMKCmBgYHtyIHdyaXRpbmdlbmNyeXB0ZWRsb3dsZXZlbH0KY3R4IDwtIHRpbGVkYl9jdHgoKQphcnJwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X29wZW5fd2l0aF9rZXkoY3R4QHB0ciwgdXJpZGVuc2V3a2V5LCAiV1JJVEUiLCBlbmNyeXB0aW9uX2tleSkKCiMjIGRhdGE6IHNpbXBsZSAoaW50ZWdlciBzZXF1ZW5jZSkgb2YgMToxNiB0aW1lcyAxMAp2ZWMgPC0gMToxNiAqIDEwTApzdWJhcnIgPC0gYygxTCw0TCwgMUwsNEwpCgpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5KGN0eEBwdHIsIGFycnB0ciwgIldSSVRFIikKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zZXRfc3ViYXJyYXkocXJ5cHRyLCBzdWJhcnIpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc2V0X2xheW91dChxcnlwdHIsICJST1dfTUFKT1IiKQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3NldF9idWZmZXIocXJ5cHRyLCAiYSIsIHZlYykKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zdWJtaXQocXJ5cHRyKQpyZXMgPC0gdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X2Nsb3NlKGFycnB0cikKIyBUT0RPIEhpZ2hlci1sZXZlbCBSIHN1cHBvcnQKCmBgYAoKCgoKIyMjIEZpeGVkLWxlbmd0aCBBdHRyaWJ1dGVzCgpgYGB7ciBmaXhlZGxlbmd0aGF0dHJpYnV0ZXN9CmlmIChkaXIuZXhpc3RzKHVyaWRlbnNlZml4KSkgdW5saW5rKHVyaWRlbnNlZml4LCByZWN1cnNpdmU9VFJVRSkKZDEgIDwtIHRpbGVkYl9kaW0oImQxIiwgZG9tYWluID0gYygxTCwgNEwpKQpkMiAgPC0gdGlsZWRiX2RpbSgiZDIiLCBkb21haW4gPSBjKDFMLCA0TCkpCmRvbSA8LSB0aWxlZGJfZG9tYWluKGMoZDEsIGQyKSkKCnZlYyA8LSAxOjMyICogMTBMCmF0dHIgPC0gdGlsZWRiX2F0dHIoImEiLCB0eXBlID0gcl90b190aWxlZGJfdHlwZSh2ZWMpKQoKIyMgc2V0IHRvIHR3byB2YWx1ZXMgcGVyIGNlbGwKdGlsZWRiOjo6bGlidGlsZWRiX2F0dHJpYnV0ZV9zZXRfY2VsbF92YWxfbnVtKGF0dHJAcHRyLCAyKQpzY2ggPC0gdGlsZWRiX2FycmF5X3NjaGVtYShkb20sIGF0dHIpCnRpbGVkYl9hcnJheV9jcmVhdGUodXJpZGVuc2VmaXgsIHNjaCkKCmN0eCA8LSB0aWxlZGJfY3R4KCkKYXJycHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9hcnJheV9vcGVuKGN0eEBwdHIsIHVyaWRlbnNlZml4LCAiV1JJVEUiKQpzdWJhcnIgPC0gYygxTCw0TCwgMUwsNEwpCgpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5KGN0eEBwdHIsIGFycnB0ciwgIldSSVRFIikKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zZXRfc3ViYXJyYXkocXJ5cHRyLCBzdWJhcnIpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc2V0X2xheW91dChxcnlwdHIsICJST1dfTUFKT1IiKQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3NldF9idWZmZXIocXJ5cHRyLCAiYSIsIHZlYykKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zdWJtaXQocXJ5cHRyKQpyZXMgPC0gdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X2Nsb3NlKGFycnB0cikKCiNUT0RPIEhpZ2hlci1sZXZlbCBSIHN1cHBvcnQKYGBgCgojIyMgVmFyLWxlbmd0aCBBdHRyaWJ1dGVzCgpgYGB7cn0KaWYgKGRpci5leGlzdHModXJpZGVuc2V2YXIpKSB1bmxpbmsodXJpZGVuc2V2YXIsIHJlY3Vyc2l2ZT1UUlVFKQojIyBEZWZpbmUgYXJyYXkKIyMgVGhlIGFycmF5IHdpbGwgYmUgNHg0IHdpdGggZGltZW5zaW9ucyAicm93cyIgYW5kICJjb2xzIiwgd2l0aCBkb21haW4gWzEsNF0uCmRvbSA8LSB0aWxlZGJfZG9tYWluKGRpbXMgPSBjKHRpbGVkYl9kaW0oInJvd3MiLCBjKDFMLCA0TCksIDRMLCAiSU5UMzIiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGlsZWRiX2RpbSgiY29scyIsIGMoMUwsIDRMKSwgNEwsICJJTlQzMiIpKSkKCgphdHRyIDwtIHRpbGVkYl9hdHRyKCJhMSIsIHR5cGUgPSAiQ0hBUiIpCiMjIHNldCB0byB2YXJpYWJsZSBsZW5ndGgKdGlsZWRiOjo6bGlidGlsZWRiX2F0dHJpYnV0ZV9zZXRfY2VsbF92YWxfbnVtKGF0dHJAcHRyLCBOQSkKCiMjIG5vdyBzZXQgdGhlIHNjaGVtYQpjdHggPC0gdGlsZWRiX2N0eCgpCnNjaHB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfc2NoZW1hX2NyZWF0ZShjdHhAcHRyLCAiREVOU0UiKQp0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfc2NoZW1hX3NldF9kb21haW4oc2NocHRyLCBkb21AcHRyKQp0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfc2NoZW1hX3NldF9jZWxsX29yZGVyKHNjaHB0ciwgIlJPV19NQUpPUiIpCnRpbGVkYjo6OmxpYnRpbGVkYl9hcnJheV9zY2hlbWFfc2V0X3RpbGVfb3JkZXIoc2NocHRyLCAiUk9XX01BSk9SIikKdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X3NjaGVtYV9hZGRfYXR0cmlidXRlKHNjaHB0ciwgYXR0ckBwdHIpCgoKCiMjIENyZWF0ZSB0aGUgKGVtcHR5KSBhcnJheSBvbiBkaXNrLgp0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfY3JlYXRlKHVyaWRlbnNldmFyLCBzY2hwdHIpCgpkYXRhIDwtICJhYmJjY2NkZGVlZWZnaGhoaWpqamtrbG1ub29wIjsKb2Zmc2V0cyA8LSBjKDBMLCAxTCwgM0wsIDZMLCA4TCwgMTFMLCAxMkwsIDEzTCwgMTZMLCAxN0wsIDIwTCwgMjJMLCAyM0wsIDI0TCwgMjVMLCAyN0wpCgpjdHggPC0gdGlsZWRiX2N0eCgpCmFycnB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfb3BlbihjdHhAcHRyLCB1cmlkZW5zZXZhciwgIldSSVRFIikKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeShjdHhAcHRyLCBhcnJwdHIsICJXUklURSIpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc2V0X2xheW91dChxcnlwdHIsICJST1dfTUFKT1IiKQoKYnVmcHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9idWZmZXJfdmFyX2NoYXJfY3JlYXRlKG9mZnNldHMsIGRhdGEpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc2V0X2J1ZmZlcl92YXJfY2hhcihxcnlwdHIsICJhMSIsIGJ1ZnB0cikKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zdWJtaXQocXJ5cHRyKQp0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfY2xvc2UoYXJycHRyKQoKI1RPRE8gSGlnaGVyLWxldmVsIFIgc3VwcG9ydApgYGAKCgojIyMgR2V0dGluZyB0aGUgRnJhZ21lbnQgSW5mbwoKYGBge3IgZnJhZ21lbnRpbmZvfQojIyBjb250aW51aW5nIGZyb20gcHJldmlvdXMgZXhhbXBsZSBvbiBkZW5zZSB2YXJpYWJsZSBsZW5ndGggYXJyYXkKIyMgKGJ1dCB0aGlzIHdvcmtzIG9mIGNvdXJzZSB3aXRoIGFueSBhcnJheSBhZnRlciBhIHdyaXRlIGlzIG5lZWRlZApudW1mcmFnIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9nZXRfZnJhZ21lbnRfbnVtKHFyeXB0cikKdXJpdHh0IDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9nZXRfZnJhZ21lbnRfdXJpKHFyeXB0ciwgMCkKCiMjVE9ETyBIaWdoZXItbGV2ZWwgUiBzdXBwb3J0CmBgYAoKIyMgUmVhZGluZyBBcnJheXMKCiMjIyBSZWFkaW5nIHRoZSBBcnJheSBTY2hlbWEKCmBgYHtyIHNjaGVtYWxvYWR9CmFycmF5X25hbWUgPC0gdXJpc3BhcnNlCkEgPC0gdGlsZWRiX3NwYXJzZSh1cmkgPSBhcnJheV9uYW1lKQojIGNhbiBhbHNvIGxvYWQgZGVuc2UKc2NoIDwtIHNjaGVtYShBKQojIGNhbiBhbHNvIG9wZW4gZW5jcnlwdGVkIGFycmF5cyB3aXRoIGtleQpgYGAKCiMjIyMgSW5zcGVjdGluZyB0aGUgYXJyYXkgc2NoZW1hCgpgYGB7ciBzY2hlbWFpbnNwZWN0fQphcnJheV9uYW1lIDwtIHVyaXNwYXJzZQoKIyBHZXQgYXJyYXkgc2NoZW1hCkEgPC0gdGlsZWRiX3NwYXJzZSh1cmkgPSBhcnJheV9uYW1lKQojIG9yIHVzZSB0aWxlZGJfZGVuc2UodXJpID0gYXJyYXlfbmFtZSkgZm9yIGRlbnNlCnNjaGVtYSA8LSBzY2hlbWEoQSkKCiMgR2V0IGFycmF5IHR5cGUKc3BhcnNlIDwtIGlzLnNwYXJzZShzY2hlbWEpCgojIEdldCB0aWxlIGNhcGFjaXR5CnRpbGVkYjo6OmxpYnRpbGVkYl9hcnJheV9zY2hlbWFfZ2V0X2NhcGFjaXR5KHNjaEBwdHIpCiMgVE9ETzogUiBhY2Nlc3NvciBmb3IgdGlsZQoKIyBHZXQgdGlsZSBvcmRlcgp0X29yZGVyIDwtIHRpbGVfb3JkZXIoc2NoZW1hKQoKIyBHZXQgY2VsbCBvcmRlcgpjX29yZGVyIDwtIGNlbGxfb3JkZXIoc2NoZW1hKQoKIyBHZXQgY29vcmRpbmF0ZXMgYW5kIG9mZnNldCBmaWx0ZXIgbGlzdApyZXNsaXN0IDwtIGZpbHRlcl9saXN0KHNjaGVtYSkKCiMgR2V0IHRoZSBhcnJheSBkb21haW4KZG9tIDwtIGRvbWFpbihzY2hlbWEpCgojIEdldCBhbGwgYXR0cmlidXRlcyBhcyBsaXN0CmF0dHJzIDwtIGF0dHJzKHNjaGVtYSkKCiMgR2V0IGF0dHJpYnV0ZSBmcm9tIG5hbWUKYXR0ciA8LSBhdHRycyhzY2hlbWEsICJhdHRyIikKCiMgRHVtcCB0aGUgYXJyYXkgc2NoZW1hIGluIEFTQ0lJIGZvcm1hdCB0byBzdGRvdXQKc2hvdyhzY2hlbWEpCmBgYAoKCiMjIyMgSW5zcGVjdGluZyBEb21haW4KCmBgYHtyIGluc3BlY3Rkb21haW59CiMgLi4uIGdldCBhcnJheSBzY2hlbWEKIyAuLi4gZ2V0IGRvbWFpbiBmcm9tIHNjaGVtYQpkb20gPC0gZG9tYWluKHNjaGVtYSkKCiMgR2V0IHRoZSBkb21haW4gZGF0YXR5cGUgKGkuZS4sIHRoZSBkYXRhdHlwZSBvZiBhbGwgZGltZW5zaW9ucykKdHlwZSA8LSBkYXRhdHlwZShkb20pCgojIEdldCBudW1iZXIgb2YgZGltZW5zaW9ucwpkaW1fbnVtIDwtIGRpbShkb20pCgojIEdldCBhbGwgZGltZW5zaW9uCmRpbXMgPC0gZGltZW5zaW9ucyhkb20pCgojIER1bXAgdGhlIGRvbWFpbiBpbiBBU0NJSSBmb3JtYXQgaW4gdGhlIHNlbGVjdGVkIG91dHB1dApzaG93KGRvbSkKYGBgCgojIyMjIEluc3BlY3RpbmcgRGltZW5zaW9ucwoKYGBge3IgaW5zcGVjdGRpbWVuc2lvbnMsIGV2YWw9RkFMU0V9CiMgLi4uIGdldCBhcnJheSBzY2hlbWEKIyAuLi4gZ2V0IGRvbWFpbgojIC4uLiBnZXQgZGltZW5zaW9uIGJ5IGluZGV4IG9yIG5hbWUKCiNGSVhNRQoKIyBHZXQgZGltZW5zaW9uIG5hbWUKZGltX25hbWUgPC0gbmFtZShkaW0pCgojIEdldCBkaW1lbnNpb24gZGF0YXR5cGUKZGltX3R5cGUgPC0gZGF0YXR5cGUoZGltKQoKIyBHZXQgZGltZW5zaW9uIGRvbWFpbgpkb21haW4gPC0gZG9tYWluKGRpbSkKCiMgR2V0IHRpbGUgZXh0ZW50CnRpbGVfZXh0ZW50IDwtIHRpbGUoZGltKQoKIyBEdW1wIHRoZSBkaW1lbnNpb24gaW4gQVNDSUkgZm9ybWF0IGluIHRoZSBzZWxlY3RlZCBvdXRwdXQKc2hvdyhkaW0pCgpgYGAKCgojIyMjIEluc3BlY3RpbmcgQXR0cmlidXRlcwoKYGBge3IgaW5zcGVjdGF0dHIsIGV2YWw9RkFMU0V9CiMgLi4uIGdldCBhcnJheSBzY2hlbWEKIyAuLi4gZ2V0IGF0dHJpYnV0ZSBieSBpbmRleCBvciBuYW1lCgpzdG9waWZub3QoaXMubnVsbChhdHRyKSkKIyBHZXQgYXR0cmlidXRlIG5hbWUKYXR0cl9uYW1lIDwtIG5hbWUoYXR0cikKCiMgR2V0IGF0dHJpYnV0ZSBkYXRhdHlwZQphdHRyX3R5cGUgPC0gZGF0YXR5cGUoYXR0cikKCiMgR2V0IGZpbHRlciBsaXN0CmZpbHRlcl9saXN0IDwtIGZpbHRlcl9saXN0KGF0dHIpCgojIENoZWNrIGlmIGF0dHJpYnV0ZSBpcyB2YXJpYWJsZS1sZW5ndGgKIyB2YXJpYWJsZSBsZW5ndGggYXR0cmlidHVlcyBhcmUgbm90IHN1cHBvcnRlZCBpbiBSIGN1cnJlbnRseQoKIyBHZXQgbnVtYmVyIG9mIHZhbHVlcyBwZXIgY2VsbApudW0gPC0gbmNlbGxzKGF0dHIpCgojIEdldCBjZWxsIHNpemUgZm9yIHRoaXMgYXR0cmlidXRlCnN6IDwtLSB0aWxlZGI6OjpsaWJ0aWxlZGJfYXR0cmlidXRlX2dldF9jZWxsX3ZhbChhdHRyQHB0cikKCiMgRHVtcCB0aGUgYXR0cmlidXRlIGluIEFTQ0lJIGZvcm1hdCBpbiB0aGUgc2VsZWN0ZWQgb3V0cHV0CnNob3coYXR0cikKYGBgCgoKCiMjIyMgSW5zcGVjdGluZyBGaWx0ZXJzCgpgYGB7ciBpbnNwZWN0ZmlsdGVycywgZXZhbD1GQUxTRX0KZmwgPC0gdGlsZWRiX2ZpbHRlcl9saXN0KCkKCiMgZ2V0IG51bWJlciBvZiBmaWx0ZXIKdGlsZWRiOjo6bGlidGlsZWRiX2ZpbHRlcl9saXN0X2dldF9uZmlsdGVycyhmbEBwdHIpCgojIGdldCBtYXggY2h1bmsgc2l6ZQp0aWxlZGI6OjpsaWJ0aWxlZGJfZmlsdGVyX2xpc3RfZ2V0X21heF9jaHVua19zaXplKGZsQHB0cikKCiMgZ2V0IGZpbHRlciBmcm9tIGluZGV4CmluZCA8LSBpCnRpbGVkYjo6OmxpYnRpbGVkYl9maWx0ZXJfbGlzdF9nZXRfZmlsdGVyX2Zyb21faW5kZXgoZmxAcHRyLCBpbmQpCmBgYAoKIyMjIEJhc2ljIFJlYWRpbmcKCmBgYHtyIGJhc2lzY3JlYWRpbmd9CiMgQ3JlYXRlIGEgVGlsZURCIGNvbnRleHQKY3R4IDwtIHRpbGVkYl9jdHgoKQoKIyBPcGVuIGEgZGVuc2UgYXJyYXkKQSA8LSB0aWxlZGJfZGVuc2UodXJpID0gdXJpZGVuc2UsIGN0eD1jdHgpCgojIE9yLCBvcGVuIGEgc3BhcnNlIGFycmF5CiMgQSA8LSB0aWxlZGJfc3BhcnNlKHVyaSA9ICI8YXJyYXktdXJpPiIsIGN0eD1jdHgpCgojIFNsaWNlIG9ubHkgcm93cyAxLCAyIGFuZCBjb2xzIDIsIDMsIDQKZGF0YSA8LSBBWzE6MiwgMjo0XQpzaG93KGRhdGEpCmBgYAoKIyMjIyBCYXNpYyBSZWFkaW5nIHVzaW5nIExvdy1MZXZlbCBDb2RlCgpgYGB7ciBiYXNpc2NyZWFkaW5nbG93bGV2ZWx9CmN0eCA8LSB0aWxlZGJfY3R4KCkKYXJycHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9hcnJheV9vcGVuKGN0eEBwdHIsIHVyaWRlbnNlLCAiUkVBRCIpCiMjIHN1YmFycmF5IG9mIHJvd3MgMSwyIGFuZCBjb2xzIDIsMyw0CnN1YmFyciA8LSBjKDFMLDJMLCAyTCw0TCkKCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnkoY3R4QHB0ciwgYXJycHRyLCAiUkVBRCIpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc2V0X3N1YmFycmF5KHFyeXB0ciwgc3ViYXJyKQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3NldF9sYXlvdXQocXJ5cHRyLCAiUk9XX01BSk9SIikKdiA8LSBpbnRlZ2VyKDYpICAjIHJlc2VydmUgc3BhY2UKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zZXRfYnVmZmVyKHFyeXB0ciwgImEiLCB2KQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3N1Ym1pdChxcnlwdHIpCnByaW50KHYpICAgICAgICAgIyB1bmZvcm1lZCBhcnJheSwgbm8gY29vcmRpbmF0ZXMKcmVzIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9hcnJheV9jbG9zZShhcnJwdHIpCmBgYAoKIyMjIFZhcmlhYmxlLWxlbmd0aCBBdHRyaWJ1dGVzCgpgYGB7ciByZWFkdmFybGVuZ3RofQphcnJwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X29wZW4oY3R4QHB0ciwgdXJpZGVuc2V2YXIsICJSRUFEIikKCnN1YmFyciA8LSBjKDFMLDRMLCAxTCw0TCkKYnVmcHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9idWZmZXJfdmFyX2NoYXJfYWxsb2MoYXJycHRyLCBzdWJhcnIsICJhMSIsIDE2LCAxMDApCgpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5KGN0eEBwdHIsIGFycnB0ciwgIlJFQUQiKQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3NldF9zdWJhcnJheShxcnlwdHIsIHN1YmFycikKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zZXRfbGF5b3V0KHFyeXB0ciwgIlJPV19NQUpPUiIpCgpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3NldF9idWZmZXJfdmFyX2NoYXIocXJ5cHRyLCAiYTEiLCBidWZwdHIpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc3VibWl0KHFyeXB0cikKdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X2Nsb3NlKGFycnB0cikKCm1hdCA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfZ2V0X2J1ZmZlcl92YXJfY2hhcihidWZwdHIpCnByaW50KG1hdCwgcXVvdGU9RkFMU0UpCmBgYAoKIyMjIEdldHRpbmcgdGhlIE5vbi1lbXB0eSBEb21haW4KCmBgYHtyIG5vbmVtcHR5fQphcnJwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X29wZW4oY3R4QHB0ciwgdXJpZGVuc2V2YXIsICJSRUFEIikKIyByZXR1cm5zIGEgbGlzdCBvYmplY3QKcmVzbGlzdCA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfbm9uZW1wdHlfZG9tYWluKGFycnB0cikKdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X2Nsb3NlKGFycnB0cikKYGBgCgojIyMgUmVhZGluZyBFbmNyeXB0ZWQgQXJyYXlzCgpgYGB7ciByZWFkZW5jcnlwdGVkfQpjdHggPC0gdGlsZWRiX2N0eCgpCmFycnB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfb3Blbl93aXRoX2tleShjdHhAcHRyLCB1cmlkZW5zZXdrZXksICJSRUFEIiwgZW5jcnlwdGlvbl9rZXkpCgojIyBzdWJhcnJheSBvZiByb3dzIDEsMiBhbmQgY29scyAyLDMsNApzdWJhcnIgPC0gYygxTCwyTCwgMkwsNEwpCgpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5KGN0eEBwdHIsIGFycnB0ciwgIlJFQUQiKQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3NldF9zdWJhcnJheShxcnlwdHIsIHN1YmFycikKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zZXRfbGF5b3V0KHFyeXB0ciwgIlJPV19NQUpPUiIpCnYgPC0gaW50ZWdlcig2KSAgIyByZXNlcnZlIHNwYWNlCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc2V0X2J1ZmZlcihxcnlwdHIsICJhIiwgdikKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zdWJtaXQocXJ5cHRyKQpwcmludCh2KSAgICAgICAgICMgdW5mb3JtZWQgYXJyYXksIG5vIGNvb3JkaW5hdGVzCnJlcyA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfY2xvc2UoYXJycHRyKQoKIyMgVE9ETyBvcGVuIGF0IHRpbWVzdGFtcCBleGFtcGxlCmBgYAoKIyMjIE11bHRpLXJhbmdlIFN1YmFycmF5cwoKYGBge3IgbXVsdGlyYW5nZX0KY3R4IDwtIHRpbGVkYl9jdHgoKQphcnJwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X29wZW4oY3R4QHB0ciwgdXJpZGVuc2UsICJSRUFEIikKCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnkoY3R4QHB0ciwgYXJycHRyLCAiUkVBRCIpCgojIyByYW5nZSBvZiByb3dzIDEgYW5kIDIsIGFuZCA0IGZvciBkaW0gMSwgYWxsIHJvd3MgZm9yIGRpbSAyCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfYWRkX3JhbmdlKHFyeXB0ciwgMCwgMUwsIDJMKQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X2FkZF9yYW5nZShxcnlwdHIsIDAsIDRMLCA0TCkKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9hZGRfcmFuZ2UocXJ5cHRyLCAxLCAxTCwgNEwpCgpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3NldF9sYXlvdXQocXJ5cHRyLCAiUk9XX01BSk9SIikKdiA8LSBpbnRlZ2VyKDEyKSAgIyByZXNlcnZlIHNwYWNlCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc2V0X2J1ZmZlcihxcnlwdHIsICJhIiwgdikKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zdWJtaXQocXJ5cHRyKQpwcmludCh2KSAgICAgICAgICMgdW5mb3JtZWQgYXJyYXksIG5vIGNvb3JkaW5hdGVzCnJlcyA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfY2xvc2UoYXJycHRyKQpgYGAKCiMjIyBJbmNvbXBsZXRlIFF1ZXJpZXMKCmBgYHtyIGluY29tcGxldGVyZWFkc30KY3R4IDwtIHRpbGVkYl9jdHgoKQphcnJwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X29wZW4oY3R4QHB0ciwgdXJpZGVuc2UsICJSRUFEIikKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeShjdHhAcHRyLCBhcnJwdHIsICJSRUFEIikKc3ViYXJyIDwtIGMoMUwsNEwsIDFMLDRMKQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3NldF9zdWJhcnJheShxcnlwdHIsIHN1YmFycikKdmVjIDwtIGludGVnZXIoNCkgICMgcmVzZXJ2ZSAoaW5zdWZmaWNpZW50KSBzcGFjZQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3NldF9idWZmZXIocXJ5cHRyLCAiYSIsIHZlYykKZmluaXNoZWQgPC0gRkFMU0UKd2hpbGUgKCFmaW5pc2hlZCkgewogIHFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc3VibWl0KHFyeXB0cikKICBwcmludCh2ZWMpCiAgZmluaXNoZWQgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3N0YXR1cyhxcnlwdHIpID09ICJDT01QTEVURSIKfQpyZXMgPC0gdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X2Nsb3NlKGFycnB0cikKYGBgCgojIyMgUmVzdWx0IEVzdGltYXRpb24KCmBgYHtyIHJlc3VsdGVzdGltYXRpb259CmN0eCA8LSB0aWxlZGJfY3R4KCkKYXJycHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9hcnJheV9vcGVuKGN0eEBwdHIsIHVyaWRlbnNldmFyLCAiUkVBRCIpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnkoY3R4QHB0ciwgYXJycHRyLCAiUkVBRCIpCmVzdHN6IDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9nZXRfZXN0X3Jlc3VsdF9zaXplX3ZhcihxcnlwdHIsICJhMSIpCnJlcyA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfY2xvc2UoYXJycHRyKQplc3RzegpgYGAKCiMjIyBUaW1lIFRyYXZlbGluZwoKYGBge3IgdGltZXRyYXZlbH0KY3R4IDwtIHRpbGVkYl9jdHgoKQp0c3RhbXAgPC0gU3lzLnRpbWUoKSAtIDEuMDsgIyBvbmUgc2Vjb25kcyBhZ28gKGFzIHRoZSBhcnJheXMgY3JlYXRlZCBoZXJlIGFyZSBpbiB0ZW1wLmZpbGVzKQphcnJwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X29wZW5fYXQoY3R4QHB0ciwgdXJpZGVuc2UsICJSRUFEIiwgdHN0YW1wKQpzdWJhcnIgPC0gYygxTCwyTCwgMkwsNEwpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnkoY3R4QHB0ciwgYXJycHRyLCAiUkVBRCIpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc2V0X3N1YmFycmF5KHFyeXB0ciwgc3ViYXJyKQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3NldF9sYXlvdXQocXJ5cHRyLCAiUk9XX01BSk9SIikKdiA8LSBpbnRlZ2VyKDYpICAjIHJlc2VydmUgc3BhY2UKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zZXRfYnVmZmVyKHFyeXB0ciwgImEiLCB2KQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3N1Ym1pdChxcnlwdHIpCnJlcyA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfY2xvc2UoYXJycHRyKQp2CmBgYAoKIyMgRW1iZWRkZWQgU1FMCgojIyBBc3luY2hyb25vdXMgUXVlcmllcwoKIyMgQ29uZmlndXJhdGlvbgoKIyMgQXJyYXkgTWV0YWRhdGEKCiMjIyBXcml0aW5nIEFycmF5IE1ldGFkYXRhCgpgYGB7ciB3cml0ZW1ldGFkYXRhfQphcnIgPC0gdGlsZWRiX2RlbnNlKHVyaWRlbnNlKQpjbG9zZV9hbmRfcmVvcGVuKGFyciwgIldSSVRFIikKcmVzIDwtIHRpbGVkYl9wdXRfbWV0YWRhdGEoYXJyLCAiYWFhIiwgMTAwTCkKcmVzIDwtIHRpbGVkYl9wdXRfbWV0YWRhdGEoYXJyLCAiYmIiLCBjKDEuMSwgMi4yKSkKaW52aXNpYmxlKHRpbGVkYjo6OmxpYnRpbGVkYl9hcnJheV9jbG9zZShhcnJAcHRyKSkKYGBgCgojIyMgUmVhZGluZyBBcnJheSBNZXRhZGF0YQoKT25lIGNhbiByZWFkIGJ5IGtleToKCmBgYHtyIHJlYWRtZXRhZGF0YX0KY2xvc2VfYW5kX3Jlb3BlbihhcnIsICJSRUFEIikKdGlsZWRiX2dldF9tZXRhZGF0YShhcnIsICJhYWEiKQpgYGAKCk9yIG9uZSBjYW4gcmV0cmlldmUgYWxsIG1ldGFkYXRhIGF0IG9uY2U6CgpgYGB7ciByZWFkbWV0YWRhdGFhbGx9Cm1kIDwtIHRpbGVkYl9nZXRfYWxsX21ldGFkYXRhKGFycikKcHJpbnQobWQpCmBgYAoKIyMjIERlbGV0aW5nIEFycmF5IE1ldGFkYXRhCgpgYGB7ciBkZWxldGVtZXRhZGF0YX0KY2xvc2VfYW5kX3Jlb3BlbihhcnIsICJXUklURSIpCnJlcyA8LSB0aWxlZGJfZGVsZXRlX21ldGFkYXRhKGFyciwgImFhYSIpCgpgYGAK