Overview
The Data Access is the persistence layer and manages data items that are present in the system, which are UBStores unit of data and serve as an abstraction for the stored data. Data items contain a key and a type (which together must be unique) as well as arbitrary metadata and value. They also support the two valid time and transaction time intervals, making them support the bitemporal model.
Somewhat similar, the Shepherd is responsible for keeping track of the nodes inside the network. Nodes consist of an address, a port and a name.
The Router acts as a logical connection between the two; it manages the mapping of data items to nodes and identifies which node is supposed to store which data item. It is used both for writing data to the right node as well as finding out where to read data from.
On one hand, these components, shown in blue, provide interfaces that distributed systems can build on to implement features on a higher layer of abstraction. On the other hand, albeit they possess functional dummy implementations in UBStore, they are also meant to be overridden to enable defining own network structures and data storage mechanisms.
Denoted in red is UBStores communication facility that helps nodes to communicate with each other. Tempo mainly makes use of the built-in RMI registry UBStore exposes that enables components to specify their communication protocol and nodes to call methods on each other. Unlike the blue components, the communication module is not meant to be overridden and simply serves as an aid for UBStore users.
Lastly, UBStore offers some other services that are not unique to distributed systems, but helpful during implementation, namely a logging and a configuration facility. Logging is done via SLF4J to prevent forcing users into using a specific logging implementation
At its core, UBStore is based on OSGi for the reason of high modularity. The concepts of services and easy to swap out implementations of interfaces match the idea of UBStore very well. For example, the blue components are implemented as OSGi services that can easily be swapped out. Custom implementations simply have to register themselves within OSGi to be detected and used by UBStore.