public final class Entity implements Serializable {
private static final long serialVersionUID = 1L;
- private static final QName ENTITY_QNAME =
- org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.core.general.entity.rev150820.Entity.QNAME;
+ private static final QName ENTITY_QNAME = org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang
+ .controller.md.sal.core.general.entity.rev150820.Entity.QNAME;
private static final QName ENTITY_NAME = QName.create(ENTITY_QNAME, "name");
private final String type;
}
/**
- *
- * @return id of entity
+ * Returns the id of entity.
*/
@Nonnull
- public YangInstanceIdentifier getId(){
+ public YangInstanceIdentifier getId() {
return id;
}
/**
- *
- * @return type of entity
+ * Returns the type of entity.
*/
@Nonnull
- public String getType(){
+ public String getType() {
return type;
}
@Override
- public boolean equals(Object o) {
- if (this == o) {
+ public boolean equals(Object obj) {
+ if (this == obj) {
return true;
}
- if (o == null || getClass() != o.getClass()) {
+ if (obj == null || getClass() != obj.getClass()) {
return false;
}
- Entity entity = (Entity) o;
+ Entity entity = (Entity) obj;
if (!id.equals(entity.id)) {
return false;
* Registers a candidate for ownership of the given entity. Only one such request can be made per entity
* per process. If multiple requests for registering a candidate for a given entity are received in the
* current process a CandidateAlreadyRegisteredException will be thrown.
+ *
* <p>
* The registration is performed asynchronously and any registered {@link EntityOwnershipListener} is
* notified of ownership status changes for the entity.
*
* @param entity the entity which the Candidate wants to own
* @return a registration object that can be used to unregister the Candidate
- * @throws org.opendaylight.controller.md.sal.common.api.clustering.CandidateAlreadyRegisteredException
+ * @throws CandidateAlreadyRegisteredException if the candidate is already registered
*/
EntityOwnershipCandidateRegistration registerCandidate(@Nonnull Entity entity)
throws CandidateAlreadyRegisteredException;
* @param listener the listener that is interested in the entities
* @return a registration object that can be used to unregister the Listener
*/
- EntityOwnershipListenerRegistration registerListener(@Nonnull String entityType, @Nonnull EntityOwnershipListener listener);
+ EntityOwnershipListenerRegistration registerListener(@Nonnull String entityType,
+ @Nonnull EntityOwnershipListener listener);
/**
* Gets the current ownership state information for an entity.
Optional<EntityOwnershipState> getOwnershipState(@Nonnull Entity forEntity);
/**
- * Check if a local candidate is registered for the given entity
+ * Check if a local candidate is registered for the given entity.
*
- * @param entity
+ * @param entity the entity
* @return true if a candidate was registered locally, false otherwise
*/
boolean isCandidateRegistered(@Nonnull Entity entity);
*/
package org.opendaylight.controller.md.sal.common.api.data;
-import org.opendaylight.yangtools.concepts.Path;
-
import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.yangtools.concepts.Path;
/**
- *
- * Three phase Commit Cohort for subtree, which is
- * uniquely associated with user submitted transcation.
+ * Three phase Commit Cohort for subtree, which is uniquely associated with user submitted transaction.
*
* @param <P>
* Type of path (subtree identifier), which represents location in
/**
* Initiates a pre-commit of associated request
*
+ * <p>
* Implementation MUST NOT do any blocking calls during this callback, all
* pre-commit preparation SHOULD happen asynchronously and MUST result in
* completing returned future object.
ListenableFuture<Void> preCommit(AsyncReadTransaction<P, D> rebasedTransaction);
/**
- *
* Initiates a commit phase of associated request
*
+ * <p>
* Implementation MUST NOT do any blocking calls during this callback, all
* commit finalization SHOULD happen asynchronously and MUST result in
* completing returned future object.
ListenableFuture<Void> commit();
/**
- *
* Initiates abort phase of associated request
*
+ * <p>
* Implementation MUST NOT do any blocking calls during this callback, all
* commit finalization SHOULD happen asynchronously and MUST result in
* completing returned future object.
/**
* Three Phase Commit Coordinator with support of user-supplied commit cohorts
- * which participates in three-phase commit protocols
+ * which participates in three-phase commit protocols.
*
* @param <P>
* Type of path (subtree identifier), which represents location in
public interface AsyncConfigurationCommitCoordinator<P extends Path<P>, D> {
/**
- * Register configuration commit handler for particular subtree
+ * Register configuration commit handler for particular subtree.
*
* Configuration commit handler is invoked for all write transactions
* which modifies <code>subtree</code>
*/
package org.opendaylight.controller.md.sal.common.api.data;
-import org.opendaylight.yangtools.concepts.Path;
-
import com.google.common.util.concurrent.CheckedFuture;
+import org.opendaylight.yangtools.concepts.Path;
/**
- * User-supplied participant in three-phase commit of transaction for configuration data tree
+ * User-supplied participant in three-phase commit of transaction for configuration data tree.
*
+ * <p>
* Client-supplied implementation of commit handler for subtree, which
* is responsible for processing CAN-COMMIT phase of three-phase commit protocol
* and return CommitCohort, which provides access to additional transitions
public interface AsyncConfigurationCommitHandler<P extends Path<P>, D> {
/**
- *
* Requests a can commit phase
*
+ * <p>
* Implementations SHOULD NOT do any blocking operation during
* processing this callback.
*
* <ul>
* <li><b>is successful</b> - invocation of {@link CheckedFuture#checkedGet()} on returned future MUST
* return {@link AsyncConfigurationCommitCohort} associated with request.</li>
- * <li><b>is unsuccessful</b> - invocation of {@link CheckedFuture#checkedGet()} must throw instance of {@link DataValidationFailedException}
+ * <li><b>is unsuccessful</b> - invocation of {@link CheckedFuture#checkedGet()} must throw instance
+ * of {@link DataValidationFailedException}
* with human readable explanaition of error condition.
* </li>
* </ul>
ConfigurationCommitRequest<P, D> request);
/**
- *
* Commit Request as was submitted by client code
*
+ * <p>
* Commit Request contains list view of created / updated / removed
* path and read-only view of proposed client transaction,
* which may be used to retrieve modified or referenced data.
interface ConfigurationCommitRequest<P extends Path<P>, D> {
/**
- *
* Read-only transaction which provides access only to configuration
* data tree as if submitted transaction successfully happened and
* no other concurrent modifications happened between allocation
* of client transactions and write of client transactions.
*
+ * <p>
* Implementations of Commit Handlers are REQUIRED to use this
* read-only view to access any data from configuration data tree,
* in order to capture them as preconditions for this transaction.
*
* @return Read-only transaction which provides access only to configuration
- * data tree as if submitted transaction successfully happened
+ * data tree as if submitted transaction successfully happened
*/
AsyncReadTransaction<P, D> getReadOnlyView();
/**
- *
* Returns iteration of paths, to data which was introduced by this transaction.
*
* @return Iteration of paths, which was introduced by this transaction.
*/
Iterable<P> getCreatedPaths();
+
/**
- *
* Returns iteration of paths, to data which was updated by this transaction.
*
* @return Iteration of paths, which was updated by this transaction.
Iterable<P> getUpdatedPaths();
/**
- *
* Returns iteration of paths, to data which was removed by this transaction.
*
* @return Iteration of paths, which was removed by this transaction.
import org.opendaylight.yangtools.concepts.Path;
/**
- *
* Base interface that provides access to a conceptual data tree store and also provides the ability to
* subscribe for changes to data under a given branch of the tree.
*
AsyncDataTransactionFactory<P, D> {
/**
- *
* Scope of Data Change
*
* <p>
* Represents scope of data change (addition, replacement, deletion).
- *
* The terminology for scope types is reused from LDAP.
*
* <h2>Examples</h2>
*
+ * <p>
* Following is an example model with comments describing what notifications
* you would receive based on the scope you specify, when you are
* registering for changes on container a.
* id "b" // scope SUBTREE
* </pre>
*
+ * <p>
* Following is an example model with comments describing what notifications
* you would receive based on the scope you specify, when you are
* registering for changes on list list (without specifying concrete item in
/**
* Represent a change (addition,replacement,deletion) of the node or one of its direct
* children.
+ *
* <p>
* Note that this is done in the <i>binding independent</i> data tree and so the behavior
* might be counterintuitive when used with <i>binding aware</i> interfaces particularly
* when it comes to lists. The list itself is a node in the <i>binding independent</i> tree,
* which means that if you want to listen on new elements you must listen on the list itself
* with the scope of {@link #ONE}.
+ *
* <p>
* As an example, in the below YANG snippet, listening on <tt>node</tt> with scope
* {@link #ONE} would tell you if the <tt>node-connector</tt> list was created or deleted,
* }
* </pre>
*
+ * <p>
* This scope is superset of {@link #BASE}.
*
*/
* Represents a change of the node or any of or any of its child nodes,
* direct and nested.
*
+ * <p>
* This scope is superset of {@link #ONE} and {@link #BASE}.
*
*/
SUBTREE
}
- /**
- * {@inheritDoc}
- */
@Override
AsyncReadOnlyTransaction<P, D> newReadOnlyTransaction();
- /**
- * {@inheritDoc}
- */
@Override
AsyncReadWriteTransaction<P, D> newReadWriteTransaction();
- /**
- * {@inheritDoc}
- */
@Override
AsyncWriteTransaction<P, D> newWriteOnlyTransaction();
* Registers a {@link AsyncDataChangeListener} to receive
* notifications when data changes under a given path in the conceptual data
* tree.
+ *
* <p>
* You are able to register for notifications for any node or subtree
* which can be reached via the supplied path.
+ *
* <p>
* If path type <code>P</code> allows it, you may specify paths up to the leaf nodes
* then it is possible to listen on leaf nodes.
+ *
* <p>
* You are able to register for data change notifications for a subtree even
- * if it does not exist. You will receive notification once that node is
- * created.
+ * if it does not exist. You will receive notification once that node is created.
+ *
* <p>
* If there is any preexisting data in data tree on path for which you are
* registering, you will receive initial data change event, which will
* <p>
* You are also able to specify the scope of the changes you want to be
* notified.
+ *
* <p>
* Supported scopes are:
* <ul>
* or replaced.
* </ul>
* See {@link DataChangeScope} for examples.
+ *
* <p>
* This method returns a {@link ListenerRegistration} object. To
* "unregister" your listener for changes call the "close" method on this
* returned object.
+ *
* <p>
* You MUST call close when you no longer need to receive notifications
* (such as during shutdown or for example if your bundle is shutting down).
import java.util.Map;
import java.util.Set;
-
import org.opendaylight.yangtools.concepts.Immutable;
import org.opendaylight.yangtools.concepts.Path;
/**
- *
- * An event which contains a capture of changes in a data subtree
+ * An event which contains a capture of changes in a data subtree.
*
* <p>
* Represents a notification indicating that some data at or under a particular
* path has changed. The notification contains a capture of the changes in the data
* subtree. This event is triggered by successful application of modifications
* from a transaction on the global data tree. Use the
- * {@link AsyncDataBroker#registerDataChangeListener(LogicalDatastoreType, Path, AsyncDataChangeListener, AsyncDataBroker.DataChangeScope)}
+ * {@link AsyncDataBroker#registerDataChangeListener(LogicalDatastoreType, Path, AsyncDataChangeListener,
+ * AsyncDataBroker.DataChangeScope)}
* method to register a listener for data change events.
*
* <p>
* A listener will only receive notifications for changes to data under the path
* they register for. See
- * {@link AsyncDataBroker#registerDataChangeListener(LogicalDatastoreType, Path, AsyncDataChangeListener, AsyncDataBroker.DataChangeScope)}
+ * {@link AsyncDataBroker#registerDataChangeListener(LogicalDatastoreType, Path, AsyncDataChangeListener,
+ * AsyncDataBroker.DataChangeScope)}
* to learn more about registration scopes.
*
* <p>
* Returns a map of paths and newly created objects, which were introduced by
* this change into conceptual data tree, if no new objects were introduced
* this map will be empty.
- *<p>
+ *
+ * <p>
* This map contains all data tree nodes (and paths to them) which were created
* and are in the scope of listener registration. The data tree nodes
* contain their whole subtree with their current state.
* Returns a map of paths and objects which were updated by this change in the
* conceptual data tree if no existing objects were updated
* this map will be empty.
- *<p>
+ *
+ * <p>
* This map contains all data tree nodes (and paths to them) which were updated
* and are in the scope of listener registration. The data tree nodes
* contain their whole subtree with their current state.
- *<p>
+ *
+ * <p>
* A Node is considered updated if it contents were replaced or one of its
* children was created, removed or updated.
- *<p>
+ *
+ * <p>
* Original state of the updated data tree nodes is in
* {@link #getOriginalData()} stored with same path.
*
/**
* Returns an immutable set of removed paths.
- *<p>
+ *
+ * <p>
* This set contains the paths to the data tree nodes which are in the scope
* of the listener registration that have been removed.
- *<p>
+ *
+ * <p>
* Original state of the removed data tree nodes is in
* {@link #getOriginalData()} stored with same path.
*
*<p>
* The view is rooted at the point where the listener, to which the event is
* being delivered, was registered.
- *<p>
+ *
+ * <p>
* If listener used a wildcarded path (if supported by path type) during
* registration for change listeners this method returns null, and original
* state can be accessed only via {@link #getOriginalData()}
/**
* Returns an immutable stable view of data, which captures the state of data
* store after the reported change.
- *<p>
+ *
+ * <p>
* The view is rooted at the point where the listener, to which the event is
* being delivered, was registered.
- *<p>
+ *
+ * <p>
* If listener used a wildcarded path (if supported by path type) during
* registration for change listeners this method returns null, and state
* can be accessed only via {@link #getCreatedData()},
package org.opendaylight.controller.md.sal.common.api.data;
import java.util.EventListener;
-
import org.opendaylight.yangtools.concepts.Path;
/**
*
* <p>
* User-supplied implementations of this listener interface MUST register via
- * {@link AsyncDataBroker#registerDataChangeListener(LogicalDatastoreType, Path, AsyncDataChangeListener, AsyncDataBroker.DataChangeScope)}
+ * {@link AsyncDataBroker#registerDataChangeListener(LogicalDatastoreType, Path, AsyncDataChangeListener,
+ * AsyncDataBroker.DataChangeScope)}
* in order to start receiving data change events, which capture state changes
* in a subtree.
*
@Deprecated
public interface AsyncDataChangeListener<P extends Path<P>, D> extends EventListener {
/**
- *
* Invoked when there is data change for the particular path, which was used to
* register this listener.
+ *
* <p>
* This method may be also invoked during registration of the listener if
* there is any preexisting data in the conceptual data tree for supplied path.
* implementations may optimize the transaction for reading if they know ahead
* of time that you only need to read data - such as not keeping additional meta-data,
* which may be required for write transactions.
- *<p>
+ *
+ * <p>
* <b>Implementation Note:</b> This interface is not intended to be implemented
* by users of MD-SAL, but only to be consumed by them.
*
public interface AsyncDataTransactionFactory<P extends Path<P>, D> {
/**
- * Allocates a new read-only transaction which provides an immutable snapshot of
- * the data tree.
- *<p>
+ * Allocates a new read-only transaction which provides an immutable snapshot of the data tree.
+ *
+ * <p>
* The view of data tree is an immutable snapshot of current data tree state when
* transaction was allocated.
*
* used only by callers which are exclusive writers (exporters of data)
* to the subtree they modify. This prevents optimistic
* lock failures as described in {@link AsyncWriteTransaction#commit()}.
+ *
* <p>
* Exclusivity of writers to particular subtree SHOULD BE enforced by
* external locking mechanism.
import org.opendaylight.yangtools.concepts.Path;
/**
- *
* Marker interface for stateful read view of the data tree.
*
* <p>
* that action happened after other asynchronous action. Use of blocking call
* {@link com.google.common.util.concurrent.ListenableFuture#get()} is discouraged for most
* uses and you should use
- * {@link com.google.common.util.concurrent.Futures#addCallback(com.google.common.util.concurrent.ListenableFuture, com.google.common.util.concurrent.FutureCallback)}
+ * {@link com.google.common.util.concurrent.Futures#addCallback(com.google.common.util.concurrent.ListenableFuture,
+ * com.google.common.util.concurrent.FutureCallback)}
* or other functions from {@link com.google.common.util.concurrent.Futures} to
* register more specific listeners.
*
*
* <h3>Transaction local state</h3>
*
+ * <p>
* Let assume initial state of data tree for <code>PATH</code> is <code>A</code>
* .
*
* tx1afterCommit.read(OPERATIONAL,PATH).get(); // returns Optional containing B
* </pre>
*
+ * <p>
* As you could see read-write transaction provides capabilities as
* {@link AsyncWriteTransaction} but also allows for reading proposed changes as
* if they already happened.
* <b>Note:</b> examples contains blocking calls on future only to illustrate
* that action happened after other asynchronous action. Use of blocking call
* {@link com.google.common.util.concurrent.ListenableFuture#get()} is discouraged for most uses and you should
- * use
- * {@link com.google.common.util.concurrent.Futures#addCallback(com.google.common.util.concurrent.ListenableFuture, com.google.common.util.concurrent.FutureCallback)}
+ * use {@link com.google.common.util.concurrent.Futures#addCallback(com.google.common.util.concurrent.ListenableFuture,
+ * com.google.common.util.concurrent.FutureCallback)}
* or other functions from {@link com.google.common.util.concurrent.Futures} to
* register more specific listeners.
*
/**
- *
* A common parent for all transactions which operate on a conceptual data tree.
*
+ * <p>
* See derived transaction types for more concrete behavior:
* <ul>
* <li>{@link AsyncReadTransaction} - Read capabilities, user is able to read data from data tree</li>
* <li>{@link AsyncWriteTransaction} - Write capabilities, user is able to propose changes to data tree</li>
- * <li>{@link AsyncReadWriteTransaction} - Read and Write capabilities, user is able to read state and to propose changes of state.</li>
+ * <li>{@link AsyncReadWriteTransaction} - Read and Write capabilities, user is able to read state and to propose
+ * changes of state.</li>
* </ul>
*
* <b>Implementation Note:</b> This interface is not intended to be implemented
@Override
Object getIdentifier();
-
-
}
*/
package org.opendaylight.controller.md.sal.common.api.data;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.ListenableFuture;
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.yangtools.concepts.Path;
import org.opendaylight.yangtools.yang.common.RpcResult;
-import com.google.common.util.concurrent.CheckedFuture;
-import com.google.common.util.concurrent.ListenableFuture;
-
/**
* Write transaction provides mutation capabilities for a data tree.
*
* Initial state of write transaction is a stable snapshot of the current data tree.
* The state is captured when the transaction is created and its state and underlying
* data tree are not affected by other concurrently running transactions.
+ *
* <p>
* Write transactions are isolated from other concurrent write transactions. All
* writes are local to the transaction and represent only a proposal of state
* change for the data tree and it is not visible to any other concurrently running
* transaction.
+ *
* <p>
* Applications make changes to the local data tree in the transaction by via the
* <b>put</b>, <b>merge</b>, and <b>delete</b> operations.
* Stores a piece of data at a specified path. This acts as an add / replace
* operation, which is to say that whole subtree will be replaced by the
* specified data.
+ *
* <p>
* Performing the following put operations:
*
* 2) container { list [ b ] }
* </pre>
*
+ * <p>
* will result in the following data being present:
*
* <pre>
* Merges a piece of data with the existing data at a specified path. Any pre-existing data
* which is not explicitly overwritten will be preserved. This means that if you store a container,
* its child lists will be merged.
+ *
* <p>
* Performing the following merge operations:
*
* 2) container { list [ b ] }
* </pre>
*
+ * <p>
* will result in the following data being present:
*
* <pre>
* container { list [ a, b ] }
* </pre>
*
+ * <p>
* This also means that storing the container will preserve any
* augmentations which have been attached to it.
*
* <h2>Delete operation</h2>
* Removes a piece of data from a specified path.
+ *
* <p>
* After applying changes to the local data tree, applications publish the changes proposed in the
* transaction by calling {@link #submit} on the transaction. This seals the transaction
* (preventing any further writes using this transaction) and submits it to be
* processed and applied to global conceptual data tree.
+ *
* <p>
* The transaction commit may fail due to a concurrent transaction modifying and committing data in
* an incompatible way. See {@link #submit} for more concrete commit failure examples.
+ *
* <p>
* <b>Implementation Note:</b> This interface is not intended to be implemented
* by users of MD-SAL, but only to be consumed by them.
/**
* Cancels the transaction.
*
+ * <p>
* Transactions can only be cancelled if it's status is
* {@link TransactionStatus#NEW} or {@link TransactionStatus#SUBMITED}
*
+ * <p>
* Invoking cancel() on {@link TransactionStatus#FAILED} or
* {@link TransactionStatus#CANCELED} will have no effect, and transaction
* is considered cancelled.
*
+ * <p>
* Invoking cancel() on finished transaction (future returned by {@link #submit()}
* already completed with {@link TransactionStatus#COMMITED}) will always
* fail (return false).
*
- * @return <tt>false</tt> if the task could not be cancelled,
- * typically because it has already completed normally;
+ * @return <tt>false</tt> if the task could not be cancelled, typically because it has already completed normally
* <tt>true</tt> otherwise
*
*/
/**
* Submits this transaction to be asynchronously applied to update the logical data tree.
* The returned CheckedFuture conveys the result of applying the data changes.
+ *
* <p>
* <b>Note:</b> It is strongly recommended to process the CheckedFuture result in an asynchronous
* manner rather than using the blocking get() method. See example usage below.
+ *
* <p>
* This call logically seals the transaction, which prevents the client from
* further changing data tree using this transaction. Any subsequent calls to
* {@link #delete(LogicalDatastoreType, Path)} will fail with
* {@link IllegalStateException}.
*
+ * <p>
* The transaction is marked as {@link TransactionStatus#SUBMITED} and
* enqueued into the data store back-end for processing.
*
* <p>
* Whether or not the commit is successful is determined by versioning
* of the data tree and validation of registered commit participants
- * ({@link AsyncConfigurationCommitHandler})
- * if the transaction changes the data tree.
+ * ({@link AsyncConfigurationCommitHandler}) if the transaction changes the data tree.
+ *
* <p>
* The effects of a successful commit of data depends on data change listeners
* ({@link AsyncDataChangeListener}) and commit participants
* doWrite( 2 );
* </pre>
* <h2>Failure scenarios</h2>
+ *
* <p>
* Transaction may fail because of multiple reasons, such as
* <ul>
*
* <h3>Change compatibility</h3>
*
+ * <p>
* There are several sets of changes which could be considered incompatible
* between two transactions which are derived from same initial state.
* Rules for conflict detection applies recursively for each subtree
*
* <h4>Change compatibility of leafs, leaf-list items</h4>
*
+ * <p>
* Following table shows state changes and failures between two concurrent transactions,
* which are based on same initial state, Tx 1 completes successfully
* before Tx 2 is submitted.
*
* <h4>Change compatibility of subtrees</h4>
*
+ * <p>
* Following table shows state changes and failures between two concurrent transactions,
* which are based on same initial state, Tx 1 completes successfully
* before Tx 2 is submitted.
* <tr><td>Empty</td><td>put(TOP,[])</td><td>put(TOP,[])</td><td>Tx 2 will fail, state is TOP=[]</td></tr>
* <tr><td>Empty</td><td>put(TOP,[])</td><td>merge(TOP,[])</td><td>TOP=[]</td></tr>
*
- * <tr><td>Empty</td><td>put(TOP,[FOO=1])</td><td>put(TOP,[BAR=1])</td><td>Tx 2 will fail, state is TOP=[FOO=1]</td></tr>
+ * <tr><td>Empty</td><td>put(TOP,[FOO=1])</td><td>put(TOP,[BAR=1])</td><td>Tx 2 will fail, state is TOP=[FOO=1]
+ * </td></tr>
* <tr><td>Empty</td><td>put(TOP,[FOO=1])</td><td>merge(TOP,[BAR=1])</td><td>TOP=[FOO=1,BAR=1]</td></tr>
*
- * <tr><td>Empty</td><td>merge(TOP,[FOO=1])</td><td>put(TOP,[BAR=1])</td><td>Tx 2 will fail, state is TOP=[FOO=1]</td></tr>
+ * <tr><td>Empty</td><td>merge(TOP,[FOO=1])</td><td>put(TOP,[BAR=1])</td><td>Tx 2 will fail, state is TOP=[FOO=1]
+ * </td></tr>
* <tr><td>Empty</td><td>merge(TOP,[FOO=1])</td><td>merge(TOP,[BAR=1])</td><td>TOP=[FOO=1,BAR=1]</td></tr>
*
- * <tr><td>TOP=[]</td><td>put(TOP,[FOO=1])</td><td>put(TOP,[BAR=1])</td><td>Tx 2 will fail, state is TOP=[FOO=1]</td></tr>
+ * <tr><td>TOP=[]</td><td>put(TOP,[FOO=1])</td><td>put(TOP,[BAR=1])</td><td>Tx 2 will fail, state is TOP=[FOO=1]
+ * </td></tr>
* <tr><td>TOP=[]</td><td>put(TOP,[FOO=1])</td><td>merge(TOP,[BAR=1])</td><td>state is TOP=[FOO=1,BAR=1]</td></tr>
- * <tr><td>TOP=[]</td><td>merge(TOP,[FOO=1])</td><td>put(TOP,[BAR=1])</td><td>Tx 2 will fail, state is TOP=[FOO=1]</td></tr>
+ * <tr><td>TOP=[]</td><td>merge(TOP,[FOO=1])</td><td>put(TOP,[BAR=1])</td><td>Tx 2 will fail, state is TOP=[FOO=1]
+ * </td></tr>
* <tr><td>TOP=[]</td><td>merge(TOP,[FOO=1])</td><td>merge(TOP,[BAR=1])</td><td>state is TOP=[FOO=1,BAR=1]</td></tr>
- * <tr><td>TOP=[]</td><td>delete(TOP)</td><td>put(TOP,[BAR=1])</td><td>Tx 2 will fail, state is empty store</td></tr>
+ * <tr><td>TOP=[]</td><td>delete(TOP)</td><td>put(TOP,[BAR=1])</td><td>Tx 2 will fail, state is empty store
+ * </td></tr>
* <tr><td>TOP=[]</td><td>delete(TOP)</td><td>merge(TOP,[BAR=1])</td><td>state is TOP=[BAR=1]</td></tr>
*
* <tr><td>TOP=[]</td><td>put(TOP/FOO,1)</td><td>put(TOP/BAR,1])</td><td>state is TOP=[FOO=1,BAR=1]</td></tr>
* <tr><td>TOP=[]</td><td>merge(TOP/FOO,1)</td><td>put(TOP/BAR,1)</td><td>state is TOP=[FOO=1,BAR=1]</td></tr>
* <tr><td>TOP=[]</td><td>merge(TOP/FOO,1)</td><td>merge(TOP/BAR,1)</td><td>state is TOP=[FOO=1,BAR=1]</td></tr>
* <tr><td>TOP=[]</td><td>delete(TOP)</td><td>put(TOP/BAR,1)</td><td>Tx 2 will fail, state is empty store</td></tr>
- * <tr><td>TOP=[]</td><td>delete(TOP)</td><td>merge(TOP/BAR,1]</td><td>Tx 2 will fail, state is empty store</td></tr>
+ * <tr><td>TOP=[]</td><td>delete(TOP)</td><td>merge(TOP/BAR,1]</td><td>Tx 2 will fail, state is empty store
+ * </td></tr>
*
* <tr><td>TOP=[FOO=1]</td><td>put(TOP/FOO,2)</td><td>put(TOP/BAR,1)</td><td>state is TOP=[FOO=2,BAR=1]</td></tr>
* <tr><td>TOP=[FOO=1]</td><td>put(TOP/FOO,2)</td><td>merge(TOP/BAR,1)</td><td>state is TOP=[FOO=2,BAR=1]</td></tr>
* <tr><td>TOP=[FOO=1]</td><td>merge(TOP/FOO,2)</td><td>put(TOP/BAR,1)</td><td>state is TOP=[FOO=2,BAR=1]</td></tr>
- * <tr><td>TOP=[FOO=1]</td><td>merge(TOP/FOO,2)</td><td>merge(TOP/BAR,1)</td><td>state is TOP=[FOO=2,BAR=1]</td></tr>
+ * <tr><td>TOP=[FOO=1]</td><td>merge(TOP/FOO,2)</td><td>merge(TOP/BAR,1)</td><td>state is TOP=[FOO=2,BAR=1]
+ * </td></tr>
* <tr><td>TOP=[FOO=1]</td><td>delete(TOP/FOO)</td><td>put(TOP/BAR,1)</td><td>state is TOP=[BAR=1]</td></tr>
* <tr><td>TOP=[FOO=1]</td><td>delete(TOP/FOO)</td><td>merge(TOP/BAR,1]</td><td>state is TOP=[BAR=1]</td></tr>
* </table>
*
* <h4>Conflict of two transactions</h4>
*
+ * <p>
* This example illustrates two concurrent transactions, which derived from
* same initial state of data tree and proposes conflicting modifications.
*
* ListenebleFuture futureB = txB.submit(); // transaction B is sealed and submitted
* </pre>
*
+ * <p>
* Commit of transaction A will be processed asynchronously and data tree
* will be updated to contain value <code>A</code> for <code>PATH</code>.
* Returned {@link ListenableFuture} will successfully complete once
* state is applied to data tree.
*
+ * <p>
* 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 {@link ListenableFuture} object will fail
CheckedFuture<Void,TransactionCommitFailedException> submit();
/**
+ * Deprecated.
+ *
* @deprecated Use {@link #submit()} instead.
*/
@Deprecated
import java.util.Map;
import java.util.Set;
-
import org.opendaylight.yangtools.concepts.Path;
public interface DataChange<P extends Path<P>, D> {
/**
- * Returns a map of paths and newly created objects
+ * Returns a map of paths and newly created objects.
*
* @return map of paths and newly created objects
*/
Map<P, D> getCreatedOperationalData();
/**
- * Returns a map of paths and newly created objects
+ * Returns a map of paths and newly created objects.
*
* @return map of paths and newly created objects
*/
/**
* Returns a map of paths and respective updated objects after update.
*
+ * <p>
* Original state of the object is in
* {@link #getOriginalOperationalData()}
*
/**
* Returns a map of paths and respective updated objects after update.
*
+ * <p>
* Original state of the object is in
* {@link #getOriginalConfigurationData()}
*
/**
* Returns a set of paths of removed objects.
*
+ * <p>
* Original state of the object is in
* {@link #getOriginalConfigurationData()}
*
/**
* Returns a set of paths of removed objects.
*
+ * <p>
* Original state of the object is in
* {@link #getOriginalOperationalData()}
*
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.yangtools.concepts.Path;
import org.opendaylight.yangtools.yang.common.RpcResult;
+
/**
+ * Deprecated.
*
* @deprecated Replaced by {@link AsyncWriteTransaction}
*/
@Deprecated
public interface DataModification<P extends Path<P>, D> extends DataChange<P, D>, DataReader<P, D> {
/**
- * Returns transaction identifier
+ * Returns transaction identifier.
*
* @return Transaction identifier
*/
* overwritten will be preserved. This means that if you store a container,
* its child lists will be merged. Performing the following put operations:
*
+ * <p>
* 1) container { list [ a ] }
* 2) container { list [ b ] }
*
+ * <p>
* will result in the following data being present:
*
+ * <p>
* container { list [ a, b ] }
*
+ * <p>
* This also means that storing the container will preserve any augmentations
* which have been attached to it.
*
+ * <p>
* If you require an explicit replace operation, perform
* {@link removeOperationalData} first.
*/
* overwritten will be preserved. This means that if you store a container,
* its child lists will be merged. Performing the following put operations:
*
+ * <p>
* 1) container { list [ a ] }
* 2) container { list [ b ] }
*
+ * <p>
* will result in the following data being present:
*
+ * <p>
* container { list [ a, b ] }
*
+ * <p>
* This also means that storing the container will preserve any augmentations
* which have been attached to it.
*
+ * <p>
* If you require an explicit replace operation, perform
* {@link removeConfigurationData} first.
*/
/**
* Reader for reading YANG subtrees based on their path.
*
+ * <p>
* Reader is requested to return object at specified path and all it's subnodes
* known to the reader or null if node is not found in this reader.
*
* @deprecated Replaced by org.opendaylight.controller.sal.core.spi.data.DOMStore contract.
*/
@Deprecated
-public interface DataReader<P extends Path<P> ,D> {
+public interface DataReader<P extends Path<P>, D> {
/**
- * Reads data from Operational data store located at provided path
+ * Reads data from Operational data store located at provided path.
*
* @param path Path to data
- * @return
+ * @return the data
*/
D readOperationalData(P path);
*/
package org.opendaylight.controller.md.sal.common.api.data;
+import com.google.common.base.Preconditions;
import org.opendaylight.yangtools.concepts.Path;
import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
-import com.google.common.base.Preconditions;
-
/**
- *
* Failure of asynchronous transaction commit caused by invalid data.
*
+ * <p>
* This exception is raised and returned when transaction commit
- * failed, because other data submitted via transactions
+ * failed, because other data submitted via transactions.
*
+ * <p>
* Clients usually are not able recover from this error condition by
* retrieving same transaction, since data introduced by this transaction
* are invalid.
- *
*/
public class DataValidationFailedException extends TransactionCommitFailedException {
private static final long serialVersionUID = 1L;
- private Path<?> path;
+ private final Path<?> path;
- private Class<? extends Path<?>> pathType;
+ private final Class<? extends Path<?>> pathType;
public <P extends Path<P>> DataValidationFailedException(final Class<P> pathType,final P path,
final String message, final Throwable cause) {
public final Class<? extends Path<?>> getPathType() {
return pathType;
}
-
}
* Logical atastore representing operational state of the system
* and it's components
*
+ * <p>
* This datastore is used to describe operational state of
* the system and it's operation related data.
*
* Logical Datastore representing configuration state of the system
* and it's components.
*
+ * <p>
* This datastore is used to describe intended state of
* the system and intended operation mode.
*
*/
CONFIGURATION
-
}
package org.opendaylight.controller.md.sal.common.api.data;
-import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
/**
-*
* Failure of asynchronous transaction commit caused by failure
* of optimistic locking.
*
+* <p>
* This exception is raised and returned when transaction commit
* failed, because other transaction finished successfully
* and modified same data as failed transaction.
*
+* <p>
* Clients may recover from this error condition by
* retrieving current state and submitting new updated
* transaction.
public OptimisticLockFailedException(final String message) {
this(message, null);
}
-
}
private static final long serialVersionUID = 1L;
public static final ExceptionMapper<ReadFailedException> MAPPER =
- new ExceptionMapper<ReadFailedException>("read", ReadFailedException.class) {
- @Override
- protected ReadFailedException newWithCause(String message, Throwable cause) {
- return new ReadFailedException(message, cause);
- }
+ new ExceptionMapper<ReadFailedException>("read", ReadFailedException.class) {
+ @Override
+ protected ReadFailedException newWithCause(String message, Throwable cause) {
+ return new ReadFailedException(message, cause);
+ }
};
public ReadFailedException(String message, RpcError... errors) {
* as they occurred. A chain makes no guarantees of atomicity across the chained transactions -
* the transactions are committed as soon as possible in the order that they were submitted.
*
+ * <p>
* This behaviour is different from the default AsyncDataBroker, where a
* transaction is always created from the current global state, not taking into
* account any transactions previously committed by the calling thread. Due to
* the asynchronous nature of transaction submission this can lead to surprising
* results. If a thread executes the following sequence sufficiently quickly:
*
+ * <p>
* AsyncWriteTransaction t1 = broker.newWriteOnlyTransaction();
* t1.put(id, data);
* t1.submit();
*
+ * <p>
* AsyncReadTransaction t2 = broker.newReadOnlyTransaction();
* Optional<?> maybeData = t2.read(id).get();
*
+ * <p>
* it may happen, that it sees maybeData.isPresent() == false, simply because
* t1 has not completed the processes of being applied and t2 is actually
* allocated from the previous state. This is obviously bad for users who create
* incremental state in the datastore and actually read what they write in
* subsequent transactions.
*
+ * <p>
* Using a TransactionChain instead of a broker solves this particular problem,
* and leads to expected behavior: t2 will always see the data written in t1
* present.
* The previous write transaction has to be either SUBMITTED
* ({@link AsyncWriteTransaction#submit submit} was invoked) or CANCELLED
* ({@link #close close} was invoked).
+ *
* <p>
* The returned read-only transaction presents an isolated view of the data if the previous
* write transaction was successful - in other words, this read-only transaction will see the
* The previous write transaction has to be either SUBMITTED
* ({@link AsyncWriteTransaction#submit submit} was invoked) or CANCELLED
* ({@link #close close} was invoked).
+ *
* <p>
* The returned read-write transaction presents an isolated view of the data if the previous
* write transaction was successful - in other words, this read-write transaction will see the
* state changes made by the previous write transaction in the chain. However, state which
* was introduced by other transactions outside this transaction chain after creation of
* the previous transaction is not visible.
+ *
* <p>
* Committing this read-write transaction using {@link AsyncWriteTransaction#submit submit}
* will submit the state changes in this transaction to be visible to any subsequent
* The previous write transaction has to be either SUBMITTED
* ({@link AsyncWriteTransaction#submit submit} was invoked) or CANCELLED
* ({@link #close close} was invoked).
+ *
* <p>
* The returned write-only transaction presents an isolated view of the data if the previous
* write transaction was successful - in other words, this write-only transaction will see the
* state changes made by the previous write transaction in the chain. However, state which
* was introduced by other transactions outside this transaction chain after creation of
* the previous transaction is not visible.
+ *
* <p>
* Committing this write-only transaction using {@link AsyncWriteTransaction#submit submit}
* will submit the state changes in this transaction to be visible to any subsequent
public class TransactionCommitDeadlockException extends TransactionCommitFailedException {
private static final long serialVersionUID = 1L;
private static final String DEADLOCK_MESSAGE =
- "An attempt to block on a ListenableFuture via a get method from a write " +
- "transaction submit was detected that would result in deadlock. The commit " +
- "result must be obtained asynchronously, e.g. via Futures#addCallback, to avoid deadlock.";
- private static final RpcError DEADLOCK_RPCERROR = RpcResultBuilder.newError(ErrorType.APPLICATION, "lock-denied", DEADLOCK_MESSAGE);
+ "An attempt to block on a ListenableFuture via a get method from a write "
+ + "transaction submit was detected that would result in deadlock. The commit "
+ + "result must be obtained asynchronously, e.g. via Futures#addCallback, to avoid deadlock.";
+ private static final RpcError DEADLOCK_RPCERROR = RpcResultBuilder.newError(ErrorType.APPLICATION,
+ "lock-denied", DEADLOCK_MESSAGE);
public static final Supplier<Exception> DEADLOCK_EXCEPTION_SUPPLIER =
- () -> new TransactionCommitDeadlockException(DEADLOCK_MESSAGE, DEADLOCK_RPCERROR);
+ () -> new TransactionCommitDeadlockException(DEADLOCK_MESSAGE, DEADLOCK_RPCERROR);
public TransactionCommitDeadlockException(final String message, final RpcError... errors) {
super(message, errors);
import org.opendaylight.yangtools.yang.common.RpcError;
/**
- *
- * Failed commit of asynchronous transaction
- *
- * This exception is raised and returned when transaction commit
- * failed.
- *
+ * Failed commit of asynchronous transaction. This exception is raised and returned when transaction commit failed.
*/
public class TransactionCommitFailedException extends OperationFailedException {
/**
* Interface for publishing YANG-modeled notifications.
+ *
* <p>
* Users of this interface can publish any YANG-modeled notification which will
* be delivered to all subscribed listeners.
+ *
* <p>
* Preferred way of publishing of notifications is done by invoking {@link #publish(Object)}.
*
* The metadata required to deliver a notification to the correct listeners is
* extracted from the published notification.
*
- *
+ * <p>
* FIXME: Consider clarification of execution/delivery policy, how it will be
* affected by Actor model and cluster-wide notifications.
*
/**
* Publishes a notification and notifies subscribed listeners. All listener
* notifications are done via a default executor.
+ *
* <p>
* <b>Note:</b> This call will block when the default executor is saturated
* and the notification queue for this executor is full.
/**
* Publishes a notification and notifies subscribed listeners. All listener
* notifications are done via the provided executor.
+ *
* <p>
* <b>Note:</b> Use only if necessary. Consider using
* {@link #publish(Object)} for most use-cases.
import java.util.Map;
import java.util.Set;
+
/**
* Event representing change in RPC routing table.
*
* @param <C> Type, which is used to represent Routing context.
* @param <P> Type of data tree path, which is used to identify route.
*/
-public interface RouteChange<C,P> {
+public interface RouteChange<C, P> {
/**
- *
* Returns a map of removed routes in associated routing contexts.
+ *
* <p>
* This map represents routes, which were withdrawn from broker local
* routing table and broker may need to forward RPC to other broker
* @return Map of contexts and removed routes
*/
Map<C,Set<P>> getRemovals();
+
/**
- *
- * Returns a map of announced routes in associated routing contexts.
- *
- * This map represents routes, which were announced by broker
- * and are present in broker's local routing table. This routes
- * are processed by implementations which are registered
- * to originating broker.
- *
- * @return Map of contexts and announced routes
- */
- Map<C,Set<P>> getAnnouncements();
+ * Returns a map of announced routes in associated routing contexts.
+ *
+ * <p>
+ * This map represents routes, which were announced by broker
+ * and are present in broker's local routing table. This routes
+ * are processed by implementations which are registered
+ * to originating broker.
+ *
+ * @return Map of contexts and announced routes
+ */
+ Map<C, Set<P>> getAnnouncements();
}
package org.opendaylight.controller.md.sal.common.api.routing;
import java.util.EventListener;
+
/**
+ * Listener which is interested in receiving RouteChangeEvents for its local broker.
*
- * Listener which is interested in receiving RouteChangeEvents
- * for its local broker.
* <p>
- * Listener is registerd via {@link RouteChangePublisher#registerRouteChangeListener(RouteChangeListener)}
- *
+ * Listener is registered via {@link RouteChangePublisher#registerRouteChangeListener(RouteChangeListener)}
*
* @param <C> Type, which is used to represent Routing context.
* @param <P> Type of data tree path, which is used to identify route.
*/
-public interface RouteChangeListener<C,P> extends EventListener {
+public interface RouteChangeListener<C, P> extends EventListener {
/**
* Callback which is invoked if there is an rpc routing table change.
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
+
import org.apache.commons.lang3.SerializationUtils;
import org.junit.Test;
import org.opendaylight.yangtools.yang.common.QName;