From: Robert Varga Date: Tue, 11 Mar 2014 12:28:59 +0000 (+0100) Subject: Bug 500: Updated data APIs with new concepts. X-Git-Tag: autorelease-tag-v20140601202136_82eb3f9~309^2 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=9fda938ef6dc037ef1c5a9fbed25469d4a532150;hp=9b07bd85d10b509d29b70b1e43b1919c5b4bcbb2 Bug 500: Updated data APIs with new concepts. - Logical Datastore Type idenfier - Asynchronous Data Broker contracts - some data broker contracts were synchronous which could misslead consumers of APIs - New Transaction subtypes with support for Asynchronous reads - read-only transaction - write-only transaction - read-write transaction - Scoped Data Change Publisher - client code is able to specify scope of changes and logical datastore type on which it is listening. Change-Id: I2367e7df633dd07b08550014bed7a35c3e88a7ba Signed-off-by: Tony Tkacik Signed-off-by: Robert Varga --- diff --git a/opendaylight/md-sal/sal-common-api/pom.xml b/opendaylight/md-sal/sal-common-api/pom.xml index 126fe8d39e..8798897a1d 100644 --- a/opendaylight/md-sal/sal-common-api/pom.xml +++ b/opendaylight/md-sal/sal-common-api/pom.xml @@ -1,17 +1,21 @@ - + 4.0.0 org.opendaylight.controller sal-parent 1.1-SNAPSHOT + sal-common-api + bundle + - scm:git:ssh://git.opendaylight.org:29418/controller.git - scm:git:ssh://git.opendaylight.org:29418/controller.git - https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL - HEAD - + scm:git:ssh://git.opendaylight.org:29418/controller.git + scm:git:ssh://git.opendaylight.org:29418/controller.git + https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL + HEAD + @@ -22,6 +26,9 @@ org.opendaylight.yangtools concepts + + com.google.guava + guava + - bundle diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncDataBroker.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncDataBroker.java new file mode 100644 index 0000000000..87bbfd3d06 --- /dev/null +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncDataBroker.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.md.sal.common.api.data; + +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.concepts.Path; + +public interface AsyncDataBroker

, D, L extends AsyncDataChangeListener> extends // + AsyncDataTransactionFactory { + + /** + * + * Scope of Data Change + * + * Represents scope of data change (addition, replacement, deletion). + * + * The terminology for types is reused from LDAP + * + * @see http://www.idevelopment.info/data/LDAP/LDAP_Resources/SEARCH_Setting_the_SCOPE_Parameter.shtml + */ + public enum DataChangeScope { + + /** + * Represents only a direct change of the node, such as replacement of node, + * addition or deletion. + * + */ + BASE, + /** + * Represent a change (addition,replacement,deletion) + * of the node or one of it's direct childs. + * + */ + ONE, + /** + * Represents a change of the node or any of it's child nodes. + * + */ + SUBTREE + } + + @Override + public AsyncReadTransaction newReadOnlyTransaction(); + + @Override + public AsyncReadWriteTransaction newReadWriteTransaction(); + + @Override + public AsyncWriteTransaction newWriteOnlyTransaction(); + + /** + * Registers {@link DataChangeListener} for Data Change callbacks + * which will be triggered on which will be triggered on the store + * + * @param store Logical store in which listener is registered. + * @param path Path (subtree identifier) on which client listener will be invoked. + * @param listener Instance of listener which should be invoked on + * @param triggeringScope Scope of change which triggers callback. + * @return Listener registration of the listener, call {@link ListenerRegistration#close()} + * to stop delivery of change events. + */ + ListenerRegistration registerDataChangeListener(LogicalDatastoreType store, P path, L listener, DataChangeScope triggeringScope); +} diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncDataChangeEvent.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncDataChangeEvent.java new file mode 100644 index 0000000000..f612e51747 --- /dev/null +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncDataChangeEvent.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.md.sal.common.api.data; + +import java.util.Map; +import java.util.Set; + +import org.opendaylight.yangtools.concepts.Immutable; +import org.opendaylight.yangtools.concepts.Path; + +public interface AsyncDataChangeEvent

