Introduced design document for Data Tree
[mdsal.git] / docs / design / conceptual-data-tree.adoc
1 = Conceptual Data Tree
2 Robert Varga <rovarga@cisco.com>
3 :rfc6020: https://tools.ietf.org/html/rfc6020
4 :mdsal-apidoc: https://nexus.opendaylight.org/content/sites/site/org.opendaylight.mdsal/boron/apidocs/org/opendaylight/mdsal/dom/api/
5
6 :toclevel: 3
7 :toc:
8
9
10 == Terminology
11
12 Data Tree::
13   The instatiated logical tree representing configuration or operational state
14   data of modeled problem domain (e.g controller, network)
15
16 Data Tree Consumer::
17   Component acting on data, after this data are introduced into particular
18   subtree(s) of Data Tree.
19
20 Data Tree Identifier::
21   A unique identifier for a particular subtree of Data Tree. It is composed of
22   the logical data store type and the instance identifier of the root node.
23   It is represented by `DOMDataTreeIdentifier`.
24
25 Data Tree Producer::
26   Component responsible for providing data for particular subtree(s) of Data Tree.
27
28 Data Tree Shard::
29   Component responsible for providing storage or access to particular subtree
30   of Data Tree.
31
32 Shard Layout::
33   Longest-prefix mapping between Data Tree Identifiers and Data Tree Shards
34   responsible for providing access to data subtree.
35
36
37 == Basic Concepts
38
39 === Data Tree is a Namespace
40 The concept of a data tree comes from {rfc6020}[RFC6020]. It is is vaguely split
41 into two instances, configuration and operational. The implicit assumption is that
42 *config implies oper*, e.g. any configuration data is also valid operational data.
43 Further interactions between the two are left undefined and YANG language is not
44 strictly extensible in the number and semantics of these instances, leaving
45 a lot to implementation details. An outline of use, consistent with current
46 MD-SAL design, is outlined in
47 https://tools.ietf.org/html/draft-kwatsen-netmod-opstate[draft-kwatsen-netmod-opstate].
48
49 OpenDaylight MD-SAL design makes no inherent assumptions about config/oper
50 relationship, treating them as separate entities and making them fully
51 addressable (via `DOMDataTreeIdentifier`). It is up to MD-SAL plugins (e.g. protocol
52 plugins, applications) to maintain this relationship. This reflects
53 the asynchronous nature of applying configuration and also the fact that
54 intended configuration data may be subject to translation (such as template
55 configuration instantiation).
56
57 Each of configuration and operational spaces are instances of the Conceptual Data Tree.
58 Any data item in the conceptual data tree is addressed via `YangInstanceIdentifier`,
59 which is a hierarchical. content-based, unique identifier. All applications
60 identify data using these identifiers to MD-SAL services, which are expect
61 to perform proper namespace management such that logical operation connectivity
62 is maintained.
63
64 === Identifiers versus Locators
65 It is important to note that when we talk about Identifiers and Locators,
66 we *do not* mean
67 https://en.wikipedia.org/wiki/Uniform_Resource_Identifier[URIs and URLs],
68 but rather URNs and URLs as strictly separate entities. MD-SAL plugins do not
69 have access to locators and it is the job of MD-SAL services to provide location
70 independence.
71
72 Exact details on how a particular MD-SAL service achieves location independence
73 is currently left up to the implementation, which leads to the problem of having
74 MD-SAL service cooperate, such as storing data in different backends (in-memory,
75 SQL, NoSQL, etc.) and providing unified access to all available data. Note that
76 data availability is subject to capabilities of the storage engine and its
77 operational state, which leads to the design decision that `YangInstanceIdentifier`
78 needs to be performed in two steps:
79
80 . a longest-prefix match is performed to locate the storage backend instance for
81   that identifier
82 . masked path elements are resolved by the storage backend.
83
84 === Data Tree Shard
85 A process similar to the first step is performed today by the Distributed Data Store
86 implementation to split data into Shards. The concept of a shard as currently
87 implemented is limited to specifying namespaces and does not allow pluggable
88 storage engines.
89
90 In the context of the conceptual data tree, the Shard concept is generalized
91 as the shorthad equivalent of a storage backend instance. Shards can be attached
92 at any (even wildcard) `YangInstanceIdentifier`. This contract is exposed via
93 the `DOMShardedDataTree`, which is an MD-SAL SPI class implementing
94 an `YangInstanceIdentifier` -> `Shard` registry service. This is an omnipresent
95 MD-SAL service, Shard Registry, whose visibility scope is a single
96 OpenDaylight instance (e.g. a cluster member). *Shard Layout* is used to refer
97 to the mapping information contained in this service.
98
99 === Federation, Replication and High Availability
100
101 Support for various multi-node scenarios is a concern outside of core MD-SAL.
102 If a particular scenario requires the shard layout to be replicated (either
103 fully or partially), it is up to the Shard providers to maintain an omnipresent
104 service on each node, which in turn is responsible for dynamically registering
105 `DOMDataTreeShard` instances with Shard Registry.
106
107 Since the Shard Layout is strictly local to a particular OpenDaylight instance,
108 an OpenDaylight cluster is geared towards being asymmetric with each node
109 serving its own view of the data. This allows each node to project its local
110 operational details, as well as partitioning of the data set being worked on
111 based on workload and node availability. Partial symmetry of the conceptual
112 data tree can still be maintained to the extent that a particular deployment
113 requires.
114
115 == Design
116
117 [[design-listener]]
118 ==== Data Tree Listener
119
120 Data Tree Listener is data consumer, e.g. process wanting to act on data
121 after it has been introduced to the conceptual data tree.
122
123 Data Tree Listener implements {mdsal-apidoc}DOMDataTreeListener.html[DOMDataTreeListener]
124 interface and registers itself using {mdsal-apidoc}DOMDataTreeService.html[DOMDataTreeService].
125
126 Data Tree Listener may register for multiple subtrees and each time it is invoked
127 it will be provided with current state of all subtrees, it is listening for.
128
129
130 // FIXME: Consider linking / inlining interface
131
132 .DOMDataTreeListener interface signature
133 [source, java]
134 ----
135 public interface DOMDataTreeListener extends EventListener {
136
137   void onDataTreeChanged(Collection<DataTreeCandidate> changes, // (1)
138     Map<DOMDataTreeIdentifier, NormalizedNode<?, ?>> subtrees);
139
140   void onDataTreeFailed(Collection<DOMDataTreeListeningException> causes); // (2)
141 }
142 ----
143 <1> Invoked when subscribed data tree changed. `changes` contains collection
144     of changes, `subtrees` contains current state of all subtrees to which
145     listener is registered.
146 <2> Invoked when a subtree listening failure occurs. This can be triggered,
147     for example, when a connection to external subtree source is broken.
148
149 [[design-producer]]
150 ==== Data Tree Producer
151
152 Data Tree Producer represents source of data in system.
153 Producer implementations are not required to implement specific interface, but
154 uses a {mdsal-apidoc}DOMDataTreeProducer.html[DOMDataTreeProducer] instance
155 to publish data (modify conceptual data tree).
156
157 Data Tree Producer is exclusively bound to subtree(s) of Conceptual Data Tree,
158 which prevents other producers to modify same subtree.
159
160 * Failed Data Tree Producer still holds namespace claim (exclusive lock of subtree)
161   till it is closed.
162
163 {mdsal-apidoc}DOMDataTreeProducer.html[DOMDataTreeProducer]  Represents Data producer context
164
165 * allows transactions to be submitted to the subtrees specified at creation time
166 * at any given time there may be a single transaction open.
167 * once a transaction is submitted, it will proceed to be committed asynchronously.
168
169
170
171 // FIXME: Consider linking / inlining interface
172
173 .DOMDataTreeProducer interface signature
174 [source, java]
175 ----
176 public interface DOMDataTreeProducer extends DOMDataTreeProducerFactory, AutoCloseable {
177   DOMDataWriteTransaction createTransaction(boolean isolated); // (1)
178   DOMDataTreeProducer createProducer(Collection<DOMDataTreeIdentifier> subtrees); // (2)
179 }
180 ----
181 <1> Allocates new transaction, all transactions previously allocated must have
182     been either submitted or canceled. Setting `isolated` to `true` disables
183     state compression for this transaction.
184 <2> Creates sub-producer for provided `subtrees`, parent producer loses the
185     ability to access the specified paths until the resulting (child) producer
186     is shut down.
187
188 [[design-shard]]
189 === Data Tree Shard
190
191 - *Data Tree Shard* is always bound to either `OPERATIONAL`, or `CONFIG` space, never combined.
192
193 - *Data Tree Shards* may be nested, parent shard must be aware of sub-shards and
194  has to execute every request in the context of a self-consistent view
195  of sub-shards liveness. Data requests passing through it need to be multiplexed
196  with sub-shard creation/deletion.
197
198 - *Shard Layout* is local to OpenDaylight instance.
199
200 - *Shard Layout* is modified by agents (registering / unregistering Data Tree Shards)
201 in order to make Data Tree Shard and underlaying data available to local instance
202
203
204 ==== Registering Shard
205
206 NOTE: Namespace in this context means Data Tree Identifier prefix
207
208 . *Claim namespace* - Agent registering shard must prove that it has sufficient
209   rights to modify subtree where shard is going to be attached.
210   Namespace claim is realized by having Data Tree Producer instance which is
211   bound to same subtree as shard, and producer must not have any open child
212   producers and should not have any outstanding transactions.
213
214 . *Create shard instance* - Once namespace is claimed, agent creates
215   shard instance.
216 . *Attach shard* - Agent registers created shard instance along with providing
217   Data Tree Producer instance to verify namespace claim. Shard is verified if it
218   is able to cooperate with parent shard and then it is attached to parent shard
219   and Shard layout.
220 . *Remove namespace claim* (optional) - If shard is providing storage for applications,
221   agent should close Data Tree Producer instance in order to make subtree available
222   to applications.
223
224 IMPORTANT: Step 1, 2 and 3  may fail and recovery strategy depends
225 on step which failed and failure reason.
226
227 // FIXME: Describe possible failures and recovery scenarios