From bd0e40b3221325dbc96b17fef191df2245954f44 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Sun, 25 Oct 2020 18:17:42 +0100 Subject: [PATCH] Add DOMDataTreeQueryOperations DOMDataTreeQueryOperations exposes the ability to execute queries on the backing datastore, much like one would execute a read. mdsal-binding-dom-adapter is taught to recognize the interface and use it to offload execution deeper. It still falls back to its evaluation should the backing store not support this. DOMStoreReadTransaction gained the ability to value expressions, using a default implementation based om DOMQueryEvaluator. Based on that capability, mdsal-dom-broker's transactions are retrofitted to always provide evaluation locally. JIRA: MDSAL-607 Change-Id: Ia20acf59870f47c8a84914e239dee82e2a56c1bb Signed-off-by: Robert Varga --- .../adapter/AbstractForwardedTransaction.java | 26 +++++++++--- .../dom/api/DOMDataTreeQueryOperations.java | 40 +++++++++++++++++++ .../api/DOMDataTreeQueryReadTransaction.java | 18 +++++++++ .../DOMDataTreeQueryReadWriteTransaction.java | 19 +++++++++ .../DOMForwardedReadOnlyTransaction.java | 15 +++++-- .../DOMForwardedReadWriteTransaction.java | 11 ++++- .../spi/store/DOMStoreReadTransaction.java | 32 +++++++++++++++ 7 files changed, 149 insertions(+), 12 deletions(-) create mode 100644 dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMDataTreeQueryOperations.java create mode 100644 dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMDataTreeQueryReadTransaction.java create mode 100644 dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMDataTreeQueryReadWriteTransaction.java diff --git a/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/AbstractForwardedTransaction.java b/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/AbstractForwardedTransaction.java index b7aa7da8cc..7bcd2823da 100644 --- a/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/AbstractForwardedTransaction.java +++ b/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/AbstractForwardedTransaction.java @@ -19,9 +19,11 @@ import org.opendaylight.mdsal.binding.api.query.QueryExpression; import org.opendaylight.mdsal.binding.api.query.QueryResult; import org.opendaylight.mdsal.binding.dom.adapter.query.DefaultQuery; import org.opendaylight.mdsal.common.api.LogicalDatastoreType; +import org.opendaylight.mdsal.dom.api.DOMDataTreeQueryOperations; import org.opendaylight.mdsal.dom.api.DOMDataTreeReadOperations; import org.opendaylight.mdsal.dom.api.DOMDataTreeTransaction; import org.opendaylight.mdsal.dom.api.query.DOMQuery; +import org.opendaylight.mdsal.dom.api.query.DOMQueryResult; import org.opendaylight.mdsal.dom.spi.query.DOMQueryEvaluator; import org.opendaylight.mdsal.dom.spi.query.EagerDOMQueryResult; import org.opendaylight.yangtools.concepts.Delegator; @@ -29,9 +31,12 @@ import org.opendaylight.yangtools.concepts.Identifiable; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; abstract class AbstractForwardedTransaction implements Delegator, Identifiable { + private static final Logger LOG = LoggerFactory.getLogger(AbstractForwardedTransaction.class); private final @NonNull AdapterContext adapterContext; private final @NonNull T delegate; @@ -79,17 +84,26 @@ abstract class AbstractForwardedTransaction im return readOps.exists(store, adapterContext.currentSerializer().toYangInstanceIdentifier(path)); } - protected final @NonNull FluentFuture> doExecute( + protected final @NonNull FluentFuture> doExecute( final DOMDataTreeReadOperations readOps, final @NonNull LogicalDatastoreType store, final @NonNull QueryExpression query) { checkArgument(query instanceof DefaultQuery, "Unsupported query type %s", query); final DefaultQuery defaultQuery = (DefaultQuery) query; - final DOMQuery domQuery = defaultQuery.asDOMQuery(); + final FluentFuture domResult = readOps instanceof DOMDataTreeQueryOperations + ? ((DOMDataTreeQueryOperations) readOps).execute(store, defaultQuery.asDOMQuery()) + : fallbackExecute(readOps, store, defaultQuery.asDOMQuery()); + + return domResult.transform(defaultQuery::toQueryResult, MoreExecutors.directExecutor()); + } + + private static FluentFuture fallbackExecute(final @NonNull DOMDataTreeReadOperations readOps, + final @NonNull LogicalDatastoreType store, final @NonNull DOMQuery domQuery) { + LOG.trace("Fallback evaluation of {} on {}", domQuery, readOps); return readOps.read(store, domQuery.getRoot()) - .transform(node -> node.map( - data -> DOMQueryEvaluator.evaluateOn(domQuery, data)).orElse(EagerDOMQueryResult.of()), - MoreExecutors.directExecutor()) - .transform(defaultQuery::toQueryResult, MoreExecutors.directExecutor()); + .transform( + node -> node.map(data -> DOMQueryEvaluator.evaluateOn(domQuery, data)).orElse(EagerDOMQueryResult.of()), + // TODO: execute on a dedicated thread pool + MoreExecutors.directExecutor()); } } diff --git a/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMDataTreeQueryOperations.java b/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMDataTreeQueryOperations.java new file mode 100644 index 0000000000..0cf2199e85 --- /dev/null +++ b/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMDataTreeQueryOperations.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2020 PANTHEON.tech, s.r.o. 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.FluentFuture; +import org.opendaylight.mdsal.common.api.LogicalDatastoreType; +import org.opendaylight.mdsal.common.api.ReadFailedException; +import org.opendaylight.mdsal.dom.api.query.DOMQuery; +import org.opendaylight.mdsal.dom.api.query.DOMQueryResult; + +/** + * Query-like operations supported by {@link DOMDataTreeReadTransaction} and {@link DOMDataTreeReadWriteTransaction}. + * This interface defines the operations without a tie-in with lifecycle management. + */ +@Beta +public interface DOMDataTreeQueryOperations { + /** + * Executes a query on the provided logical data store. + * + * @param store Logical data store from which read should occur. + * @param query DOMQuery to execute + * @return a FluentFuture containing the result of the query. The Future blocks until the operation is complete. + * Once complete: + *
    + *
  • The Future returns the result of the query
  • + *
  • If the query execution fails, the Future will fail with a {@link ReadFailedException} or + * an exception derived from ReadFailedException. + *
  • + *