,D> extends Immutable { + /** + * Returns a immutable map of paths and newly created objects + * + * @return map of paths and newly created objects + */ + Map getCreatedData(); + + /** + * Returns a immutable map of paths and respective updated objects after update. + * + * Original state of the object is in + * {@link #getOriginalData()} + * + * @return map of paths and newly created objects + */ + Map getUpdatedData(); + + /** + * Returns a immutable set of removed paths. + * + * Original state of the object is in + * {@link #getOriginalData()} + * + * @return set of removed paths + */ + Set

getRemovedPaths(); + + /** + * Return a immutable map of paths and original state of updated and removed objects. + * + * This map is populated if at changed path was previous object, and captures + * state of previous object. + * + * @return map of paths and original state of updated and removed objects. + */ + Map getOriginalData(); + + /** + * Returns a immutable stable view of data state, which + * captures state of data store before the reported change. + * + * + * The view is rooted at the point where the listener, to which the event is being delivered, was registered. + * + * @return Stable view of data before the change happened, rooted at the listener registration path. + * + */ + D getOriginalSubtree(); + + /** + * Returns a immutable stable view of data, which captures state of data store + * after the reported change. + * + * The view is rooted at the point where the listener, to which the event is being delivered, was registered. + * + * @return Stable view of data after the change happened, rooted at the listener registration path. + */ + D getUpdatedSubtree(); +} diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncDataChangeListener.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncDataChangeListener.java new file mode 100644 index 0000000000..49f07bc52b --- /dev/null +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncDataChangeListener.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.md.sal.common.api.data; + +import java.util.EventListener; + +import org.opendaylight.yangtools.concepts.Path; + +public interface AsyncDataChangeListener

, D> extends EventListener { + /** + * Note that this method may be invoked from a shared thread pool, so + * implementations SHOULD NOT perform CPU-intensive operations and they + * definitely MUST NOT invoke any potentially blocking operations. + * + * @param change Data Change Event being delivered. + */ + void onDataChanged(AsyncDataChangeEvent change); +} diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncDataTransactionFactory.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncDataTransactionFactory.java new file mode 100644 index 0000000000..732fed0f3f --- /dev/null +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncDataTransactionFactory.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.md.sal.common.api.data; + +import org.opendaylight.yangtools.concepts.Path; + +public interface AsyncDataTransactionFactory

, D> { + + AsyncReadTransaction newReadOnlyTransaction(); + + AsyncReadWriteTransaction newReadWriteTransaction(); + + AsyncWriteTransaction newWriteOnlyTransaction(); + +} diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncReadTransaction.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncReadTransaction.java new file mode 100644 index 0000000000..1d1d9101ec --- /dev/null +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncReadTransaction.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.md.sal.common.api.data; + +import java.util.concurrent.Future; + +import org.opendaylight.yangtools.concepts.Path; + +import com.google.common.base.Optional; +import com.google.common.util.concurrent.ListenableFuture; + +public interface AsyncReadTransaction

, D> extends AsyncTransaction { + + /** + * + * Reads data from provided logical data store located at provided path + * + * + * @param store + * Logical data store from which read should occur. + * @param path + * Path which uniquely identifies subtree which client want to + * read + * @return Listenable Future which contains read result + *

    + *
  • If data at supplied path exists the {@link Future#get()} + * returns Optional object containing data + *
  • If data at supplied path does not exists the + * {@link Future#get()} returns {@link Optional#absent()}. + *
+ */ + ListenableFuture> read(LogicalDatastoreType store, P path); + +} diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncReadWriteTransaction.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncReadWriteTransaction.java new file mode 100644 index 0000000000..ce740bf41d --- /dev/null +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncReadWriteTransaction.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.md.sal.common.api.data; + +import org.opendaylight.yangtools.concepts.Path; + +/** + * Transaction enabling client to have combined transaction, + * which provides read and write capabilities. + * + * + * @param

Path Type + * @param Data Type + */ +public interface AsyncReadWriteTransaction

