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