Fix a javadoc warning about empty paragraph
[mdsal.git] / common / mdsal-common-api / src / main / java / org / opendaylight / mdsal / common / api / AsyncWriteTransaction.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.mdsal.common.api;
9
10 import com.google.common.util.concurrent.CheckedFuture;
11 import com.google.common.util.concurrent.ListenableFuture;
12 import org.opendaylight.yangtools.concepts.Path;
13
14 /**
15  * Write transaction provides mutation capabilities for a data tree.
16  *
17  * <p>
18  * Initial state of write transaction is a stable snapshot of the current data tree.
19  * The state is captured when the transaction is created and its state and underlying
20  * data tree are not affected by other concurrently running transactions.
21  * <p>
22  * Write transactions are isolated from other concurrent write transactions. All
23  * writes are local to the transaction and represent only a proposal of state
24  * change for the data tree and it is not visible to any other concurrently running
25  * transaction.
26  * <p>
27  * Applications make changes to the local data tree in the transaction by via the
28  * <b>put</b>, <b>merge</b>, and <b>delete</b> operations.
29  *
30  * <h2>Put operation</h2>
31  * Stores a piece of data at a specified path. This acts as an add / replace
32  * operation, which is to say that whole subtree will be replaced by the
33  * specified data.
34  * <p>
35  * Performing the following put operations:
36  *
37  * <pre>
38  * 1) container { list [ a ] }
39  * 2) container { list [ b ] }
40  * </pre>
41  *
42  * will result in the following data being present:
43  *
44  * <pre>
45  * container { list [ b ] }
46  * </pre>
47  * <h2>Merge operation</h2>
48  * Merges a piece of data with the existing data at a specified path. Any pre-existing data
49  * which is not explicitly overwritten will be preserved. This means that if you store a container,
50  * its child lists will be merged.
51  * <p>
52  * Performing the following merge operations:
53  *
54  * <pre>
55  * 1) container { list [ a ] }
56  * 2) container { list [ b ] }
57  * </pre>
58  *
59  * will result in the following data being present:
60  *
61  * <pre>
62  * container { list [ a, b ] }
63  * </pre>
64  *
65  * This also means that storing the container will preserve any
66  * augmentations which have been attached to it.
67  *
68  * <h2>Delete operation</h2>
69  * Removes a piece of data from a specified path.
70  * <p>
71  * After applying changes to the local data tree, applications publish the changes proposed in the
72  * transaction by calling {@link #submit} on the transaction. This seals the transaction
73  * (preventing any further writes using this transaction) and submits it to be
74  * processed and applied to global conceptual data tree.
75  * <p>
76  * The transaction commit may fail due to a concurrent transaction modifying and committing data in
77  * an incompatible way. See {@link #submit} for more concrete commit failure examples.
78  * <p>
79  * <b>Implementation Note:</b> This interface is not intended to be implemented
80  * by users of MD-SAL, but only to be consumed by them.
81  *
82  * @param <P>
83  *            Type of path (subtree identifier), which represents location in
84  *            tree
85  * @param <D>
86  *            Type of data (payload), which represents data payload
87  */
88 public interface AsyncWriteTransaction<P extends Path<P>, D> extends AsyncTransaction<P, D> {
89     /**
90      * Cancels the transaction.
91      *
92      * Transactions can only be cancelled if it was not yet submited.
93      *
94      * Invoking cancel() on failed or already canceled will have no effect, and transaction is
95      * considered cancelled.
96      *
97      * Invoking cancel() on finished transaction (future returned by {@link #submit()} already
98      * successfully completed) will always fail (return false).
99      *
100      * @return <tt>false</tt> if the task could not be cancelled, typically because it has already
101      *         completed normally; <tt>true</tt> otherwise
102      *
103      */
104     boolean cancel();
105
106     /**
107      * Removes a piece of data from specified path. This operation does not fail if the specified
108      * path does not exist.
109      *
110      * @param store Logical data store which should be modified
111      * @param path Data object path
112      * @throws IllegalStateException if the transaction was submitted or canceled.
113      */
114     void delete(LogicalDatastoreType store, P path);
115
116     /**
117      * Submits this transaction to be asynchronously applied to update the logical data tree. The
118      * returned CheckedFuture conveys the result of applying the data changes.
119      * <p>
120      * <b>Note:</b> It is strongly recommended to process the CheckedFuture result in an
121      * asynchronous manner rather than using the blocking get() method. See example usage below.
122      * <p>
123      * This call logically seals the transaction, which prevents the client from further changing
124      * data tree using this transaction. Any subsequent calls to
125      * <code>put(LogicalDatastoreType, Path, Object)</code>,
126      * <code>merge(LogicalDatastoreType, Path, Object)</code>,
127      * <code>delete(LogicalDatastoreType, Path)</code> will fail with {@link IllegalStateException}.
128      *
129      * The transaction is marked as submitted and enqueued into the data store back-end for
130      * processing.
131      *
132      * <p>
133      * Whether or not the commit is successful is determined by versioning of the data tree and
134      * validation of registered commit participants if the transaction changes the data tree.
135      * <p>
136      * The effects of a successful commit of data depends on listeners 
137      * and commit participants that are registered with the data
138      * broker.
139      * <h3>Example usage:</h3>
140      *
141      * <pre>
142      *  private void doWrite( final int tries ) {
143      *      WriteTransaction writeTx = dataBroker.newWriteOnlyTransaction();
144      * 
145      *      MyDataObject data = ...;
146      *      InstanceIdentifier&lt;MyDataObject&gt; path = ...;
147      *      writeTx.put( LogicalDatastoreType.OPERATIONAL, path, data );
148      * 
149      *      Futures.addCallback( writeTx.submit(), new FutureCallback&lt;Void&gt;() {
150      *          public void onSuccess( Void result ) {
151      *              // succeeded
152      *          }
153      * 
154      *          public void onFailure( Throwable t ) {
155      *              if( t instanceof OptimisticLockFailedException ) {
156      *                  if( ( tries - 1 ) &gt; 0 ) {
157      *                      // do retry
158      *                      doWrite( tries - 1 );
159      *                  } else {
160      *                      // out of retries
161      *                  }
162      *              } else {
163      *                  // failed due to another type of TransactionCommitFailedException.
164      *              }
165      *          } );
166      * }
167      * ...
168      * doWrite( 2 );
169      * </pre>
170      *
171      * <h2>Failure scenarios</h2>
172      * <p>
173      * Transaction may fail because of multiple reasons, such as
174      * <ul>
175      * <li>Another transaction finished earlier and modified the same node in a non-compatible way
176      * (see below). In this case the returned future will fail with an
177      * {@link OptimisticLockFailedException}. It is the responsibility of the caller to create a new
178      * transaction and submit the same modification again in order to update data tree.
179      * <i><b>Warning</b>: In most cases, retrying after an OptimisticLockFailedException will result
180      * in a high probability of success. However, there are scenarios, albeit unusual, where any
181      * number of retries will not succeed. Therefore it is strongly recommended to limit the number
182      * of retries (2 or 3) to avoid an endless loop.</i></li>
183      * <li>Data change introduced by this transaction did not pass validation by commit handlers or
184      * data was incorrectly structured. Returned future will fail with a
185      * {@link DataValidationFailedException}. User should not retry to create new transaction with
186      * same data, since it probably will fail again.</li>
187      * </ul>
188      *
189      * <h3>Change compatibility</h3>
190      *
191      * There are several sets of changes which could be considered incompatible between two
192      * transactions which are derived from same initial state. Rules for conflict detection applies
193      * recursively for each subtree level.
194      *
195      * <h4>Change compatibility of leafs, leaf-list items</h4>
196      *
197      * Following table shows state changes and failures between two concurrent transactions, which
198      * are based on same initial state, Tx 1 completes successfully before Tx 2 is submitted.
199      *
200      * <table summary="Change compatibility of leaf values">
201      * <tr>
202      * <th>Initial state</th>
203      * <th>Tx 1</th>
204      * <th>Tx 2</th>
205      * <th>Result</th>
206      * </tr>
207      * <tr>
208      * <td>Empty</td>
209      * <td>put(A,1)</td>
210      * <td>put(A,2)</td>
211      * <td>Tx 2 will fail, state is A=1</td>
212      * </tr>
213      * <tr>
214      * <td>Empty</td>
215      * <td>put(A,1)</td>
216      * <td>merge(A,2)</td>
217      * <td>A=2</td>
218      * </tr>
219      *
220      * <tr>
221      * <td>Empty</td>
222      * <td>merge(A,1)</td>
223      * <td>put(A,2)</td>
224      * <td>Tx 2 will fail, state is A=1</td>
225      * </tr>
226      * <tr>
227      * <td>Empty</td>
228      * <td>merge(A,1)</td>
229      * <td>merge(A,2)</td>
230      * <td>A=2</td>
231      * </tr>
232      *
233      *
234      * <tr>
235      * <td>A=0</td>
236      * <td>put(A,1)</td>
237      * <td>put(A,2)</td>
238      * <td>Tx 2 will fail, A=1</td>
239      * </tr>
240      * <tr>
241      * <td>A=0</td>
242      * <td>put(A,1)</td>
243      * <td>merge(A,2)</td>
244      * <td>A=2</td>
245      * </tr>
246      * <tr>
247      * <td>A=0</td>
248      * <td>merge(A,1)</td>
249      * <td>put(A,2)</td>
250      * <td>Tx 2 will fail, A=1</td>
251      * </tr>
252      * <tr>
253      * <td>A=0</td>
254      * <td>merge(A,1)</td>
255      * <td>merge(A,2)</td>
256      * <td>A=2</td>
257      * </tr>
258      *
259      * <tr>
260      * <td>A=0</td>
261      * <td>delete(A)</td>
262      * <td>put(A,2)</td>
263      * <td>Tx 2 will fail, A does not exists</td>
264      * </tr>
265      * <tr>
266      * <td>A=0</td>
267      * <td>delete(A)</td>
268      * <td>merge(A,2)</td>
269      * <td>A=2</td>
270      * </tr>
271      * </table>
272      *
273      * <h4>Change compatibility of subtrees</h4>
274      *
275      * Following table shows state changes and failures between two concurrent transactions, which
276      * are based on same initial state, Tx 1 completes successfully before Tx 2 is submitted.
277      *
278      * <table summary="Change compatibility of containers">
279      * <tr>
280      * <th>Initial state</th>
281      * <th>Tx 1</th>
282      * <th>Tx 2</th>
283      * <th>Result</th>
284      * </tr>
285      *
286      * <tr>
287      * <td>Empty</td>
288      * <td>put(TOP,[])</td>
289      * <td>put(TOP,[])</td>
290      * <td>Tx 2 will fail, state is TOP=[]</td>
291      * </tr>
292      * <tr>
293      * <td>Empty</td>
294      * <td>put(TOP,[])</td>
295      * <td>merge(TOP,[])</td>
296      * <td>TOP=[]</td>
297      * </tr>
298      *
299      * <tr>
300      * <td>Empty</td>
301      * <td>put(TOP,[FOO=1])</td>
302      * <td>put(TOP,[BAR=1])</td>
303      * <td>Tx 2 will fail, state is TOP=[FOO=1]</td>
304      * </tr>
305      * <tr>
306      * <td>Empty</td>
307      * <td>put(TOP,[FOO=1])</td>
308      * <td>merge(TOP,[BAR=1])</td>
309      * <td>TOP=[FOO=1,BAR=1]</td>
310      * </tr>
311      *
312      * <tr>
313      * <td>Empty</td>
314      * <td>merge(TOP,[FOO=1])</td>
315      * <td>put(TOP,[BAR=1])</td>
316      * <td>Tx 2 will fail, state is TOP=[FOO=1]</td>
317      * </tr>
318      * <tr>
319      * <td>Empty</td>
320      * <td>merge(TOP,[FOO=1])</td>
321      * <td>merge(TOP,[BAR=1])</td>
322      * <td>TOP=[FOO=1,BAR=1]</td>
323      * </tr>
324      *
325      * <tr>
326      * <td>TOP=[]</td>
327      * <td>put(TOP,[FOO=1])</td>
328      * <td>put(TOP,[BAR=1])</td>
329      * <td>Tx 2 will fail, state is TOP=[FOO=1]</td>
330      * </tr>
331      * <tr>
332      * <td>TOP=[]</td>
333      * <td>put(TOP,[FOO=1])</td>
334      * <td>merge(TOP,[BAR=1])</td>
335      * <td>state is TOP=[FOO=1,BAR=1]</td>
336      * </tr>
337      * <tr>
338      * <td>TOP=[]</td>
339      * <td>merge(TOP,[FOO=1])</td>
340      * <td>put(TOP,[BAR=1])</td>
341      * <td>Tx 2 will fail, state is TOP=[FOO=1]</td>
342      * </tr>
343      * <tr>
344      * <td>TOP=[]</td>
345      * <td>merge(TOP,[FOO=1])</td>
346      * <td>merge(TOP,[BAR=1])</td>
347      * <td>state is TOP=[FOO=1,BAR=1]</td>
348      * </tr>
349      * <tr>
350      * <td>TOP=[]</td>
351      * <td>delete(TOP)</td>
352      * <td>put(TOP,[BAR=1])</td>
353      * <td>Tx 2 will fail, state is empty store</td>
354      * </tr>
355      * <tr>
356      * <td>TOP=[]</td>
357      * <td>delete(TOP)</td>
358      * <td>merge(TOP,[BAR=1])</td>
359      * <td>state is TOP=[BAR=1]</td>
360      * </tr>
361      *
362      * <tr>
363      * <td>TOP=[]</td>
364      * <td>put(TOP/FOO,1)</td>
365      * <td>put(TOP/BAR,1])</td>
366      * <td>state is TOP=[FOO=1,BAR=1]</td>
367      * </tr>
368      * <tr>
369      * <td>TOP=[]</td>
370      * <td>put(TOP/FOO,1)</td>
371      * <td>merge(TOP/BAR,1)</td>
372      * <td>state is TOP=[FOO=1,BAR=1]</td>
373      * </tr>
374      * <tr>
375      * <td>TOP=[]</td>
376      * <td>merge(TOP/FOO,1)</td>
377      * <td>put(TOP/BAR,1)</td>
378      * <td>state is TOP=[FOO=1,BAR=1]</td>
379      * </tr>
380      * <tr>
381      * <td>TOP=[]</td>
382      * <td>merge(TOP/FOO,1)</td>
383      * <td>merge(TOP/BAR,1)</td>
384      * <td>state is TOP=[FOO=1,BAR=1]</td>
385      * </tr>
386      * <tr>
387      * <td>TOP=[]</td>
388      * <td>delete(TOP)</td>
389      * <td>put(TOP/BAR,1)</td>
390      * <td>Tx 2 will fail, state is empty store</td>
391      * </tr>
392      * <tr>
393      * <td>TOP=[]</td>
394      * <td>delete(TOP)</td>
395      * <td>merge(TOP/BAR,1]</td>
396      * <td>Tx 2 will fail, state is empty store</td>
397      * </tr>
398      *
399      * <tr>
400      * <td>TOP=[FOO=1]</td>
401      * <td>put(TOP/FOO,2)</td>
402      * <td>put(TOP/BAR,1)</td>
403      * <td>state is TOP=[FOO=2,BAR=1]</td>
404      * </tr>
405      * <tr>
406      * <td>TOP=[FOO=1]</td>
407      * <td>put(TOP/FOO,2)</td>
408      * <td>merge(TOP/BAR,1)</td>
409      * <td>state is TOP=[FOO=2,BAR=1]</td>
410      * </tr>
411      * <tr>
412      * <td>TOP=[FOO=1]</td>
413      * <td>merge(TOP/FOO,2)</td>
414      * <td>put(TOP/BAR,1)</td>
415      * <td>state is TOP=[FOO=2,BAR=1]</td>
416      * </tr>
417      * <tr>
418      * <td>TOP=[FOO=1]</td>
419      * <td>merge(TOP/FOO,2)</td>
420      * <td>merge(TOP/BAR,1)</td>
421      * <td>state is TOP=[FOO=2,BAR=1]</td>
422      * </tr>
423      * <tr>
424      * <td>TOP=[FOO=1]</td>
425      * <td>delete(TOP/FOO)</td>
426      * <td>put(TOP/BAR,1)</td>
427      * <td>state is TOP=[BAR=1]</td>
428      * </tr>
429      * <tr>
430      * <td>TOP=[FOO=1]</td>
431      * <td>delete(TOP/FOO)</td>
432      * <td>merge(TOP/BAR,1]</td>
433      * <td>state is TOP=[BAR=1]</td>
434      * </tr>
435      * </table>
436      *
437      *
438      * <h3>Examples of failure scenarios</h3>
439      *
440      * <h4>Conflict of two transactions</h4>
441      *
442      * This example illustrates two concurrent transactions, which derived from same initial state
443      * of data tree and proposes conflicting modifications.
444      *
445      * <pre>
446      * txA = broker.newWriteTransaction(); // allocates new transaction, data tree is empty
447      * txB = broker.newWriteTransaction(); // allocates new transaction, data tree is empty
448      * 
449      * txA.put(CONFIGURATION, PATH, A);    // writes to PATH value A
450      * txB.put(CONFIGURATION, PATH, B)     // writes to PATH value B
451      * 
452      * ListenableFuture futureA = txA.submit(); // transaction A is sealed and submitted
453      * ListenebleFuture futureB = txB.submit(); // transaction B is sealed and submitted
454      * </pre>
455      *
456      * Commit of transaction A will be processed asynchronously and data tree will be updated to
457      * contain value <code>A</code> for <code>PATH</code>. Returned {@link ListenableFuture} will
458      * successfully complete once state is applied to data tree.
459      *
460      * Commit of Transaction B will fail, because previous transaction also modified path in a
461      * concurrent way. The state introduced by transaction B will not be applied. Returned
462      * {@link ListenableFuture} object will fail with {@link OptimisticLockFailedException}
463      * exception, which indicates to client that concurrent transaction prevented the submitted
464      * transaction from being applied. <br>
465      *
466      * @return a CheckFuture containing the result of the commit. The Future blocks until the commit
467      *         operation is complete. A successful commit returns nothing. On failure, the Future
468      *         will fail with a {@link TransactionCommitFailedException} or an exception derived
469      *         from TransactionCommitFailedException.
470      *
471      * @throws IllegalStateException if the transaction is already submitted or was canceled.
472      */
473     CheckedFuture<Void,TransactionCommitFailedException> submit();
474
475 }