, D> extends AsyncReadTransaction, + AsyncWriteTransaction { + +} diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncTransaction.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncTransaction.java new file mode 100644 index 0000000000..23ca275ef2 --- /dev/null +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncTransaction.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.md.sal.common.api.data; + +import org.opendaylight.yangtools.concepts.Identifiable; +import org.opendaylight.yangtools.concepts.Path; + + +/** + * + * @author + * + * @param

Type of path (subtree identifier), which represents location in tree + * @param Type of data (payload), which represents data payload + */ +public interface AsyncTransaction

,D> extends // + Identifiable, + AutoCloseable { + + @Override + public Object getIdentifier(); + + /** + * Closes transaction and releases all resources associated with it. + */ + @Override + public void close(); +} diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncWriteTransaction.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncWriteTransaction.java new file mode 100644 index 0000000000..35b9914a12 --- /dev/null +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncWriteTransaction.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.md.sal.common.api.data; + +import java.util.concurrent.Future; + +import org.opendaylight.controller.md.sal.common.api.TransactionStatus; +import org.opendaylight.yangtools.concepts.Path; +import org.opendaylight.yangtools.yang.common.RpcResult; + +public interface AsyncWriteTransaction

, D> extends AsyncTransaction { + /** + * Cancels transaction. + * + * Transaction could be only cancelled if it's status + * is {@link TransactionStatus#NEW} or {@link TransactionStatus#SUBMITED} + * + * Invoking cancel() on {@link TransactionStatus#FAILED} or {@link TransactionStatus#CANCELED} + * will have no effect. + * + * @throws IllegalStateException If transaction status is {@link TransactionStatus#COMMITED} + * + */ + public void cancel(); + + /** + * Store a piece of data at specified path. This acts as a add / replace operation, + * which is to say that whole subtree will be replaced by specified path. + * + * If you need add or merge of current object with specified use {@link #merge(LogicalDatastoreType, Path, Object)} + * + * @param store Logical data store which should be modified + * @param path Data object path + * @param data Data object to be written to specified path + * @throws IllegalStateException if the transaction is no longer {@link TransactionStatus#NEW} + */ + public void put(LogicalDatastoreType store, P path, D data); + + /** + * Store a piece of data at specified path. This acts as a merge operation, + * which is to say that 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. Performing the following put operations: + * + * 1) container { list [ a ] } + * 2) container { list [ b ] } + * + * will result in the following data being present: + * + * container { list [ a, b ] } + * + * This also means that storing the container will preserve any augmentations + * which have been attached to it. + * + * If you require an explicit replace operation, use {@link #put(LogicalDatastoreType, Path, Object)} instead. + * + * @param store Logical data store which should be modified + * @param path Data object path + * @param data Data object to be written to specified path + * @throws IllegalStateException if the transaction is no longer {@link TransactionStatus#NEW} + */ + public void merge(LogicalDatastoreType store, P path, D data); + + /** + * Remove a piece of data from specified path. This operation does not fail + * if the specified path does not exist. + * + * @param store Logical data store which should be modified + * @param path Data object path + * @throws IllegalStateException if the transaction is no longer {@link TransactionStatus#NEW} + */ + public void delete(LogicalDatastoreType store, P path); + + /** + * + * Closes transaction and resources allocated to the transaction. + * + * This call does not change Transaction status. Client SHOULD + * explicitly {@link #commit()} or {@link #cancel()} transaction. + * + * @throws IllegalStateException if the transaction has not been + * updated by invoking {@link #commit()} or {@link #cancel()}. + */ + @Override + public void close(); + + /** + * Initiates a commit of modification. This call logically seals the + * transaction, preventing any the client from interacting with the + * data stores. The transaction is marked as {@link TransactionStatus#SUBMITED} + * and enqueued into the data store backed for processing. + * + *

+ * The successful commit changes the state of the system and may affect + * several components. + * + *

+ * The effects of successful commit of data are described in the + * specifications and YANG models describing the Provider components of + * controller. It is assumed that Consumer has an understanding of this + * changes. + * + * @see DataCommitHandler for further information how two-phase commit is + * processed. + * @param store Identifier of the store, where commit should occur. + * @return Result of the Commit, containing success information or list of + * encountered errors, if commit was not successful. The Future + * blocks until {@link TransactionStatus#COMMITED} or + * {@link TransactionStatus#FAILED} is reached. + * @throws IllegalStateException if the transaction is not {@link TransactionStatus#NEW} + */ + public Future> commit(); + +} diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChangeListener.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChangeListener.java index 8787a3fe8d..669baa8d9e 100644 --- a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChangeListener.java +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChangeListener.java @@ -12,6 +12,12 @@ import java.util.EventListener; import org.opendaylight.yangtools.concepts.Path; public interface DataChangeListener

