AsyncWriteTransaction submit() with @CheckReturnValue
[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.FluentFuture;
12 import com.google.common.util.concurrent.ListenableFuture;
13 import com.google.common.util.concurrent.MoreExecutors;
14 import javax.annotation.CheckReturnValue;
15 import org.eclipse.jdt.annotation.NonNull;
16 import org.opendaylight.yangtools.concepts.Path;
17
18 /**
19  * Write transaction provides mutation capabilities for a data tree.
20  *
21  * <p>
22  * Initial state of write transaction is a stable snapshot of the current data tree.
23  * The state is captured when the transaction is created and its state and underlying
24  * data tree are not affected by other concurrently running transactions.
25  *
26  * <p>
27  * Write transactions are isolated from other concurrent write transactions. All
28  * writes are local to the transaction and represent only a proposal of state
29  * change for the data tree and it is not visible to any other concurrently running
30  * transaction.
31  *
32  * <p>
33  * Applications make changes to the local data tree in the transaction by via the
34  * <b>put</b>, <b>merge</b>, and <b>delete</b> operations.
35  *
36  * <h2>Put operation</h2>
37  * Stores a piece of data at a specified path. This acts as an add / replace
38  * operation, which is to say that whole subtree will be replaced by the
39  * specified data.
40  *
41  * <p>
42  * Performing the following put operations:
43  *
44  * <pre>
45  * 1) container { list [ a ] }
46  * 2) container { list [ b ] }
47  * </pre>
48  * will result in the following data being present:
49  *
50  * <pre>
51  * container { list [ b ] }
52  * </pre>
53  * <h2>Merge operation</h2>
54  * Merges a piece of data with the existing data at a specified path. Any pre-existing data
55  * which is not explicitly overwritten will be preserved. This means that if you store a container,
56  * its child lists will be merged.
57  *
58  * <p>
59  * Performing the following merge operations:
60  *
61  * <pre>
62  * 1) container { list [ a ] }
63  * 2) container { list [ b ] }
64  * </pre>
65  * will result in the following data being present:
66  *
67  * <pre>
68  * container { list [ a, b ] }
69  * </pre>
70  * This also means that storing the container will preserve any
71  * augmentations which have been attached to it.
72  *
73  * <h2>Delete operation</h2>
74  * Removes a piece of data from a specified path.
75  *
76  * <p>
77  * After applying changes to the local data tree, applications publish the changes proposed in the
78  * transaction by calling {@link #submit} on the transaction. This seals the transaction
79  * (preventing any further writes using this transaction) and submits it to be
80  * processed and applied to global conceptual data tree.
81  *
82  * <p>
83  * The transaction commit may fail due to a concurrent transaction modifying and committing data in
84  * an incompatible way. See {@link #submit} for more concrete commit failure examples.
85  *
86  * <p>
87  * <b>Implementation Note:</b> This interface is not intended to be implemented
88  * by users of MD-SAL, but only to be consumed by them.
89  *
90  * @param <P>
91  *            Type of path (subtree identifier), which represents location in
92  *            tree
93  * @param <D>
94  *            Type of data (payload), which represents data payload
95  */
96 public interface AsyncWriteTransaction<P extends Path<P>, D> extends AsyncTransaction<P, D> {
97     /**
98      * Cancels the transaction.
99      * Transactions can only be cancelled if it was not yet submited.
100      * Invoking cancel() on failed or already canceled will have no effect, and transaction is
101      * considered cancelled.
102      * Invoking cancel() on finished transaction (future returned by {@link #submit()} already
103      * successfully completed) will always fail (return false).
104      *
105      * @return <tt>false</tt> if the task could not be cancelled, typically because it has already
106      *         completed normally; <tt>true</tt> otherwise
107      *
108      */
109     boolean cancel();
110
111     /**
112      * Removes a piece of data from specified path. This operation does not fail if the specified
113      * path does not exist.
114      *
115      * @param store Logical data store which should be modified
116      * @param path Data object path
117      * @throws IllegalStateException if the transaction was submitted or canceled.
118      */
119     void delete(LogicalDatastoreType store, P path);
120
121     /**
122      * Submits this transaction to be asynchronously applied to update the logical data tree. The
123      * returned CheckedFuture conveys the result of applying the data changes.
124      *
125      * <p>
126      * <b>Note:</b> It is strongly recommended to process the CheckedFuture result in an
127      * asynchronous manner rather than using the blocking get() method. See example usage below.
128      *
129      * <p>
130      * This call logically seals the transaction, which prevents the client from further changing
131      * data tree using this transaction. Any subsequent calls to
132      * <code>put(LogicalDatastoreType, Path, Object)</code>,
133      * <code>merge(LogicalDatastoreType, Path, Object)</code>,
134      * <code>delete(LogicalDatastoreType, Path)</code> will fail with {@link IllegalStateException}.
135      * The transaction is marked as submitted and enqueued into the data store back-end for
136      * processing.
137      *
138      * <p>
139      * Whether or not the commit is successful is determined by versioning of the data tree and
140      * validation of registered commit participants if the transaction changes the data tree.
141      *
142      * <p>
143      * The effects of a successful commit of data depends on listeners
144      * and commit participants that are registered with the data
145      * broker.
146      * <h3>Example usage:</h3>
147      *
148      * <pre>
149      *  private void doWrite(final int tries) {
150      *      WriteTransaction writeTx = dataBroker.newWriteOnlyTransaction();
151      *      MyDataObject data = ...;
152      *      InstanceIdentifier&lt;MyDataObject&gt; path = ...;
153      *      writeTx.put(LogicalDatastoreType.OPERATIONAL, path, data);
154      *      Futures.addCallback(writeTx.submit(), new FutureCallback&lt;Void&gt;() {
155      *          public void onSuccess(Void result) {
156      *              // succeeded
157      *          }
158      *          public void onFailure(Throwable t) {
159      *              if(t instanceof OptimisticLockFailedException) {
160      *                  if(( tries - 1) &gt; 0 ) {
161      *                      // do retry
162      *                      doWrite(tries - 1);
163      *                  } else {
164      *                      // out of retries
165      *                  }
166      *              } else {
167      *                  // failed due to another type of TransactionCommitFailedException.
168      *              }
169      *          });
170      * }
171      * ...
172      * doWrite(2);
173      * </pre>
174      *
175      * <h2>Failure scenarios</h2>
176      *
177      * <p>
178      * Transaction may fail because of multiple reasons, such as
179      * <ul>
180      * <li>Another transaction finished earlier and modified the same node in a non-compatible way
181      * (see below). In this case the returned future will fail with an
182      * {@link OptimisticLockFailedException}. It is the responsibility of the caller to create a new
183      * transaction and submit the same modification again in order to update data tree.
184      * <i><b>Warning</b>: In most cases, retrying after an OptimisticLockFailedException will result
185      * in a high probability of success. However, there are scenarios, albeit unusual, where any
186      * number of retries will not succeed. Therefore it is strongly recommended to limit the number
187      * of retries (2 or 3) to avoid an endless loop.</i></li>
188      * <li>Data change introduced by this transaction did not pass validation by commit handlers or
189      * data was incorrectly structured. Returned future will fail with a
190      * {@link DataValidationFailedException}. User should not retry to create new transaction with
191      * same data, since it probably will fail again.</li>
192      * </ul>
193      *
194      * <h3>Change compatibility</h3>
195      * There are several sets of changes which could be considered incompatible between two
196      * transactions which are derived from same initial state. Rules for conflict detection applies
197      * recursively for each subtree level.
198      *
199      * <h4>Change compatibility of leafs, leaf-list items</h4>
200      * Following table shows state changes and failures between two concurrent transactions, which
201      * are based on same initial state, Tx 1 completes successfully before Tx 2 is submitted.
202      *
203      * <table summary="Change compatibility of leaf values">
204      * <tr>
205      * <th>Initial state</th>
206      * <th>Tx 1</th>
207      * <th>Tx 2</th>
208      * <th>Result</th>
209      * </tr>
210      * <tr>
211      * <td>Empty</td>
212      * <td>put(A,1)</td>
213      * <td>put(A,2)</td>
214      * <td>Tx 2 will fail, state is A=1</td>
215      * </tr>
216      * <tr>
217      * <td>Empty</td>
218      * <td>put(A,1)</td>
219      * <td>merge(A,2)</td>
220      * <td>A=2</td>
221      * </tr>
222      *
223      * <tr>
224      * <td>Empty</td>
225      * <td>merge(A,1)</td>
226      * <td>put(A,2)</td>
227      * <td>Tx 2 will fail, state is A=1</td>
228      * </tr>
229      * <tr>
230      * <td>Empty</td>
231      * <td>merge(A,1)</td>
232      * <td>merge(A,2)</td>
233      * <td>A=2</td>
234      * </tr>
235      *
236      *
237      * <tr>
238      * <td>A=0</td>
239      * <td>put(A,1)</td>
240      * <td>put(A,2)</td>
241      * <td>Tx 2 will fail, A=1</td>
242      * </tr>
243      * <tr>
244      * <td>A=0</td>
245      * <td>put(A,1)</td>
246      * <td>merge(A,2)</td>
247      * <td>A=2</td>
248      * </tr>
249      * <tr>
250      * <td>A=0</td>
251      * <td>merge(A,1)</td>
252      * <td>put(A,2)</td>
253      * <td>Tx 2 will fail, A=1</td>
254      * </tr>
255      * <tr>
256      * <td>A=0</td>
257      * <td>merge(A,1)</td>
258      * <td>merge(A,2)</td>
259      * <td>A=2</td>
260      * </tr>
261      *
262      * <tr>
263      * <td>A=0</td>
264      * <td>delete(A)</td>
265      * <td>put(A,2)</td>
266      * <td>Tx 2 will fail, A does not exists</td>
267      * </tr>
268      * <tr>
269      * <td>A=0</td>
270      * <td>delete(A)</td>
271      * <td>merge(A,2)</td>
272      * <td>A=2</td>
273      * </tr>
274      * </table>
275      *
276      * <h4>Change compatibility of subtrees</h4>
277      * Following table shows state changes and failures between two concurrent transactions, which
278      * are based on same initial state, Tx 1 completes successfully before Tx 2 is submitted.
279      *
280      * <table summary="Change compatibility of containers">
281      * <tr>
282      * <th>Initial state</th>
283      * <th>Tx 1</th>
284      * <th>Tx 2</th>
285      * <th>Result</th>
286      * </tr>
287      *
288      * <tr>
289      * <td>Empty</td>
290      * <td>put(TOP,[])</td>
291      * <td>put(TOP,[])</td>
292      * <td>Tx 2 will fail, state is TOP=[]</td>
293      * </tr>
294      * <tr>
295      * <td>Empty</td>
296      * <td>put(TOP,[])</td>
297      * <td>merge(TOP,[])</td>
298      * <td>TOP=[]</td>
299      * </tr>
300      *
301      * <tr>
302      * <td>Empty</td>
303      * <td>put(TOP,[FOO=1])</td>
304      * <td>put(TOP,[BAR=1])</td>
305      * <td>Tx 2 will fail, state is TOP=[FOO=1]</td>
306      * </tr>
307      * <tr>
308      * <td>Empty</td>
309      * <td>put(TOP,[FOO=1])</td>
310      * <td>merge(TOP,[BAR=1])</td>
311      * <td>TOP=[FOO=1,BAR=1]</td>
312      * </tr>
313      *
314      * <tr>
315      * <td>Empty</td>
316      * <td>merge(TOP,[FOO=1])</td>
317      * <td>put(TOP,[BAR=1])</td>
318      * <td>Tx 2 will fail, state is TOP=[FOO=1]</td>
319      * </tr>
320      * <tr>
321      * <td>Empty</td>
322      * <td>merge(TOP,[FOO=1])</td>
323      * <td>merge(TOP,[BAR=1])</td>
324      * <td>TOP=[FOO=1,BAR=1]</td>
325      * </tr>
326      *
327      * <tr>
328      * <td>TOP=[]</td>
329      * <td>put(TOP,[FOO=1])</td>
330      * <td>put(TOP,[BAR=1])</td>
331      * <td>Tx 2 will fail, state is TOP=[FOO=1]</td>
332      * </tr>
333      * <tr>
334      * <td>TOP=[]</td>
335      * <td>put(TOP,[FOO=1])</td>
336      * <td>merge(TOP,[BAR=1])</td>
337      * <td>state is TOP=[FOO=1,BAR=1]</td>
338      * </tr>
339      * <tr>
340      * <td>TOP=[]</td>
341      * <td>merge(TOP,[FOO=1])</td>
342      * <td>put(TOP,[BAR=1])</td>
343      * <td>Tx 2 will fail, state is TOP=[FOO=1]</td>
344      * </tr>
345      * <tr>
346      * <td>TOP=[]</td>
347      * <td>merge(TOP,[FOO=1])</td>
348      * <td>merge(TOP,[BAR=1])</td>
349      * <td>state is TOP=[FOO=1,BAR=1]</td>
350      * </tr>
351      * <tr>
352      * <td>TOP=[]</td>
353      * <td>delete(TOP)</td>
354      * <td>put(TOP,[BAR=1])</td>
355      * <td>Tx 2 will fail, state is empty store</td>
356      * </tr>
357      * <tr>
358      * <td>TOP=[]</td>
359      * <td>delete(TOP)</td>
360      * <td>merge(TOP,[BAR=1])</td>
361      * <td>state is TOP=[BAR=1]</td>
362      * </tr>
363      *
364      * <tr>
365      * <td>TOP=[]</td>
366      * <td>put(TOP/FOO,1)</td>
367      * <td>put(TOP/BAR,1])</td>
368      * <td>state is TOP=[FOO=1,BAR=1]</td>
369      * </tr>
370      * <tr>
371      * <td>TOP=[]</td>
372      * <td>put(TOP/FOO,1)</td>
373      * <td>merge(TOP/BAR,1)</td>
374      * <td>state is TOP=[FOO=1,BAR=1]</td>
375      * </tr>
376      * <tr>
377      * <td>TOP=[]</td>
378      * <td>merge(TOP/FOO,1)</td>
379      * <td>put(TOP/BAR,1)</td>
380      * <td>state is TOP=[FOO=1,BAR=1]</td>
381      * </tr>
382      * <tr>
383      * <td>TOP=[]</td>
384      * <td>merge(TOP/FOO,1)</td>
385      * <td>merge(TOP/BAR,1)</td>
386      * <td>state is TOP=[FOO=1,BAR=1]</td>
387      * </tr>
388      * <tr>
389      * <td>TOP=[]</td>
390      * <td>delete(TOP)</td>
391      * <td>put(TOP/BAR,1)</td>
392      * <td>Tx 2 will fail, state is empty store</td>
393      * </tr>
394      * <tr>
395      * <td>TOP=[]</td>
396      * <td>delete(TOP)</td>
397      * <td>merge(TOP/BAR,1]</td>
398      * <td>Tx 2 will fail, state is empty store</td>
399      * </tr>
400      *
401      * <tr>
402      * <td>TOP=[FOO=1]</td>
403      * <td>put(TOP/FOO,2)</td>
404      * <td>put(TOP/BAR,1)</td>
405      * <td>state is TOP=[FOO=2,BAR=1]</td>
406      * </tr>
407      * <tr>
408      * <td>TOP=[FOO=1]</td>
409      * <td>put(TOP/FOO,2)</td>
410      * <td>merge(TOP/BAR,1)</td>
411      * <td>state is TOP=[FOO=2,BAR=1]</td>
412      * </tr>
413      * <tr>
414      * <td>TOP=[FOO=1]</td>
415      * <td>merge(TOP/FOO,2)</td>
416      * <td>put(TOP/BAR,1)</td>
417      * <td>state is TOP=[FOO=2,BAR=1]</td>
418      * </tr>
419      * <tr>
420      * <td>TOP=[FOO=1]</td>
421      * <td>merge(TOP/FOO,2)</td>
422      * <td>merge(TOP/BAR,1)</td>
423      * <td>state is TOP=[FOO=2,BAR=1]</td>
424      * </tr>
425      * <tr>
426      * <td>TOP=[FOO=1]</td>
427      * <td>delete(TOP/FOO)</td>
428      * <td>put(TOP/BAR,1)</td>
429      * <td>state is TOP=[BAR=1]</td>
430      * </tr>
431      * <tr>
432      * <td>TOP=[FOO=1]</td>
433      * <td>delete(TOP/FOO)</td>
434      * <td>merge(TOP/BAR,1]</td>
435      * <td>state is TOP=[BAR=1]</td>
436      * </tr>
437      * </table>
438      *
439      *
440      * <h3>Examples of failure scenarios</h3>
441      *
442      * <h4>Conflict of two transactions</h4>
443      * This example illustrates two concurrent transactions, which derived from same initial state
444      * of data tree and proposes conflicting modifications.
445      *
446      * <pre>
447      * txA = broker.newWriteTransaction(); // allocates new transaction, data tree is empty
448      * txB = broker.newWriteTransaction(); // allocates new transaction, data tree is empty
449      * txA.put(CONFIGURATION, PATH, A);    // writes to PATH value A
450      * txB.put(CONFIGURATION, PATH, B)     // writes to PATH value B
451      * ListenableFuture futureA = txA.submit(); // transaction A is sealed and submitted
452      * ListenebleFuture futureB = txB.submit(); // transaction B is sealed and submitted
453      * </pre>
454      * Commit of transaction A will be processed asynchronously and data tree will be updated to
455      * contain value <code>A</code> for <code>PATH</code>. Returned {@link ListenableFuture} will
456      * successfully complete once state is applied to data tree.
457      * Commit of Transaction B will fail, because previous transaction also modified path in a
458      * concurrent way. The state introduced by transaction B will not be applied. Returned
459      * {@link ListenableFuture} object will fail with {@link OptimisticLockFailedException}
460      * exception, which indicates to client that concurrent transaction prevented the submitted
461      * transaction from being applied. <br>
462      *
463      * @return a CheckFuture containing the result of the commit. The Future blocks until the commit
464      *         operation is complete. A successful commit returns nothing. On failure, the Future
465      *         will fail with a {@link TransactionCommitFailedException} or an exception derived
466      *         from TransactionCommitFailedException.
467      * @throws IllegalStateException if the transaction is already submitted or was canceled.
468      * @deprecated Use {@link #commit()} instead.
469      */
470     @Deprecated
471     @CheckReturnValue
472     CheckedFuture<Void, TransactionCommitFailedException> submit();
473
474     /**
475      * Submits this transaction to be asynchronously applied to update the logical data tree. The returned
476      * {@link FluentFuture} conveys the result of applying the data changes.
477      *
478      * <p>
479      * This call logically seals the transaction, which prevents the client from further changing the data tree using
480      * this transaction. Any subsequent calls to <code>put(LogicalDatastoreType, Path, Object)</code>,
481      * <code>merge(LogicalDatastoreType, Path, Object)</code>, <code>delete(LogicalDatastoreType, Path)</code> will fail
482      * with {@link IllegalStateException}. The transaction is marked as submitted and enqueued into the data store
483      * back-end for processing.
484      *
485      * <p>
486      * Whether or not the commit is successful is determined by versioning of the data tree and validation of registered
487      * commit participants if the transaction changes the data tree.
488      *
489      * <p>
490      * The effects of a successful commit of data depends on listeners and commit participants that are registered with
491      * the data broker.
492      *
493      * <p>
494      * <h3>Example usage:</h3>
495      * <pre>
496      *  private void doWrite(final int tries) {
497      *      WriteTransaction writeTx = dataBroker.newWriteOnlyTransaction();
498      *      MyDataObject data = ...;
499      *      InstanceIdentifier&lt;MyDataObject&gt; path = ...;
500      *      writeTx.put(LogicalDatastoreType.OPERATIONAL, path, data);
501      *      Futures.addCallback(writeTx.submit(), new FutureCallback&lt;Void&gt;() {
502      *          public void onSuccess(Void result) {
503      *              // succeeded
504      *          }
505      *          public void onFailure(Throwable t) {
506      *              if(t instanceof OptimisticLockFailedException) {
507      *                  if(( tries - 1) &gt; 0 ) {
508      *                      // do retry
509      *                      doWrite(tries - 1);
510      *                  } else {
511      *                      // out of retries
512      *                  }
513      *              } else {
514      *                  // failed due to another type of TransactionCommitFailedException.
515      *              }
516      *          });
517      * }
518      * ...
519      * doWrite(2);
520      * </pre>
521      *
522      * <h2>Failure scenarios</h2>
523      *
524      * <p>
525      * Transaction may fail because of multiple reasons, such as
526      * <ul>
527      *   <li>
528      *     Another transaction finished earlier and modified the same node in a non-compatible way (see below). In this
529      *     case the returned future will fail with an {@link OptimisticLockFailedException}. It is the responsibility
530      *     of the caller to create a new transaction and submit the same modification again in order to update data
531      *     tree.
532      *     <i>
533      *       <b>Warning</b>: In most cases, retrying after an OptimisticLockFailedException will result in a high
534      *       probability of success. However, there are scenarios, albeit unusual, where any number of retries will
535      *       not succeed. Therefore it is strongly recommended to limit the number of retries (2 or 3) to avoid
536      *       an endless loop.
537      *     </i>
538      *   </li>
539      *   <li>Data change introduced by this transaction did not pass validation by commit handlers or data was
540      *       incorrectly structured. Returned future will fail with a {@link DataValidationFailedException}. User
541      *       should not retry to create new transaction with same data, since it probably will fail again.
542      *   </li>
543      * </ul>
544      *
545      * <h3>Change compatibility</h3>
546      * There are several sets of changes which could be considered incompatible between two transactions which are
547      * derived from same initial state. Rules for conflict detection applies recursively for each subtree level.
548      *
549      * <h4>Change compatibility of leafs, leaf-list items</h4>
550      * Following table shows state changes and failures between two concurrent transactions, which are based on same
551      * initial state, Tx 1 completes successfully before Tx 2 is submitted.
552      *
553      * <table summary="Change compatibility of leaf values">
554      * <tr>
555      * <th>Initial state</th>
556      * <th>Tx 1</th>
557      * <th>Tx 2</th>
558      * <th>Result</th>
559      * </tr>
560      * <tr>
561      * <td>Empty</td>
562      * <td>put(A,1)</td>
563      * <td>put(A,2)</td>
564      * <td>Tx 2 will fail, state is A=1</td>
565      * </tr>
566      * <tr>
567      * <td>Empty</td>
568      * <td>put(A,1)</td>
569      * <td>merge(A,2)</td>
570      * <td>A=2</td>
571      * </tr>
572      *
573      * <tr>
574      * <td>Empty</td>
575      * <td>merge(A,1)</td>
576      * <td>put(A,2)</td>
577      * <td>Tx 2 will fail, state is A=1</td>
578      * </tr>
579      * <tr>
580      * <td>Empty</td>
581      * <td>merge(A,1)</td>
582      * <td>merge(A,2)</td>
583      * <td>A=2</td>
584      * </tr>
585      *
586      *
587      * <tr>
588      * <td>A=0</td>
589      * <td>put(A,1)</td>
590      * <td>put(A,2)</td>
591      * <td>Tx 2 will fail, A=1</td>
592      * </tr>
593      * <tr>
594      * <td>A=0</td>
595      * <td>put(A,1)</td>
596      * <td>merge(A,2)</td>
597      * <td>A=2</td>
598      * </tr>
599      * <tr>
600      * <td>A=0</td>
601      * <td>merge(A,1)</td>
602      * <td>put(A,2)</td>
603      * <td>Tx 2 will fail, A=1</td>
604      * </tr>
605      * <tr>
606      * <td>A=0</td>
607      * <td>merge(A,1)</td>
608      * <td>merge(A,2)</td>
609      * <td>A=2</td>
610      * </tr>
611      *
612      * <tr>
613      * <td>A=0</td>
614      * <td>delete(A)</td>
615      * <td>put(A,2)</td>
616      * <td>Tx 2 will fail, A does not exists</td>
617      * </tr>
618      * <tr>
619      * <td>A=0</td>
620      * <td>delete(A)</td>
621      * <td>merge(A,2)</td>
622      * <td>A=2</td>
623      * </tr>
624      * </table>
625      *
626      * <h4>Change compatibility of subtrees</h4>
627      * Following table shows state changes and failures between two concurrent transactions, which are based on same
628      * initial state, Tx 1 completes successfully before Tx 2 is submitted.
629      *
630      * <table summary="Change compatibility of containers">
631      * <tr>
632      * <th>Initial state</th>
633      * <th>Tx 1</th>
634      * <th>Tx 2</th>
635      * <th>Result</th>
636      * </tr>
637      *
638      * <tr>
639      * <td>Empty</td>
640      * <td>put(TOP,[])</td>
641      * <td>put(TOP,[])</td>
642      * <td>Tx 2 will fail, state is TOP=[]</td>
643      * </tr>
644      * <tr>
645      * <td>Empty</td>
646      * <td>put(TOP,[])</td>
647      * <td>merge(TOP,[])</td>
648      * <td>TOP=[]</td>
649      * </tr>
650      *
651      * <tr>
652      * <td>Empty</td>
653      * <td>put(TOP,[FOO=1])</td>
654      * <td>put(TOP,[BAR=1])</td>
655      * <td>Tx 2 will fail, state is TOP=[FOO=1]</td>
656      * </tr>
657      * <tr>
658      * <td>Empty</td>
659      * <td>put(TOP,[FOO=1])</td>
660      * <td>merge(TOP,[BAR=1])</td>
661      * <td>TOP=[FOO=1,BAR=1]</td>
662      * </tr>
663      *
664      * <tr>
665      * <td>Empty</td>
666      * <td>merge(TOP,[FOO=1])</td>
667      * <td>put(TOP,[BAR=1])</td>
668      * <td>Tx 2 will fail, state is TOP=[FOO=1]</td>
669      * </tr>
670      * <tr>
671      * <td>Empty</td>
672      * <td>merge(TOP,[FOO=1])</td>
673      * <td>merge(TOP,[BAR=1])</td>
674      * <td>TOP=[FOO=1,BAR=1]</td>
675      * </tr>
676      *
677      * <tr>
678      * <td>TOP=[]</td>
679      * <td>put(TOP,[FOO=1])</td>
680      * <td>put(TOP,[BAR=1])</td>
681      * <td>Tx 2 will fail, state is TOP=[FOO=1]</td>
682      * </tr>
683      * <tr>
684      * <td>TOP=[]</td>
685      * <td>put(TOP,[FOO=1])</td>
686      * <td>merge(TOP,[BAR=1])</td>
687      * <td>state is TOP=[FOO=1,BAR=1]</td>
688      * </tr>
689      * <tr>
690      * <td>TOP=[]</td>
691      * <td>merge(TOP,[FOO=1])</td>
692      * <td>put(TOP,[BAR=1])</td>
693      * <td>Tx 2 will fail, state is TOP=[FOO=1]</td>
694      * </tr>
695      * <tr>
696      * <td>TOP=[]</td>
697      * <td>merge(TOP,[FOO=1])</td>
698      * <td>merge(TOP,[BAR=1])</td>
699      * <td>state is TOP=[FOO=1,BAR=1]</td>
700      * </tr>
701      * <tr>
702      * <td>TOP=[]</td>
703      * <td>delete(TOP)</td>
704      * <td>put(TOP,[BAR=1])</td>
705      * <td>Tx 2 will fail, state is empty store</td>
706      * </tr>
707      * <tr>
708      * <td>TOP=[]</td>
709      * <td>delete(TOP)</td>
710      * <td>merge(TOP,[BAR=1])</td>
711      * <td>state is TOP=[BAR=1]</td>
712      * </tr>
713      *
714      * <tr>
715      * <td>TOP=[]</td>
716      * <td>put(TOP/FOO,1)</td>
717      * <td>put(TOP/BAR,1])</td>
718      * <td>state is TOP=[FOO=1,BAR=1]</td>
719      * </tr>
720      * <tr>
721      * <td>TOP=[]</td>
722      * <td>put(TOP/FOO,1)</td>
723      * <td>merge(TOP/BAR,1)</td>
724      * <td>state is TOP=[FOO=1,BAR=1]</td>
725      * </tr>
726      * <tr>
727      * <td>TOP=[]</td>
728      * <td>merge(TOP/FOO,1)</td>
729      * <td>put(TOP/BAR,1)</td>
730      * <td>state is TOP=[FOO=1,BAR=1]</td>
731      * </tr>
732      * <tr>
733      * <td>TOP=[]</td>
734      * <td>merge(TOP/FOO,1)</td>
735      * <td>merge(TOP/BAR,1)</td>
736      * <td>state is TOP=[FOO=1,BAR=1]</td>
737      * </tr>
738      * <tr>
739      * <td>TOP=[]</td>
740      * <td>delete(TOP)</td>
741      * <td>put(TOP/BAR,1)</td>
742      * <td>Tx 2 will fail, state is empty store</td>
743      * </tr>
744      * <tr>
745      * <td>TOP=[]</td>
746      * <td>delete(TOP)</td>
747      * <td>merge(TOP/BAR,1]</td>
748      * <td>Tx 2 will fail, state is empty store</td>
749      * </tr>
750      *
751      * <tr>
752      * <td>TOP=[FOO=1]</td>
753      * <td>put(TOP/FOO,2)</td>
754      * <td>put(TOP/BAR,1)</td>
755      * <td>state is TOP=[FOO=2,BAR=1]</td>
756      * </tr>
757      * <tr>
758      * <td>TOP=[FOO=1]</td>
759      * <td>put(TOP/FOO,2)</td>
760      * <td>merge(TOP/BAR,1)</td>
761      * <td>state is TOP=[FOO=2,BAR=1]</td>
762      * </tr>
763      * <tr>
764      * <td>TOP=[FOO=1]</td>
765      * <td>merge(TOP/FOO,2)</td>
766      * <td>put(TOP/BAR,1)</td>
767      * <td>state is TOP=[FOO=2,BAR=1]</td>
768      * </tr>
769      * <tr>
770      * <td>TOP=[FOO=1]</td>
771      * <td>merge(TOP/FOO,2)</td>
772      * <td>merge(TOP/BAR,1)</td>
773      * <td>state is TOP=[FOO=2,BAR=1]</td>
774      * </tr>
775      * <tr>
776      * <td>TOP=[FOO=1]</td>
777      * <td>delete(TOP/FOO)</td>
778      * <td>put(TOP/BAR,1)</td>
779      * <td>state is TOP=[BAR=1]</td>
780      * </tr>
781      * <tr>
782      * <td>TOP=[FOO=1]</td>
783      * <td>delete(TOP/FOO)</td>
784      * <td>merge(TOP/BAR,1]</td>
785      * <td>state is TOP=[BAR=1]</td>
786      * </tr>
787      * </table>
788      *
789      *
790      * <h3>Examples of failure scenarios</h3>
791      *
792      * <h4>Conflict of two transactions</h4>
793      * This example illustrates two concurrent transactions, which derived from same initial state
794      * of data tree and proposes conflicting modifications.
795      *
796      * <pre>
797      * txA = broker.newWriteTransaction(); // allocates new transaction, data tree is empty
798      * txB = broker.newWriteTransaction(); // allocates new transaction, data tree is empty
799      * txA.put(CONFIGURATION, PATH, A);    // writes to PATH value A
800      * txB.put(CONFIGURATION, PATH, B)     // writes to PATH value B
801      * ListenableFuture futureA = txA.submit(); // transaction A is sealed and submitted
802      * ListenebleFuture futureB = txB.submit(); // transaction B is sealed and submitted
803      * </pre>
804      * Commit of transaction A will be processed asynchronously and data tree will be updated to
805      * contain value <code>A</code> for <code>PATH</code>. Returned {@link ListenableFuture} will
806      * successfully complete once state is applied to data tree.
807      * Commit of Transaction B will fail, because previous transaction also modified path in a
808      * concurrent way. The state introduced by transaction B will not be applied. Returned
809      * {@link ListenableFuture} object will fail with {@link OptimisticLockFailedException}
810      * exception, which indicates to client that concurrent transaction prevented the submitted
811      * transaction from being applied. <br>
812      *
813      * <p>
814      * A successful commit produces implementation-specific {@link CommitInfo} structure, which is used to communicate
815      * post-condition information to the caller. Such information can contain commit-id, timing information or any
816      * other information the implementation wishes to share.
817      *
818      * @return a FluentFuture containing the result of the commit information. The Future blocks until the commit
819      *         operation is complete. A successful commit returns nothing. On failure, the Future will fail with a
820      *         {@link TransactionCommitFailedException} or an exception derived from TransactionCommitFailedException.
821      * @throws IllegalStateException if the transaction is already submitted or was canceled.
822      */
823     @CheckReturnValue
824     default @NonNull FluentFuture<? extends @NonNull CommitInfo> commit() {
825         return FluentFuture.from(submit()).transformAsync((ignored) -> CommitInfo.emptyFluentFuture(),
826             MoreExecutors.directExecutor());
827     }
828 }