+ * @throws NullPointerException if any of the arguments is null + * @throws IllegalArgumentException if the query is not supported + */ + FluentFuture execute(LogicalDatastoreType store, DOMQuery query); +} diff --git a/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMDataTreeQueryReadTransaction.java b/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMDataTreeQueryReadTransaction.java new file mode 100644 index 0000000000..d3627144d3 --- /dev/null +++ b/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMDataTreeQueryReadTransaction.java @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2020 PANTHEON.tech, s.r.o. 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; + +/** + * A {@link DOMDataTreeReadTransaction} which can also perform {@link DOMDataTreeQueryOperations}. + */ +@Beta +public interface DOMDataTreeQueryReadTransaction extends DOMDataTreeReadTransaction, DOMDataTreeQueryOperations { + +} diff --git a/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMDataTreeQueryReadWriteTransaction.java b/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMDataTreeQueryReadWriteTransaction.java new file mode 100644 index 0000000000..8d41e1924d --- /dev/null +++ b/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMDataTreeQueryReadWriteTransaction.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2020 PANTHEON.tech, s.r.o. 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; + +/** + * A {@link DOMDataTreeReadWriteTransaction} which can also perform {@link DOMDataTreeQueryOperations}. + */ +@Beta +public interface DOMDataTreeQueryReadWriteTransaction + extends DOMDataTreeReadWriteTransaction, DOMDataTreeQueryOperations { + +} diff --git a/dom/mdsal-dom-broker/src/main/java/org/opendaylight/mdsal/dom/broker/DOMForwardedReadOnlyTransaction.java b/dom/mdsal-dom-broker/src/main/java/org/opendaylight/mdsal/dom/broker/DOMForwardedReadOnlyTransaction.java index a4cbd5d3d1..76ef4ba881 100644 --- a/dom/mdsal-dom-broker/src/main/java/org/opendaylight/mdsal/dom/broker/DOMForwardedReadOnlyTransaction.java +++ b/dom/mdsal-dom-broker/src/main/java/org/opendaylight/mdsal/dom/broker/DOMForwardedReadOnlyTransaction.java @@ -11,7 +11,9 @@ import com.google.common.util.concurrent.FluentFuture; import java.util.Map; import java.util.Optional; import org.opendaylight.mdsal.common.api.LogicalDatastoreType; -import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction; +import org.opendaylight.mdsal.dom.api.DOMDataTreeQueryReadTransaction; +import org.opendaylight.mdsal.dom.api.query.DOMQuery; +import org.opendaylight.mdsal.dom.api.query.DOMQueryResult; import org.opendaylight.mdsal.dom.spi.store.DOMStoreReadTransaction; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; @@ -22,9 +24,9 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; * {@link LogicalDatastoreType} type parameter in * {@link #read(LogicalDatastoreType, YangInstanceIdentifier)}. */ -class DOMForwardedReadOnlyTransaction extends - AbstractDOMForwardedCompositeTransaction implements - DOMDataTreeReadTransaction { +class DOMForwardedReadOnlyTransaction + extends AbstractDOMForwardedCompositeTransaction + implements DOMDataTreeQueryReadTransaction { protected DOMForwardedReadOnlyTransaction(final Object identifier, final Map backingTxs) { @@ -42,6 +44,11 @@ class DOMForwardedReadOnlyTransaction extends return getSubtransaction(store).exists(path); } + @Override + public FluentFuture execute(final LogicalDatastoreType store, final DOMQuery query) { + return getSubtransaction(store).execute(query); + } + @Override public void close() { closeSubtransactions(); diff --git a/dom/mdsal-dom-broker/src/main/java/org/opendaylight/mdsal/dom/broker/DOMForwardedReadWriteTransaction.java b/dom/mdsal-dom-broker/src/main/java/org/opendaylight/mdsal/dom/broker/DOMForwardedReadWriteTransaction.java index d9205baef4..e1978dfd58 100644 --- a/dom/mdsal-dom-broker/src/main/java/org/opendaylight/mdsal/dom/broker/DOMForwardedReadWriteTransaction.java +++ b/dom/mdsal-dom-broker/src/main/java/org/opendaylight/mdsal/dom/broker/DOMForwardedReadWriteTransaction.java @@ -11,7 +11,9 @@ import com.google.common.util.concurrent.FluentFuture; import java.util.Map; import java.util.Optional; import org.opendaylight.mdsal.common.api.LogicalDatastoreType; -import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction; +import org.opendaylight.mdsal.dom.api.DOMDataTreeQueryReadWriteTransaction; +import org.opendaylight.mdsal.dom.api.query.DOMQuery; +import org.opendaylight.mdsal.dom.api.query.DOMQueryResult; import org.opendaylight.mdsal.dom.spi.store.DOMStoreReadWriteTransaction; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; @@ -36,7 +38,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; * underlying transactions. */ final class DOMForwardedReadWriteTransaction extends DOMForwardedWriteTransaction - implements DOMDataTreeReadWriteTransaction { + implements DOMDataTreeQueryReadWriteTransaction { DOMForwardedReadWriteTransaction(final Object identifier, final Map backingTxs, @@ -54,4 +56,9 @@ final class DOMForwardedReadWriteTransaction extends DOMForwardedWriteTransactio public FluentFuture exists(final LogicalDatastoreType store, final YangInstanceIdentifier path) { return getSubtransaction(store).exists(path); } + + @Override + public FluentFuture execute(final LogicalDatastoreType store, final DOMQuery query) { + return getSubtransaction(store).execute(query); + } } diff --git a/dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/store/DOMStoreReadTransaction.java b/dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/store/DOMStoreReadTransaction.java index 0b22cef46e..b5e41e3f74 100644 --- a/dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/store/DOMStoreReadTransaction.java +++ b/dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/store/DOMStoreReadTransaction.java @@ -8,8 +8,14 @@ package org.opendaylight.mdsal.dom.spi.store; import com.google.common.util.concurrent.FluentFuture; +import com.google.common.util.concurrent.MoreExecutors; import java.util.Optional; +import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.mdsal.common.api.ReadFailedException; +import org.opendaylight.mdsal.dom.api.query.DOMQuery; +import org.opendaylight.mdsal.dom.api.query.DOMQueryResult; +import org.opendaylight.mdsal.dom.spi.query.DOMQueryEvaluator; +import org.opendaylight.mdsal.dom.spi.query.EagerDOMQueryResult; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; @@ -55,4 +61,30 @@ public interface DOMStoreReadTransaction extends DOMStoreTransaction { * */ FluentFuture exists(YangInstanceIdentifier path); + + /** + * Executes a query on the provided logical data store. + * + *

+ * Default operation invokes {@code read(query.getRoot())} and then executes the result with + * {@link DOMQueryEvaluator}. Implementations are encouraged to provide a more efficient implementation as + * appropriate. + * + * @param query DOMQuery to execute + * @return a FluentFuture containing the result of the query. The Future blocks until the operation is complete. + * Once complete: + *

    + *
  • The Future returns the result of the query
  • + *
  • If the query execution fails, the Future will fail with a {@link ReadFailedException} or + * an exception derived from ReadFailedException. + *
  • + *
+ * @throws NullPointerException if any of the arguments is null + * @throws IllegalArgumentException if the query is not supported + */ + default @NonNull FluentFuture execute(final DOMQuery query) { + return read(query.getRoot()).transform( + node -> node.map(data -> DOMQueryEvaluator.evaluateOn(query, data)).orElse(EagerDOMQueryResult.of()), + MoreExecutors.directExecutor()); + } } -- 2.36.6