Skip to content
This repository has been archived by the owner on Aug 13, 2020. It is now read-only.

Storage or Registry

Harald Gustafsson edited this page Sep 1, 2017 · 2 revisions

Storage or Registry

Calvin have a storage or rather a registry that contains information on runtimes, actors, ports, etc. It is used by all runtimes to look-up information for other runtimes or actors.

Types of storage

All types of information that is stored in the registry is key-value-pair based, but differs in how keys or values are constructed.

Single value

This is a normal key-value-pair with a single value for any key-string. The set-function takes a prefix- and key-string and a JSON-serializable value. So the single value can contain multiple elements, e.g. when placed in a dictonary, but needs to be replaced/deleted in its entirity.

This is typically used in Calvin to register information on a runtime, e.g. communication information, actors, e.g. which port-ids it have, etc. For more details see the calvin/runtime/north/storage.py-file and e.g. the add_node or add_actor-methods. For most single-value information there are corresponding methods in this file to keep the registry formalized using a specific prefix-string.

Set value

The set-value type functions use the same prefix- and key-strings, but the value in the pair is a set of values. The functions append and remove will add or remove the values to the set and make sure that only unique values are kept. The functions takes a list or set of values. It also have a seperate get_concat-method to retrive all the values in the set.

This type of storage is not used directly currently in Calvin but could be. Typically only small values like UUIDs should be stored in this, which then could be used to look-up further information.

Index-key

The registry implements a prefix-searchable index key-string paired with the set-value type. Hence it is possible to add/remove values for an index-key. The index is prefix-searchable for sections between /-characters. The add_index, remove_index, get_index and delete_index takes the index as either one complete-string or a list of section-strings. The methods also have a root_prefix_level that specifies how many of the sections are concatenated into one section. This is mainly since the first level typically never is needed to be searched but rather to seperate it from other types of indexes. The current implementation is not efficent since it registers the values at each index-stage, but when time permits it should be replaced with a hierarchical storage-engine plugin.

This type of storage is used in Calvin for keeping information that is mainly used for requirement matching. For example each runtime registers (add_index) their runtime-UUID for each attributes that it holds. Hence, when searching a specific atrribute index-key all runtimes that support it is returned. Likewise for calvinsys support. The attribute key-strings are formalized in calvin/utilities/attribute_resolver.py. Any attributes that are added should be placed in this file. As can be seen for e.g.

address_keys = ["country", "stateOrProvince", "locality", "street", "streetNumber", "building", "floor", "room"]

Specifies the prefix-order of an attribute, by this you could search for all runtimes in a country and state down to the room number. You could not search for all runtimes in a specific room-number without specifying the previous index-stages. Calvinsys-index today is flat (have or have not), without any qualifying information.

Future registry expansion

This gives example on how the registry can be used for more advanced searches.

Range index searches

Single range

When for example new attributes are added these might require searches for ranges instead of exact match. This can be solved for attributes where it is enough to split the ranges into smaller set of categories. As an example we might want to create an attribute for available processing on a runtime to be able to place actors on runtimes with at least some level of available processing. Hence we have a range where we would be satisfied if we find a runtime with some level or greater. An index-key could be made as:

/node-processing/gt/X/X/X/X/X
                    ^ ^ ^ ^ ^
                    | | | | largest available
                    | | | 75%
                    | | 50%
                    | 25%
                    10%

Hence making the key longer the more is needed and use as many index-stages as needed. The attribute should be formalized in calvin/utilities/attribute_resolver.py so that all runtimes interpret it identically. Likewise when we want an index that is searched for some level or smaller we create e.g.:

/node-price/lt/X/X/X/X/X
               ^ ^ ^ ^ ^
               | | | | free
               | | | $0.01
               | | $0.1
               | $1
               $10

When we need to search for a range confined on both ends we would have two indexes with both greter than and less than keys, the returned values would then need to be intersectioned. Alternatively you only have one index and search for exact matches of each index-stage and create a union.

Area

For location you want to know if a certain runtime is within a (longitude, latitude) area. This could be handled by for example take a longitude and have each digit in an index-stage.

/node-location/longitude/+/0/1/0/9/3/5/3/7/3
                                ^ implied dot
/node-location/latitude/-/5/0/8/2/4/2/6/1
                             ^implied dot

Many other variants exist that would allow for searches of areas. The two indexes would be prefix-searched stopping at an index-stage level that covers the area and the intersection is made of the results. If the area is not rectangular it can be built up of several rectangular searches and the union is taken of all the results. Here I'm disregarding that the mesh of (longitude, latitude) is not really rectangular. This can be used also for other multi-dimensional index keys.

Qualifying calvinsys

Currently the calvinsys is only registering if present or not on a runtime. In the future we could have an expansion to allow for registrering specific qualities e.g.:

/node/capabilities/calvinsys.io.display                 current key
/node/capabilities/calvinsys.io.display/color           if have color
/node/capabilities/calvinsys.io.display/height/gt/X/X   range of display heights
/node/capabilities/calvinsys.io.display/width/gt/X/X    range of display widths

This would allow for specifying more detailed requirements for an actor to be deployed to a runtime having these qualities.

Dynamic information

When data in the registry is updated it might have implication for actor placements. Hence it would be beneficial to be able to get notification when changes occures, instead of regularly request information to evaluate requirement matching. This would then need to be supported by a storage-engine plugin, not yet developed.

When data is entered into the registry it would be good to be able to have it timestamped. Potentially also validity duration is provided after which the data would auto-expire. This is useful for a requirement matching to decide if the data will likely be valid or not when placing an actor on e.g. a fast moving runtime.