From d4092f3506627d50acf9dc60961c19ab70c5e2be Mon Sep 17 00:00:00 2001 From: Tony Tkacik Date: Tue, 3 Nov 2015 12:57:03 +0100 Subject: [PATCH] Bug 1435: Introduced DOM Data Commit Cohort & Validation APIs Introduced DOM Data Broker level APIs for 3PC commit cohorts and utility abstract class for implementing Data Tree validator. Change-Id: I54ca7e022f8dee278c8cd9156514b62dd37cfc97 Signed-off-by: Tony Tkacik --- .../mdsal/common/api/PostCanCommitStep.java | 66 ++++++++++ .../mdsal/common/api/PostPreCommitStep.java | 61 +++++++++ .../common/api/ThreePhaseCommitStep.java | 41 +++++++ .../mdsal/dom/api/DOMDataTreeCandidate.java | 34 +++++ .../dom/api/DOMDataTreeCommitCohort.java | 116 ++++++++++++++++++ .../DOMDataTreeCommitCohortRegistration.java | 21 ++++ .../api/DOMDataTreeCommitCohortRegistry.java | 32 +++++ 7 files changed, 371 insertions(+) create mode 100644 common/mdsal-common-api/src/main/java/org/opendaylight/mdsal/common/api/PostCanCommitStep.java create mode 100644 common/mdsal-common-api/src/main/java/org/opendaylight/mdsal/common/api/PostPreCommitStep.java create mode 100644 common/mdsal-common-api/src/main/java/org/opendaylight/mdsal/common/api/ThreePhaseCommitStep.java create mode 100644 dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMDataTreeCandidate.java create mode 100644 dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMDataTreeCommitCohort.java create mode 100644 dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMDataTreeCommitCohortRegistration.java create mode 100644 dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMDataTreeCommitCohortRegistry.java diff --git a/common/mdsal-common-api/src/main/java/org/opendaylight/mdsal/common/api/PostCanCommitStep.java b/common/mdsal-common-api/src/main/java/org/opendaylight/mdsal/common/api/PostCanCommitStep.java new file mode 100644 index 0000000000..05e09a8275 --- /dev/null +++ b/common/mdsal-common-api/src/main/java/org/opendaylight/mdsal/common/api/PostCanCommitStep.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2015 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.mdsal.common.api; + +import com.google.common.annotations.Beta; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import javax.annotation.Nonnull; + +/** + * + * User implementation of steps following can-commit in three phase protocol. + * + * If no additional visibility into transaction and data being aborted or committed is needed, use + * {@link #NOOP} implementation. + * + */ +@Beta +public interface PostCanCommitStep extends ThreePhaseCommitStep { + + /** + * No-op implementation of abort, pre-commit and commit steps. + * + * This implementation should be used if user logic does only validation of data and does not + * need to perform any actions associated with pre-commit, commit or abort. + */ + PostCanCommitStep NOOP = new PostCanCommitStep() { + + @Override + public ListenableFuture abort() { + return ThreePhaseCommitStep.NOOP_ABORT_FUTURE; + } + + @Override + public ListenableFuture preCommit() { + return PostPreCommitStep.NOOP_FUTURE; + } + }; + + /** + * Successful future, returning {@link #NOOP} implementation of {@link PostCanCommitStep}s. + * + **/ + CheckedFuture NOOP_SUCCESS_FUTURE = + Futures.immediateCheckedFuture(NOOP); + + /** + * Initiates a pre-commit of associated request + * + * 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. + * + * @return Future which is completed once pre-commit phase for this request is finished. + * + **/ + @Nonnull + ListenableFuture preCommit(); + +} diff --git a/common/mdsal-common-api/src/main/java/org/opendaylight/mdsal/common/api/PostPreCommitStep.java b/common/mdsal-common-api/src/main/java/org/opendaylight/mdsal/common/api/PostPreCommitStep.java new file mode 100644 index 0000000000..2941786b41 --- /dev/null +++ b/common/mdsal-common-api/src/main/java/org/opendaylight/mdsal/common/api/PostPreCommitStep.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2015 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.mdsal.common.api; + +import com.google.common.annotations.Beta; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; + +/** + * + * User implementation of steps following pre-commit from Three-Phase Protocol. + * + */ +@Beta +public interface PostPreCommitStep extends ThreePhaseCommitStep { + + /** + * No-op implementation of {@link #abort()} and {@link #commit()} method, which always success + * calls. + * + * This implementation is intended for users which may not need to implement commit and abort + * method. + * + */ + PostPreCommitStep NOOP = new PostPreCommitStep() { + + @Override + public ListenableFuture abort() { + return ThreePhaseCommitStep.NOOP_ABORT_FUTURE; + } + + @Override + public ListenableFuture commit() { + return NOOP_COMMIT_FUTURE; + } + }; + + ListenableFuture NOOP_COMMIT_FUTURE = Futures.immediateFuture(null); + + ListenableFuture NOOP_FUTURE = Futures.immediateFuture(NOOP); + + /** + * + * Commits cohort transaction. + * + * This callback is invoked by three-phase commit coordinator if associated data transaction + * finished pre-commit phase and will be commited. + * + * Implementation should make state, which were derived by implementation from associated data + * visible. + * + * @return Listenable Future which will complete once commit is finished. + */ + ListenableFuture commit(); + +} diff --git a/common/mdsal-common-api/src/main/java/org/opendaylight/mdsal/common/api/ThreePhaseCommitStep.java b/common/mdsal-common-api/src/main/java/org/opendaylight/mdsal/common/api/ThreePhaseCommitStep.java new file mode 100644 index 0000000000..6495c3cba0 --- /dev/null +++ b/common/mdsal-common-api/src/main/java/org/opendaylight/mdsal/common/api/ThreePhaseCommitStep.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2015 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.mdsal.common.api; + +import com.google.common.annotations.Beta; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import javax.annotation.Nonnull; + +/** + * Common interface for implementing three-phase commit steps. + * + * Actual steps to be implemented are: {@link PostCanCommitStep} and {@link PostPreCommitStep} which + * allows to customize pre-commit, commit and abort actions. + * + */ +@Beta +public interface ThreePhaseCommitStep { + + ListenableFuture NOOP_ABORT_FUTURE = Futures.immediateFuture(null); + + /** + * Invoked on transaction aborted. + * + * This callback is invoked by three-phase commit coordinator if associated data transaction + * will not be commited and is being aborted. + * + * Implementation MUST rollback any changes, which were introduced by implementation based on + * supplied data. + * + * @return ListenableFuture which will complete once abort is completed. + */ + @Nonnull + ListenableFuture abort(); +} diff --git a/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMDataTreeCandidate.java b/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMDataTreeCandidate.java new file mode 100644 index 0000000000..f843134638 --- /dev/null +++ b/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMDataTreeCandidate.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015 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.mdsal.dom.api; + +import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode; + +/** + * An encapsulation of a data tree modification. This candidate is ready for atomic commit to the + * data broker. It allows access to before- and after-state as it will be seen in to subsequent + * commit. This capture can be accessed for reference, but cannot be modified and the content is + * limited to nodes which were affected by the modification from which this instance originated. + */ +public interface DOMDataTreeCandidate { + + /** + * Get the candidate tree root path. This is the path of the root node relative to the root of + * InstanceIdentifier namespace. + * + * @return Relative path of the root node + */ + DOMDataTreeIdentifier getRootPath(); + + /** + * Get the candidate tree root node. + * + * @return Candidate tree root node + */ + DataTreeCandidateNode getRootNode(); +} diff --git a/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMDataTreeCommitCohort.java b/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMDataTreeCommitCohort.java new file mode 100644 index 0000000000..4c6eaff528 --- /dev/null +++ b/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMDataTreeCommitCohort.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2015 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.mdsal.dom.api; + +import com.google.common.annotations.Beta; +import com.google.common.util.concurrent.CheckedFuture; +import javax.annotation.Nonnull; +import org.opendaylight.mdsal.common.api.DataValidationFailedException; +import org.opendaylight.mdsal.common.api.PostCanCommitStep; +import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; + +/** + * + * Commit cohort participating in commit of data modification, which can validate data tree + * modifications, with option to reject supplied modification, and with callbacks describing state + * of commit. + * + *

Performance implications

+ * + * {@link DOMDataTreeCommitCohort}s are hooked up into commit of data tree changes and MAY + * negatively affect performance of data broker / store. + * + * Implementations of this interface are discouraged, unless you really need ability to veto data + * tree changes, or to provide external state change in sync with visibility of commited data. + * + * + *

Implementation requirements

+ * + *

Correctness assumptions

Implementation SHOULD use only {@link DataTreeCandidate} and + * provided {@link SchemaContext} for validation purposes. + * + * Use of any other external mutable state is discouraged, implementation MUST NOT use any + * transaction related APIs on same data broker / data store instance during invocation of + * callbacks, except ones provided as argument. Note that this MAY BE enforced by some + * implementations of {@link DOMDataBroker} or DOMDataCommitCoordinator + * + * Note that this may be enforced by some implementations of {@link DOMDataTreeCommitCohortRegistry} + * and such calls may fail. + * + *

Correct model usage

If implementation is performing YANG-model driven validation + * implementation SHOULD use provided schema context. + * + * Any other instance of {@link SchemaContext} obtained by other means, may not be valid for + * associated DataTreeCandidate and it may lead to incorrect validation or processing of provided + * data. + * + *

DataTreeCandidate assumptions

Implementation SHOULD NOT make any assumptions on + * {@link DataTreeCandidate} being successfully committed until associated + * {@link PostCanCommitStep#preCommit()} and + * {@link org.opendaylight.mdsal.common.api.PostPreCommitStep#commit()} callback was invoked. + * + * + *

Usage patterns

+ * + *

Data Tree Validator

+ * + * Validator is implementation, which only validates {@link DataTreeCandidate} and does not retain + * any state derived from edited data - does not care if {@link DataTreeCandidate} was rejected + * afterwards or transaction was cancelled. + * + * Implementation may opt-out from receiving {@code preCommit()}, {@code commit()}, {@code abort()} + * callbacks by returning {@link PostCanCommitStep#NOOP}. + * + * TODO: Provide example and describe more usage patterns + * + * @author Tony Tkacik <ttkacik@cisco.com> + * + */ +@Beta +public interface DOMDataTreeCommitCohort { + + /** + * Validates supplied data tree candidate and associates cohort-specific steps with data broker + * transaction. + * + * If {@link DataValidationFailedException} is thrown by implementation, commit of supplied data + * will be prevented, with the DataBroker transaction providing the thrown exception as the + * cause of failure. + * + * Note the implementations are expected to do validation and processing asynchronous. + * + * Implementations SHOULD do processing fast, and are discouraged SHOULD NOT block on any + * external resources. + * + * Implementation MUST NOT access any data transaction related APIs during invocation of + * callback. Note that this may be enforced by some implementations of + * {@link DOMDataTreeCommitCohortRegistry} and such calls may fail. + * + * Implementation MAY opt-out from implementing other steps by returning + * {@link PostCanCommitStep#NOOP}. Otherwise implementation MUST return instance of + * {@link PostCanCommitStep}, which will be used to invoke + * {@link org.opendaylight.mdsal.common.api.PostPreCommitStep#commit()} or + * {@link PostCanCommitStep#abort()} based on accepting data by data broker and or other commit + * cohorts. + * + * @param txId Transaction identifier. SHOULD be used only for reporting and correlation. + * Implementation MUST NOT use {@code txId} for validation. + * @param candidate Data Tree candidate to be validated and committed. + * @param ctx Schema Context to which Data Tree candidate should conform. + * @return Checked future which will successfully complete with user-supplied implementation of + * {@link PostCanCommitStep} if data are valid, or failed check future with + * {@link DataValidationFailedException} if and only if provided + * {@link DOMDataTreeCandidate} did not pass validation. Users are encouraged to use + * more specific subclasses of this exception to provide additional information about + * validation failure reason. + */ + @Nonnull + CheckedFuture canCommit(@Nonnull Object txId, + @Nonnull DOMDataTreeCandidate candidate, @Nonnull SchemaContext ctx); +} diff --git a/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMDataTreeCommitCohortRegistration.java b/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMDataTreeCommitCohortRegistration.java new file mode 100644 index 0000000000..9c70f6f41e --- /dev/null +++ b/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMDataTreeCommitCohortRegistration.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2015 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.mdsal.dom.api; + +import org.opendaylight.yangtools.concepts.ObjectRegistration; + +/** + * Registration of {@link DOMDataTreeCommitCohort}. Used to track and revoke registration with + * {@link DOMDataTreeCommitCohortRegistry}. + * + * @param Type of {@link DOMDataTreeCommitCohort} + */ +public interface DOMDataTreeCommitCohortRegistration extends ObjectRegistration { + +} diff --git a/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMDataTreeCommitCohortRegistry.java b/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMDataTreeCommitCohortRegistry.java new file mode 100644 index 0000000000..075dd9d04d --- /dev/null +++ b/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMDataTreeCommitCohortRegistry.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015 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.mdsal.dom.api; + +/** + * + * Commit Cohort registry for {@link DOMDataTreeWriteTransaction}. + * + * See {@link DOMDataTreeCommitCohort} for more details. + * + * @author Tony Tkacik <ttkacik@cisco.com> + * + */ +public interface DOMDataTreeCommitCohortRegistry extends DOMDataBrokerExtension { + + /** + * Register commit cohort which will participate in three-phase commit protocols of + * {@link DOMDataTreeWriteTransaction}in data broker associated with this instance of extension. + * + * @param path Subtree path on which commit cohort operates. + * @param cohort Commit cohort + * @return Registaration object for DOM Data Three Commit cohort. + */ + DOMDataTreeCommitCohortRegistration registerCommitCohort( + DOMDataTreeIdentifier path, T cohort); +} \ No newline at end of file -- 2.36.6