, D> extends EventListener { - + /** + * Note that this method may be invoked from a shared thread pool, so + * implementations SHOULD NOT perform CPU-intensive operations and they + * definitely MUST NOT invoke any potentially blocking operations. + * + * @param change Data Change Event being delivered. + **/ void onDataChanged(DataChangeEvent change); } diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/LogicalDatastoreType.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/LogicalDatastoreType.java new file mode 100644 index 0000000000..d2e41f1688 --- /dev/null +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/LogicalDatastoreType.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.md.sal.common.api.data; + +public enum LogicalDatastoreType { + + /** + * Logical atastore representing operational state of the system + * and it's components + * + * This datastore is used to describe operational state of + * the system and it's operation related data. + * + */ + OPERATIONAL, + /** + * Logical Datastore representing configuration state of the system + * and it's components. + * + * This datastore is used to describe intended state of + * the system and intended operation mode. + * + */ + CONFIGURATION + +} diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/TransactionChain.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/TransactionChain.java index d542935dd6..e7e0eb0ff8 100644 --- a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/TransactionChain.java +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/TransactionChain.java @@ -13,17 +13,34 @@ import org.opendaylight.yangtools.concepts.Path; * A chain of transactions. Transactions in a chain need to be committed in sequence and each * transaction should see the effects of previous transactions as if they happened. A chain * makes no guarantees of atomicity, in fact transactions are committed as soon as possible. + * */ -public interface TransactionChain

, D> extends AutoCloseable { +public interface TransactionChain

, D> extends AutoCloseable, AsyncDataTransactionFactory { + /** - * Create a new transaction which will continue the chain. The previous transaction - * has to be either COMMITTED or CANCELLED. + * Create a new read only transaction which will continue the chain. + * The previous read-write transaction has to be either COMMITED or CANCELLED. * * @return New transaction in the chain. - * @throws IllegalStateException if the previous transaction was not COMMITTED or CANCELLED. + * @throws IllegalStateException if the previous transaction was not COMMITED + * or CANCELLED. * @throws TransactionChainClosedException if the chain has been closed. */ - DataModification newTransaction(); + @Override + public AsyncReadTransaction newReadOnlyTransaction(); + + + /** + * Create a new read write transaction which will continue the chain. + * The previous read-write transaction has to be either COMMITED or CANCELLED. + * + * @return New transaction in the chain. + * @throws IllegalStateException if the previous transaction was not COMMITTED + * or CANCELLED. + * @throws TransactionChainClosedException if the chain has been closed. + */ + @Override + public AsyncReadWriteTransaction newReadWriteTransaction(); @Override void close(); diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/TransactionChainListener.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/TransactionChainListener.java index 4dac6f557e..52b0812736 100644 --- a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/TransactionChainListener.java +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/TransactionChainListener.java @@ -21,7 +21,7 @@ public interface TransactionChainListener extends EventListener { * @param transaction Transaction which caused the chain to fail * @param cause The cause of transaction failure */ - void onTransactionChainFailed(TransactionChain chain, DataModification transaction, Throwable cause); + void onTransactionChainFailed(TransactionChain chain, AsyncTransaction transaction, Throwable cause); /** * Invoked when a transaction chain is completed. A transaction chain is considered completed when it has been