Bug 5524: NPE in BA->BI serialization
[mdsal.git] / src / site / asciidoc / 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   An instantiated logical tree that represents configuration or operational state data of a modeled problem domain (for example, a controller or a
14   network)
15
16 Data Tree Consumer::
17   A component acting on data, after this data are introduced into one or more
18   particular subtrees of a Data Tree.
19
20 Data Tree Identifier::
21   A unique identifier for a particular subtree of a Data Tree. It is composed of
22   the logical data store type and the instance identifier of the subtree's root node. It is represented by a `DOMDataTreeIdentifier`.
23
24 Data Tree Producer::
25   A component responsible for providing data for one or more particular subtrees of a Data Tree.
26
27 Data Tree Shard::
28   A component responsible for providing storage or access to a particular subtree of a Data Tree.
29
30 Shard Layout::
31   A longest-prefix mapping between Data Tree Identifiers and Data Tree Shards
32   responsible for providing access to a data subtree.
33
34
35 == Basic Concepts
36
37 === Data Tree is a Namespace
38 The concept of a data tree comes from {rfc6020}[RFC6020]. It is is vaguely
39 split into two instances, configuration and operational. The implicit
40 assumption is that *config implies oper*, i.e. any configuration data is
41 also a valid operational data. Further interactions between the two are left
42 undefined and the YANG language is not strictly extensible in the number and
43 semantics of these instances, leaving a lot to implementation details. An
44 outline of data tree use, which is consistent with the current MD-SAL design,
45 is described in https://tools.ietf.org/html/draft-kwatsen-netmod-opstate[draft-kwatsen-netmod-opstate].
46
47 The OpenDaylight MD-SAL design makes no inherent assumptions about the
48 relationship between the configuration and operational data tree instances.
49 They are treated as separate entities and they are both fully addressable via
50 the `DOMDataTreeIdentifier` objects. It is up to MD-SAL plugins (e.g. protocol
51 plugins or applications) to maintain this relationship. This reflects the
52 asynchronous nature of applying configuration and also the fact that the
53 intended configuration data may be subject to translation (such as template
54 configuration instantiation).
55
56 Both the configuration and operational namespaces (data trees) are instances
57 of the Conceptual Data Tree. Any data item in the conceptual data tree is
58 addressed via a `YangInstanceIdentifier` object, which is a unique,
59 hierarchical, content-based identifier. All applications use the identifier
60 objects to identify data to MD-SAL services, which in turn are expected to
61 perform proper namespace management such that logical operation connectivity is
62 maintained.
63
64 // Can you reword '...are expected to perform proper namespace management such that logical operation connectivity is maintained...' - not clear what you mean
65
66 === Identifiers versus Locators
67
68 It is important to note that when we talk about Identifiers and Locators,
69 we *do not* mean
70 https://en.wikipedia.org/wiki/Uniform_Resource_Identifier[URIs and URLs],
71 but rather URNs and URLs as strictly separate entities. MD-SAL plugins do not
72 have access to locators and it is the job of MD-SAL services to provide
73 location independence.
74
75 The details of how a particular MD-SAL service achieves location independence
76 is currently left up to the service's implementation, which leads to the
77 problem of having MD-SAL services cooperate, such as storing data in different
78 backends (in-memory, SQL, NoSQL, etc.) and providing unified access to all
79 available data. Note that data availability is subject to capabilities of a
80 particular storage engine and its operational state, which leads to the design
81 decision that a `YangInstanceIdentifier` lookup needs to be performed in two
82 steps:
83
84 . A longest-prefix match is performed to locate the storage backend instance for
85   that identifier
86 . Masked path elements are resolved by the storage engine
87
88 === Data Tree Shard
89
90 A process similar to the first step above is performed today by the Distributed
91 Data Store implementation to split data into Shards. The concept of a Shard as
92 currently implemented is limited to specifying namespaces, and it does not
93 allow for pluggable storage engines.
94
95 In context of the Conceptual Data Tree, the concept of a Shard is generalized
96 as the shorthand equivalent of a storage backend instance. A Shard can be
97 attached at any (even wildcard) `YangInstanceIdentifier`. This contract is
98 exposed via the `DOMShardedDataTree`, which is an MD-SAL SPI class that
99 implements an `YangInstanceIdentifier` -> `Shard` registry service. This is
100 an omnipresent MD-SAL service, Shard Registry, whose visibility scope is a
101 single OpenDaylight instance (i.e. a cluster member). *Shard Layout* refers
102 to the mapping information contained in this service.
103
104 === Federation, Replication and High Availability
105
106 Support for various multi-node scenarios is a concern outside of core MD-SAL.
107 If a particular scenario requires the shard layout to be replicated (either
108 fully or partially), it is up to Shard providers to maintain an omnipresent
109 service on each node, which in turn is responsible for dynamically registering
110 `DOMDataTreeShard` instances with the Shard Registry service.
111
112 Since the Shard Layout is strictly local to a particular OpenDaylight instance,
113 an OpenDaylight cluster is not strictly consistent in its mapping of
114 `YangInstanceIdentifier` to data. When a query for the entire data tree is executed,
115 the returned result will vary between member instances based on the differences
116 of their Shard Layouts. This allows each node to project its local operational
117 details, as well as the partitioning of the data set being worked on based
118 on workload and node availability.
119
120 Partial symmetry of the conceptual data tree can still be maintained to
121 the extent that a particular deployment requires. For example the Shard
122 containing the OpenFlow topology can be configured to be registered on all
123 cluster members, leading to queries into that topology returning consistent
124 results.
125
126 == Design
127
128 [[design-listener]]
129 ==== Data Tree Listener
130
131 A Data Tree Listener is a data consumer, for example a process that wants
132 to act on data after it has been introduced to the Conceptual Data Tree.
133
134 A Data Tree Listener implements the {mdsal-apidoc}DOMDataTreeListener.html[DOMDataTreeListener]
135 interface and registers itself using {mdsal-apidoc}DOMDataTreeService.html[DOMDataTreeService].
136
137 A Data Tree Listener may register for multiple subtrees. Each time it is
138 invoked it will be provided with the current state of all subtrees that it
139 is registered for.
140
141
142 // FIXME: Consider linking / inlining interface
143
144 .DOMDataTreeListener interface signature
145 [source, java]
146 ----
147 public interface DOMDataTreeListener extends EventListener {
148
149   void onDataTreeChanged(Collection<DataTreeCandidate> changes, // (1)
150     Map<DOMDataTreeIdentifier, NormalizedNode<?, ?>> subtrees);
151
152   void onDataTreeFailed(Collection<DOMDataTreeListeningException> causes); // (2)
153 }
154 ----
155 <1> Invoked when the data tree to which the Data Tree Listener is subscribed
156     to changed. `changes` contains the collection of changes, `subtrees`
157     contains the current state of all subtrees to which the listener is
158     registered.
159 <2> Invoked when a subtree listening failure occurs. For example, a failure
160     can be triggered when a connection to an external subtree source is
161     broken.
162
163 [[design-producer]]
164 ==== Data Tree Producer
165
166 A Data Tree Producer represents source of data in system. Data TreeProducer
167 implementations are not required to implement a specific interface, but
168 use a {mdsal-apidoc}DOMDataTreeProducer.html[DOMDataTreeProducer] instance
169 to publish data (i.e. to modify the Conceptual Data Tree).
170
171 A Data Tree Producer is exclusively bound to one or more subtrees of the
172 Conceptual Data Tree, i.e. binding a Data Tree Producer to a subtree prevents
173 other Data Tree Producers from modifying the subtree.
174
175 * A failed Data Tree Producer still holds a claim to the namespace to which
176   it is bound (i.e. the exclusive lock of the subtree) untill it is closed.
177
178 {mdsal-apidoc}DOMDataTreeProducer.html[DOMDataTreeProducer] represents a
179 Data Tree Producer context
180
181 * allows transactions to be submitted to subtrees specified at creation
182   time
183 * at any given time there may be a single transaction open.
184 * once a transaction is submitted, it will proceed to be committed
185   asynchronously.
186
187
188
189 // FIXME: Consider linking / inlining interface
190
191 .DOMDataTreeProducer interface signature
192 [source, java]
193 ----
194 public interface DOMDataTreeProducer extends DOMDataTreeProducerFactory, AutoCloseable {
195   DOMDataWriteTransaction createTransaction(boolean isolated); // (1)
196   DOMDataTreeProducer createProducer(Collection<DOMDataTreeIdentifier> subtrees); // (2)
197 }
198 ----
199 <1> Allocates a new transaction. All previously allocated transactions must
200     have been either submitted or canceled. Setting `isolated` to `true`
201     disables state compression for this transaction.
202 <2> Creates a sub-producer for the provided `subtrees`. The parent producer
203     loses the ability to access the specified paths until the resulting child
204     producer is closed.
205
206 [[design-shard]]
207 === Data Tree Shard
208
209 - *A Data Tree Shard* is always bound to either the `OPERATIONAL`, or the
210   `CONFIG` space, never to both at the same time.
211
212 - *Data Tree Shards* may be nested, the parent shard must be aware of sub-shards
213   and execute every request in context of a self-consistent view of sub-shards
214   liveness. Data requests passing through it must be multiplexed with sub-shard
215   creations/deletions. In other words, if an application creates a transaction
216   rooted at the parent Shard and attempts to access data residing in a sub-shard,
217   the parent Shard implementation must coordinate with the sub-shard
218   implementation to provide the illusion that the data resides in the parent shard.
219   In the case of a transaction running concurrently with sub-shard creation or
220   deletion, these operations need to execute atomically with respect to each other,
221   which is to say that the transactions must completely execute as if the sub-shard
222   creation/deletion occurred before the transaction started or as if the transaction
223   completed before the sub-shard creation/deletion request was executed. This
224   requirement can also be satisfied by the Shard implementation preventing
225   transactions from completing. A Shard implementation may choose to abort any
226   open transactions prior to executing a sub-shard operation.
227
228 - *Shard Layout* is local to an OpenDaylight instance.
229
230 - *Shard Layout* is modified by agents (registering / unregistering Data Tree
231   Shards) in order to make the Data Tree Shard and the underlaying data
232   available to plugins and applications executing on that particular OpenDaylight
233   instance.
234
235 ==== Registering a Shard with the Conceptual Data Tree
236
237 NOTE: Namespace in this context means a Data Tree Identifier prefix.
238
239 . *Claim a namespace* - An agent that is registering a shard must prove that it
240   has sufficient rights to modify the subtree where the shard is going to be
241   attached. A namespace for the shard is claimed by binding a Data Tree Producer
242   instance to same subtree where the shard will be bound. The Data Tree Producer
243   must not have any open child producers, and it should not have any outstanding
244   transactions.
245
246 . *Create a shard instance* - Once a namespace is claimed, the agent creates a
247   shard instance.
248
249 . *Attach shard* - The agent registers the created shard instance and provides
250   in the reigstration the Data Tree Producer instance to verify the namespace
251   claim. The newly created Shard is checked for its ability to cooperate with
252   its parent shard. If the check is successful, the newly created Shard is
253   attached to its parent shard and recorded in the Shard layout.
254
255 . *Remove namespace claim* (optional) - If the Shard is providing storage for
256   applications, the agent should close the Data Tree Producer instance to make
257   the subtree available to applications.
258
259 IMPORTANT: Steps 1, 2 and 3 may fail, and the recovery strategy depends
260 on which step failed and on the failure reason.
261
262 // FIXME: Describe possible failures and recovery scenarios