public class ForwardingReadWriteTransaction extends ForwardingTransaction implements ReadWriteTransaction
ReadWriteTransaction
implementation which forwards all interface method invocation to a delegate
instance.CREATE_MISSING_PARENTS, FAIL_ON_MISSING_PARENTS
Constructor and Description |
---|
ForwardingReadWriteTransaction(ReadWriteTransaction delegate) |
Modifier and Type | Method and Description |
---|---|
boolean |
cancel()
Cancels the transaction.
|
com.google.common.util.concurrent.FluentFuture<? extends CommitInfo> |
commit()
Commits this transaction to be asynchronously applied to update the logical data tree.
|
protected ReadWriteTransaction |
delegate() |
void |
delete(LogicalDatastoreType store,
InstanceIdentifier<?> path)
Removes a piece of data from specified path.
|
com.google.common.util.concurrent.FluentFuture<Boolean> |
exists(LogicalDatastoreType store,
InstanceIdentifier<?> path)
Determines if data data exists in the provided logical data store located at the provided path.
|
<T extends DataObject> |
merge(LogicalDatastoreType store,
InstanceIdentifier<T> path,
T data)
Merges a piece of data with the existing data at a specified path.
|
<T extends DataObject> |
merge(LogicalDatastoreType store,
InstanceIdentifier<T> path,
T data,
boolean createMissingParents)
Deprecated.
|
<T extends DataObject> |
mergeParentStructureMerge(LogicalDatastoreType store,
InstanceIdentifier<T> path,
T data)
Merges a piece of data with the existing data at a specified path.
|
<T extends DataObject> |
mergeParentStructurePut(LogicalDatastoreType store,
InstanceIdentifier<T> path,
T data)
Stores a piece of data at the specified path.
|
<T extends DataObject> |
put(LogicalDatastoreType store,
InstanceIdentifier<T> path,
T data)
Stores a piece of data at the specified path.
|
<T extends DataObject> |
put(LogicalDatastoreType store,
InstanceIdentifier<T> path,
T data,
boolean createMissingParents)
Deprecated.
|
<T extends DataObject> |
read(LogicalDatastoreType store,
InstanceIdentifier<T> path)
Reads data from the provided logical data store located at the provided path.
|
getIdentifier
public ForwardingReadWriteTransaction(ReadWriteTransaction delegate)
protected ReadWriteTransaction delegate()
delegate
in class ForwardingTransaction
public <T extends DataObject> void put(LogicalDatastoreType store, InstanceIdentifier<T> path, T data)
WriteOperations
If you need to make sure that a parent object exists but you do not want modify its pre-existing state by using
put, consider using WriteOperations.merge(org.opendaylight.mdsal.common.api.LogicalDatastoreType, org.opendaylight.yangtools.yang.binding.InstanceIdentifier<T>, T)
instead.
put
in interface WriteOperations
store
- the logical data store which should be modifiedpath
- the data object pathdata
- the data object to be written to the specified path@Deprecated public <T extends DataObject> void put(LogicalDatastoreType store, InstanceIdentifier<T> path, T data, boolean createMissingParents)
WriteOperations
If you need to make sure that a parent object exists but you do not want modify its pre-existing state by using
put, consider using WriteOperations.merge(org.opendaylight.mdsal.common.api.LogicalDatastoreType, org.opendaylight.yangtools.yang.binding.InstanceIdentifier<T>, T)
instead.
WARNING: Using this method may introduce garbage in data store, or recreate nodes, which were deleted by
a previous transaction. It is not necessary in most scenarios and has a significantly higher cost
than WriteOperations.put(LogicalDatastoreType, InstanceIdentifier, DataObject)
and should only be used
when absolutely necessary.
put
in interface WriteOperations
store
- the logical data store which should be modifiedpath
- the data object pathdata
- the data object to be written to the specified pathcreateMissingParents
- if WriteOperations.CREATE_MISSING_PARENTS
, any missing parent nodes will be automatically
created using a merge operation. WARNING: using this option is not needed
in most scenarios and has a significant performance cost and should be avoided
whenever possible.public <T extends DataObject> void mergeParentStructurePut(LogicalDatastoreType store, InstanceIdentifier<T> path, T data)
WriteOperations
WriteOperations.put(LogicalDatastoreType, InstanceIdentifier, DataObject)
, this method will attempt to create
semantically-significant parent nodes, like list entries and presence containers, as indicated by path
.
If you need to make sure that a parent object exists but you do not want modify its pre-existing state by using
put, consider using WriteOperations.merge(org.opendaylight.mdsal.common.api.LogicalDatastoreType, org.opendaylight.yangtools.yang.binding.InstanceIdentifier<T>, T)
instead.
WARNING: Using this method may introduce garbage in data store, or recreate nodes, which were deleted by
a previous transaction. It also has a significantly higher cost than
WriteOperations.put(LogicalDatastoreType, InstanceIdentifier, DataObject)
and should only be used when
absolutely necessary.
mergeParentStructurePut
in interface WriteOperations
store
- the logical data store which should be modifiedpath
- the data object pathdata
- the data object to be written to the specified pathpublic <T extends DataObject> com.google.common.util.concurrent.FluentFuture<Optional<T>> read(LogicalDatastoreType store, InstanceIdentifier<T> path)
ReadOperations
If the target is a subtree, then the whole subtree is read (and will be accessible from the returned data object).
read
in interface ReadOperations
store
- Logical data store from which read should occur.path
- Path which uniquely identifies subtree which client want to readReadFailedException
or
an exception derived from ReadFailedException.public com.google.common.util.concurrent.FluentFuture<Boolean> exists(LogicalDatastoreType store, InstanceIdentifier<?> path)
ReadOperations
Default implementation just delegates to ReadOperations.read(LogicalDatastoreType, InstanceIdentifier)
. Implementations
are recommended to override with a more efficient implementation.
exists
in interface ReadOperations
store
- Logical data store from which read should occur.path
- Path which uniquely identifies subtree which client want to readBoolean.TRUE
.
Boolean.FALSE
.ReadFailedException
or an exception derived
from ReadFailedException.public boolean cancel()
WriteTransaction
WriteTransaction.commit()
already successfully completed)
will always fail (return false).cancel
in interface WriteTransaction
public <T extends DataObject> void merge(LogicalDatastoreType store, InstanceIdentifier<T> path, T data)
WriteOperations
If you require an explicit replace operation, use WriteOperations.put(org.opendaylight.mdsal.common.api.LogicalDatastoreType, org.opendaylight.yangtools.yang.binding.InstanceIdentifier<T>, T)
instead.
merge
in interface WriteOperations
store
- the logical data store which should be modifiedpath
- the data object pathdata
- the data object to be merged to the specified path@Deprecated public <T extends DataObject> void merge(LogicalDatastoreType store, InstanceIdentifier<T> path, T data, boolean createMissingParents)
WriteOperations
If you require an explicit replace operation, use WriteOperations.put(org.opendaylight.mdsal.common.api.LogicalDatastoreType, org.opendaylight.yangtools.yang.binding.InstanceIdentifier<T>, T)
instead.
merge
in interface WriteOperations
store
- the logical data store which should be modifiedpath
- the data object pathdata
- the data object to be merged to the specified pathcreateMissingParents
- if WriteOperations.CREATE_MISSING_PARENTS
, any missing parent nodes will be automatically
created using a merge operation. WARNING: using this option is not needed
in most scenarios and has a significant performance cost and should be avoided
whenever possible.public <T extends DataObject> void mergeParentStructureMerge(LogicalDatastoreType store, InstanceIdentifier<T> path, T data)
WriteOperations
WriteOperations.merge(LogicalDatastoreType, InstanceIdentifier, DataObject)
, this method will attempt to create
semantically-significant parent nodes, like list entries and presence containers, as indicated by path
.
If you require an explicit replace operation, use WriteOperations.put(org.opendaylight.mdsal.common.api.LogicalDatastoreType, org.opendaylight.yangtools.yang.binding.InstanceIdentifier<T>, T)
instead.
WARNING: Using this method may introduce garbage in data store, or recreate nodes, which were deleted by
a previous transaction. It is not necessary in most scenarios and has a significantly higher cost
than WriteOperations.merge(LogicalDatastoreType, InstanceIdentifier, DataObject)
. It should only be used
when absolutely necessary.
mergeParentStructureMerge
in interface WriteOperations
store
- the logical data store which should be modifiedpath
- the data object pathdata
- the data object to be merged to the specified pathpublic com.google.common.util.concurrent.FluentFuture<? extends CommitInfo> commit()
WriteTransaction
FluentFuture
conveys the result of applying the data changes.
This call logically seals the transaction, which prevents the client from further changing the data tree using
this transaction. Any subsequent calls to put(LogicalDatastoreType, Path, Object)
,
merge(LogicalDatastoreType, Path, Object)
, delete(LogicalDatastoreType, Path)
will fail
with IllegalStateException
. The transaction is marked as committed and enqueued into the data store
back-end for processing.
Whether or not the commit is successful is determined by versioning of the data tree and validation of registered commit participants if the transaction changes the data tree.
The effects of a successful commit of data depends on listeners and commit participants that are registered with the data broker.
private void doWrite(final int tries) { WriteTransaction writeTx = dataBroker.newWriteOnlyTransaction(); MyDataObject data = ...; InstanceIdentifier<MyDataObject> path = ...; writeTx.put(LogicalDatastoreType.OPERATIONAL, path, data); Futures.addCallback(writeTx.commit(), new FutureCallback<CommitInfo>() { public void onSuccess(CommitInfo result) { // succeeded } public void onFailure(Throwable t) { if (t instanceof OptimisticLockFailedException) { if(( tries - 1) > 0 ) { // do retry doWrite(tries - 1); } else { // out of retries } } else { // failed due to another type of TransactionCommitFailedException. } }); } ... doWrite(2);
Transaction may fail because of multiple reasons, such as
OptimisticLockFailedException
. It is the responsibility
of the caller to create a new transaction and commit the same modification again in order to update data
tree.
Warning: In most cases, retrying after an OptimisticLockFailedException will result in a high
probability of success. However, there are scenarios, albeit unusual, where any number of retries will
not succeed. Therefore it is strongly recommended to limit the number of retries (2 or 3) to avoid
an endless loop.
DataValidationFailedException
. User
should not retry to create new transaction with same data, since it probably will fail again.
Initial state | Tx 1 | Tx 2 | Result |
---|---|---|---|
Empty | put(A,1) | put(A,2) | Tx 2 will fail, state is A=1 |
Empty | put(A,1) | merge(A,2) | A=2 |
Empty | merge(A,1) | put(A,2) | Tx 2 will fail, state is A=1 |
Empty | merge(A,1) | merge(A,2) | A=2 |
A=0 | put(A,1) | put(A,2) | Tx 2 will fail, A=1 |
A=0 | put(A,1) | merge(A,2) | A=2 |
A=0 | merge(A,1) | put(A,2) | Tx 2 will fail, A=1 |
A=0 | merge(A,1) | merge(A,2) | A=2 |
A=0 | delete(A) | put(A,2) | Tx 2 will fail, A does not exists |
A=0 | delete(A) | merge(A,2) | A=2 |
Initial state | Tx 1 | Tx 2 | Result |
---|---|---|---|
Empty | put(TOP,[]) | put(TOP,[]) | Tx 2 will fail, state is TOP=[] |
Empty | put(TOP,[]) | merge(TOP,[]) | TOP=[] |
Empty | put(TOP,[FOO=1]) | put(TOP,[BAR=1]) | Tx 2 will fail, state is TOP=[FOO=1] |
Empty | put(TOP,[FOO=1]) | merge(TOP,[BAR=1]) | TOP=[FOO=1,BAR=1] |
Empty | merge(TOP,[FOO=1]) | put(TOP,[BAR=1]) | Tx 2 will fail, state is TOP=[FOO=1] |
Empty | merge(TOP,[FOO=1]) | merge(TOP,[BAR=1]) | TOP=[FOO=1,BAR=1] |
TOP=[] | put(TOP,[FOO=1]) | put(TOP,[BAR=1]) | Tx 2 will fail, state is TOP=[FOO=1] |
TOP=[] | put(TOP,[FOO=1]) | merge(TOP,[BAR=1]) | state is TOP=[FOO=1,BAR=1] |
TOP=[] | merge(TOP,[FOO=1]) | put(TOP,[BAR=1]) | Tx 2 will fail, state is TOP=[FOO=1] |
TOP=[] | merge(TOP,[FOO=1]) | merge(TOP,[BAR=1]) | state is TOP=[FOO=1,BAR=1] |
TOP=[] | delete(TOP) | put(TOP,[BAR=1]) | Tx 2 will fail, state is empty store |
TOP=[] | delete(TOP) | merge(TOP,[BAR=1]) | state is TOP=[BAR=1] |
TOP=[] | put(TOP/FOO,1) | put(TOP/BAR,1]) | state is TOP=[FOO=1,BAR=1] |
TOP=[] | put(TOP/FOO,1) | merge(TOP/BAR,1) | state is TOP=[FOO=1,BAR=1] |
TOP=[] | merge(TOP/FOO,1) | put(TOP/BAR,1) | state is TOP=[FOO=1,BAR=1] |
TOP=[] | merge(TOP/FOO,1) | merge(TOP/BAR,1) | state is TOP=[FOO=1,BAR=1] |
TOP=[] | delete(TOP) | put(TOP/BAR,1) | Tx 2 will fail, state is empty store |
TOP=[] | delete(TOP) | merge(TOP/BAR,1] | Tx 2 will fail, state is empty store |
TOP=[FOO=1] | put(TOP/FOO,2) | put(TOP/BAR,1) | state is TOP=[FOO=2,BAR=1] |
TOP=[FOO=1] | put(TOP/FOO,2) | merge(TOP/BAR,1) | state is TOP=[FOO=2,BAR=1] |
TOP=[FOO=1] | merge(TOP/FOO,2) | put(TOP/BAR,1) | state is TOP=[FOO=2,BAR=1] |
TOP=[FOO=1] | merge(TOP/FOO,2) | merge(TOP/BAR,1) | state is TOP=[FOO=2,BAR=1] |
TOP=[FOO=1] | delete(TOP/FOO) | put(TOP/BAR,1) | state is TOP=[BAR=1] |
TOP=[FOO=1] | delete(TOP/FOO) | merge(TOP/BAR,1] | state is TOP=[BAR=1] |
txA = broker.newWriteTransaction(); // allocates new transaction, data tree is empty txB = broker.newWriteTransaction(); // allocates new transaction, data tree is empty txA.put(CONFIGURATION, PATH, A); // writes to PATH value A txB.put(CONFIGURATION, PATH, B) // writes to PATH value B ListenableFuture futureA = txA.commit(); // transaction A is sealed and committed ListenebleFuture futureB = txB.commit(); // transaction B is sealed and committedCommit of transaction A will be processed asynchronously and data tree will be updated to contain value
A
for PATH
. Returned FluentFuture
will
successfully complete once state is applied to data tree.
Commit of Transaction B will fail, because previous transaction also modified path in a
concurrent way. The state introduced by transaction B will not be applied. Returned
FluentFuture
object will fail with OptimisticLockFailedException
exception, which indicates to client that concurrent transaction prevented the committed
transaction from being applied.
A successful commit produces implementation-specific CommitInfo
structure, which is used to communicate
post-condition information to the caller. Such information can contain commit-id, timing information or any
other information the implementation wishes to share.
commit
in interface WriteTransaction
TransactionCommitFailedException
or an exception derived from TransactionCommitFailedException.public void delete(LogicalDatastoreType store, InstanceIdentifier<?> path)
WriteOperations
delete
in interface WriteOperations
store
- Logical data store which should be modifiedpath
- Data object pathCopyright © 2019 OpenDaylight. All rights reserved.