# package tar-mirage

Library

Module

Module type

Parameter

Class

Class type

Construct a read-write key-value store from an existing block device containing tar-format data. Note that it is append-only meaning removing or renaming files is currently unsupported and will return an error.

## Parameters

`module CLOCK : Mirage_clock.PCLOCK`

`module BLOCK : Mirage_block.S`

## Signature

`include Mirage_kv.RW`

### Read-write Stores

The functions `set`

and `remove`

will cause a flush in the underlying storage layer every time, which can degrade performance.

`include Mirage_kv.RO`

### Read-only key-value stores

The type for errors.

Disconnect from the key-value store. While this might take some time to complete, it can never result in an error.

`type key = Mirage_kv.Key.t`

The type for keys.

`exists t k`

is `Some `Value`

if `k`

is bound to a value in `t`

, `Some `Dictionary`

if `k`

is a prefix of a valid key in `t`

and `None`

if no key with that prefix exists in `t`

.

`exists`

answers two questions: does the key exist and is it referring to a value or a dictionary.

An error occurs when the underlying storage layer fails.

`get t k`

is the value bound to `k`

in `t`

.

The result is `Error (`Value_expected k)`

if `k`

refers to a dictionary in `t`

.

`get_partial t k ~offset ~length`

is the `length`

bytes wide value bound at `offset`

of `k`

in `t`

.

If the size of `k`

is less than `offset`

, `get_partial`

returns an empty string. If the size of `k`

is less than `offset`

+`length`

, `get_partial`

returns a short string. The result is `Error (`Value_expected k)`

if `k`

refers to a dictionary in `t`

.

`list t k`

is the list of entries and their types in the dictionary referenced by `k`

in `t`

. The returned keys are all absolute (i.e. `Key.add k entry`

).

The result is `Error (`Dictionary_expected k)`

if `k`

refers to a value in `t`

.

`last_modified t k`

is the last time the value bound to `k`

in `t`

has been modified.

When the value bound to `k`

is a dictionary, the implementation is free to decide how to compute a last modified timestamp, or return ```
Error
(`Value_expected _)
```

.

`digest t k`

is the unique digest of the value bound to `k`

in `t`

.

When the value bound to `k`

is a dictionary, the implementation is allowed to return `Error (`Value_expected _)`

. Otherwise, the `digest`

is a unique and deterministic digest of its entries.

The type for write errors.

`val pp_write_error : write_error Fmt.t`

The pretty-printer for `pp_write_error`

.

```
val allocate :
t ->
key ->
?last_modified:Ptime.t ->
Optint.Int63.t ->
(unit, write_error) result Lwt.t
```

`allocate t key ~last_modified size`

allocates space for `key`

in `t`

with the provided `size`

and `last_modified`

. This is useful for e.g. append-only backends that could still use `set_partial`

. The data will be filled with 0. If `key`

already exists, `Error (`Already_present key)`

is returned. If there's not enough space, `Error `No_space`

is returned.

`val set : t -> key -> string -> (unit, write_error) result Lwt.t`

`set t k v`

replaces the binding `k -> v`

in `t`

.

Durability is guaranteed.

```
val set_partial :
t ->
key ->
offset:Optint.Int63.t ->
string ->
(unit, write_error) result Lwt.t
```

`set_partial t k offset v`

attempts to write `v`

at `offset`

in the value bound to `k`

in `t`

. If `k`

contains directories that do not exist, `set_partial`

will attempt to create them. If the size of `k`

is less than `offset`

, `set_partial`

appends `v`

at the end of `k`

. If the size of `k`

is greater than `offset`

+length of `v`

, `set_partial`

leaves the last bytes of `k`

unchanged.

The result is `Error (`Value_expected k)`

if `k`

refers to a dictionary in `t`

.

`val remove : t -> key -> (unit, write_error) result Lwt.t`

`remove t k`

removes any binding of `k`

in `t`

. If `k`

was bound to a dictionary, the full dictionary will be removed.

Durability is guaranteed.

`rename t source dest`

rename `source`

to `dest`

in `t`

. If `source`

and `dest`

are both bound to values in `t`

, `dest`

is removed and the binding of `source`

is moved to `dest`

. If `dest`

is bound to a dictionary in `t`

, `source`

is moved inside `dest`

. If `source`

is bound to a dictionary, the full dictionary is moved.

The result is `Error (`Not_found source)`

if `source`

does not exists in `t`

. The result is `Error (`Value_expected source)`

if `source`

is bound to a dictionary in `t`

and `dest`

is bound to a value in `t`

. The result id `Error (`Rename_source_prefix (source, dest))`

if `source`

is a prefix of `dest`

, and `source`

is a directory.

`val free : t -> int64`

`free t`

is the number of unused bytes.