Binding v2 runtime - adapters - transactions 83/59183/3
authorJakub Toth <jakub.toth@pantheon.tech>
Thu, 15 Jun 2017 12:44:50 +0000 (14:44 +0200)
committerMartin Ciglan <martin.ciglan@pantheon.tech>
Mon, 19 Jun 2017 19:04:01 +0000 (19:04 +0000)
Change-Id: I2b9734de0662c96d8388516024034da4240a3141
Signed-off-by: Jakub Toth <jakub.toth@pantheon.tech>
(cherry picked from commit 583b80b12001a568b73f9cfd4e516ecc73d14926)

binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/data/BindingDOMDataBrokerAdapter.java [new file with mode: 0644]
binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/transaction/BindingDOMReadTransactionAdapter.java [new file with mode: 0644]
binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/transaction/BindingDOMTransactionChainAdapter.java [new file with mode: 0644]
binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/transaction/BindingDOMWriteTransactionAdapter.java [new file with mode: 0644]
binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/spi/loader/BindingDOMAdapterLoader.java

diff --git a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/data/BindingDOMDataBrokerAdapter.java b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/data/BindingDOMDataBrokerAdapter.java
new file mode 100644 (file)
index 0000000..b3006f3
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies 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.binding.javav2.dom.adapter.impl.data;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ClassToInstanceMap;
+import com.google.common.collect.ImmutableSet;
+import java.util.Collection;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import org.opendaylight.mdsal.binding.javav2.api.BindingTransactionChain;
+import org.opendaylight.mdsal.binding.javav2.api.DataBroker;
+import org.opendaylight.mdsal.binding.javav2.api.DataTreeIdentifier;
+import org.opendaylight.mdsal.binding.javav2.api.DataTreeListener;
+import org.opendaylight.mdsal.binding.javav2.api.DataTreeLoopException;
+import org.opendaylight.mdsal.binding.javav2.api.DataTreeProducer;
+import org.opendaylight.mdsal.binding.javav2.api.DataTreeService;
+import org.opendaylight.mdsal.binding.javav2.api.ReadTransaction;
+import org.opendaylight.mdsal.binding.javav2.api.WriteTransaction;
+import org.opendaylight.mdsal.binding.javav2.dom.adapter.impl.data.tree.BindingDOMDataTreeServiceAdapter;
+import org.opendaylight.mdsal.binding.javav2.dom.adapter.impl.transaction.BindingDOMReadTransactionAdapter;
+import org.opendaylight.mdsal.binding.javav2.dom.adapter.impl.transaction.BindingDOMTransactionChainAdapter;
+import org.opendaylight.mdsal.binding.javav2.dom.adapter.impl.transaction.BindingDOMWriteTransactionAdapter;
+import org.opendaylight.mdsal.binding.javav2.dom.adapter.spi.AbstractForwardedDataBroker;
+import org.opendaylight.mdsal.binding.javav2.dom.adapter.spi.builder.BindingDOMAdapterBuilder;
+import org.opendaylight.mdsal.binding.javav2.dom.adapter.spi.builder.BindingDOMAdapterBuilder.Factory;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.mdsal.common.api.TransactionChainListener;
+import org.opendaylight.mdsal.dom.api.DOMDataBroker;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeService;
+import org.opendaylight.mdsal.dom.api.DOMService;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+
+/**
+ * The DataBrokerImpl simply defers to the DOMDataBroker for all its operations. All transactions and listener
+ * registrations are wrapped by the DataBrokerImpl to allow binding aware components to use the DataBroker
+ * transparently.
+ *
+ * <p>
+ * Besides this the DataBrokerImpl and it's collaborators also cache data that is already transformed from the
+ * binding independent to binding aware format
+ *
+ */
+@Beta
+public class BindingDOMDataBrokerAdapter extends AbstractForwardedDataBroker implements DataBroker, DataTreeService {
+
+    public static final Factory<DataBroker> BUILDER_FACTORY = Builder::new;
+
+    private final DataTreeService treeService;
+
+    public BindingDOMDataBrokerAdapter(final DOMDataBroker domDataBroker, final BindingToNormalizedNodeCodec codec) {
+        super(domDataBroker, codec);
+        final DOMDataTreeService domTreeChange =
+                (DOMDataTreeService) domDataBroker.getSupportedExtensions().get(DOMDataTreeService.class);
+        if (domTreeChange != null) {
+            treeService = BindingDOMDataTreeServiceAdapter.create(domTreeChange, codec);
+        } else {
+            treeService = null;
+        }
+    }
+
+    @Override
+    public ReadTransaction newReadOnlyTransaction() {
+        return new BindingDOMReadTransactionAdapter(getDelegate().newReadOnlyTransaction(), getCodec());
+    }
+
+    @Override
+    public WriteTransaction newWriteOnlyTransaction() {
+        return new BindingDOMWriteTransactionAdapter<>(getDelegate().newWriteOnlyTransaction(), getCodec());
+    }
+
+    @Override
+    public BindingTransactionChain createTransactionChain(final TransactionChainListener listener) {
+        return new BindingDOMTransactionChainAdapter(getDelegate(), getCodec(), listener);
+    }
+
+    private static class Builder extends BindingDOMAdapterBuilder<DataBroker> {
+
+        @Override
+        public Set<? extends Class<? extends DOMService>> getRequiredDelegates() {
+            return ImmutableSet.of(DOMDataBroker.class);
+        }
+
+        @Override
+        protected DataBroker createInstance(final BindingToNormalizedNodeCodec codec,
+                final ClassToInstanceMap<DOMService> delegates) {
+            final DOMDataBroker domDataBroker = delegates.getInstance(DOMDataBroker.class);
+            return new BindingDOMDataBrokerAdapter(domDataBroker, codec);
+        }
+
+    }
+
+    @Nonnull
+    @Override
+    public <T extends DataTreeListener> ListenerRegistration<T> registerListener(@Nonnull final T listener,
+            @Nonnull final Collection<DataTreeIdentifier<?>> subtrees, final boolean allowRxMerges,
+            @Nonnull final Collection<DataTreeProducer> producers) throws DataTreeLoopException {
+        if (treeService == null) {
+            throw new UnsupportedOperationException("Underlying data broker does not expose DOMDataTreeChangeService.");
+        }
+        return treeService.registerListener(listener, subtrees, allowRxMerges, producers);
+    }
+
+    @Override
+    public DataTreeProducer createProducer(final Collection<DataTreeIdentifier<?>> subtrees) {
+        return treeService.createProducer(subtrees);
+    }
+}
diff --git a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/transaction/BindingDOMReadTransactionAdapter.java b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/transaction/BindingDOMReadTransactionAdapter.java
new file mode 100644 (file)
index 0000000..92872d9
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies 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.binding.javav2.dom.adapter.impl.transaction;
+
+import com.google.common.annotations.Beta;
+import java.util.function.BiConsumer;
+import org.opendaylight.mdsal.binding.javav2.api.ReadTransaction;
+import org.opendaylight.mdsal.binding.javav2.dom.adapter.spi.AbstractForwardedTransaction;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.mdsal.binding.javav2.spec.base.InstanceIdentifier;
+import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.mdsal.common.api.ReadFailedException;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
+
+/**
+ * Read transaction adapter.
+ */
+@Beta
+public class BindingDOMReadTransactionAdapter extends AbstractForwardedTransaction<DOMDataTreeReadTransaction>
+        implements ReadTransaction {
+
+    public BindingDOMReadTransactionAdapter(final DOMDataTreeReadTransaction delegate,
+            final BindingToNormalizedNodeCodec codec) {
+        super(delegate, codec);
+    }
+
+    @Override
+    public <T extends TreeNode> void read(final LogicalDatastoreType store, final InstanceIdentifier<T> path,
+            final BiConsumer<ReadFailedException, T> callback) {
+        doRead(getDelegate(), store, path);
+    }
+
+    @Override
+    public void close() {
+        getDelegate().close();
+    }
+}
\ No newline at end of file
diff --git a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/transaction/BindingDOMTransactionChainAdapter.java b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/transaction/BindingDOMTransactionChainAdapter.java
new file mode 100644 (file)
index 0000000..4824f18
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies 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.binding.javav2.dom.adapter.impl.transaction;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import javax.annotation.Nonnull;
+import org.opendaylight.mdsal.binding.javav2.api.BindingTransactionChain;
+import org.opendaylight.mdsal.binding.javav2.api.ReadTransaction;
+import org.opendaylight.mdsal.binding.javav2.api.WriteTransaction;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.mdsal.common.api.AsyncTransaction;
+import org.opendaylight.mdsal.common.api.TransactionChain;
+import org.opendaylight.mdsal.common.api.TransactionChainListener;
+import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
+import org.opendaylight.mdsal.dom.api.DOMDataBroker;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
+import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
+import org.opendaylight.yangtools.concepts.Delegator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Transaction chain adapter.
+ */
+@Beta
+public final class BindingDOMTransactionChainAdapter
+        implements BindingTransactionChain, Delegator<DOMTransactionChain> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(BindingDOMTransactionChainAdapter.class);
+
+    private final DOMTransactionChain delegate;
+    private final BindingToNormalizedNodeCodec codec;
+    private final TransactionChainListener bindingListener;
+
+    public BindingDOMTransactionChainAdapter(final DOMDataBroker chainFactory, final BindingToNormalizedNodeCodec codec,
+            final TransactionChainListener listener) {
+        Preconditions.checkNotNull(chainFactory, "DOM Transaction chain factory must not be null");
+        this.bindingListener = listener;
+        this.delegate = chainFactory.createTransactionChain(new DelegateChainListener());
+        this.codec = codec;
+    }
+
+    @Override
+    public DOMTransactionChain getDelegate() {
+        return delegate;
+    }
+
+    @Override
+    public ReadTransaction newReadOnlyTransaction() {
+        final DOMDataTreeReadTransaction delegateTx = delegate.newReadOnlyTransaction();
+        return new BindingDOMReadTransactionAdapter(delegateTx, codec);
+    }
+
+    @Override
+    public WriteTransaction newWriteOnlyTransaction() {
+        final DOMDataTreeWriteTransaction delegateTx = delegate.newWriteOnlyTransaction();
+        return new BindingDOMWriteTransactionAdapter<DOMDataTreeWriteTransaction>(delegateTx, codec) {
+
+            @Override
+            public CheckedFuture<Void, TransactionCommitFailedException> submit() {
+                return listenForFailure(this, super.submit());
+            }
+
+        };
+    }
+
+    private CheckedFuture<Void, TransactionCommitFailedException> listenForFailure(final WriteTransaction tx,
+            final CheckedFuture<Void, TransactionCommitFailedException> future) {
+        Futures.addCallback(future, new FutureCallback<Void>() {
+            @Override
+            public void onFailure(@Nonnull final Throwable throwable) {
+                failTransactionChain(tx, throwable);
+            }
+
+            @Override
+            public void onSuccess(final Void result) {
+                // Intentionally NOOP
+            }
+        });
+
+        return future;
+    }
+
+    private void failTransactionChain(final WriteTransaction tx, final Throwable throwable) {
+        /*
+         * We assume correct state change for underlying transaction
+         *
+         * chain, so we are not changing any of our internal state to mark that we failed.
+         */
+        this.bindingListener.onTransactionChainFailed(this, tx, throwable);
+    }
+
+    @Override
+    public void close() {
+        delegate.close();
+    }
+
+    private final class DelegateChainListener implements TransactionChainListener {
+
+        @Override
+        public void onTransactionChainFailed(final TransactionChain<?, ?> chain,
+                final AsyncTransaction<?, ?> transaction, final Throwable cause) {
+            Preconditions.checkState(delegate.equals(chain),
+                    "Illegal state - listener for %s was invoked for incorrect chain %s.", delegate, chain);
+            /*
+             * Intentionally NOOP, callback for failure, since we are also listening on each transaction
+             * future for failure, in order to have reference to Binding Transaction (which was seen by client
+             * of this transaction chain), instead of DOM transaction which is known only to this chain,
+             * binding transaction implementation and underlying transaction chain.
+             *
+             */
+            LOG.debug("Transaction chain {} failed. Failed DOM Transaction {}", this, transaction, cause);
+        }
+
+        @Override
+        public void onTransactionChainSuccessful(final TransactionChain<?, ?> chain) {
+            Preconditions.checkState(delegate.equals(chain),
+                    "Illegal state - listener for %s was invoked for incorrect chain %s.", delegate, chain);
+            bindingListener.onTransactionChainSuccessful(BindingDOMTransactionChainAdapter.this);
+        }
+    }
+}
diff --git a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/transaction/BindingDOMWriteTransactionAdapter.java b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/transaction/BindingDOMWriteTransactionAdapter.java
new file mode 100644 (file)
index 0000000..6c1c5cf
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies 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.binding.javav2.dom.adapter.impl.transaction;
+
+import com.google.common.annotations.Beta;
+import com.google.common.util.concurrent.CheckedFuture;
+import org.opendaylight.mdsal.binding.javav2.api.WriteTransaction;
+import org.opendaylight.mdsal.binding.javav2.dom.adapter.spi.AbstractWriteTransaction;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.mdsal.binding.javav2.spec.base.InstanceIdentifier;
+import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
+
+/**
+ * Write transaction adapter.
+ *
+ * @param <T>
+ *            - {@link DOMDataTreeWriteTransaction} type
+ */
+@Beta
+public class BindingDOMWriteTransactionAdapter<T extends DOMDataTreeWriteTransaction>
+        extends AbstractWriteTransaction<T>
+        implements WriteTransaction {
+
+    public BindingDOMWriteTransactionAdapter(final T delegateTx, final BindingToNormalizedNodeCodec codec) {
+        super(delegateTx, codec);
+    }
+
+    @Override
+    public <U extends TreeNode> void put(final LogicalDatastoreType store, final InstanceIdentifier<U> path,
+            final U data) {
+        put(store, path, data, false);
+    }
+
+    @Override
+    public <U extends TreeNode> void merge(final LogicalDatastoreType store, final InstanceIdentifier<U> path,
+            final U data) {
+        merge(store, path, data, false);
+    }
+
+    @Override
+    public void delete(final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
+        doDelete(store, path);
+    }
+
+    @Override
+    public CheckedFuture<Void, TransactionCommitFailedException> submit() {
+        return doSubmit();
+    }
+
+    @Override
+    public boolean cancel() {
+        return doCancel();
+    }
+}
\ No newline at end of file
index fd547cf47e4177af2a84128de8675288ac03d168..2d686c2ef029e033c307759c226492861ad319a7 100644 (file)
@@ -13,6 +13,8 @@ import com.google.common.collect.ImmutableMap;
 import java.util.Map;
 import javax.annotation.Nonnull;
 import org.opendaylight.mdsal.binding.javav2.api.BindingService;
+import org.opendaylight.mdsal.binding.javav2.api.DataBroker;
+import org.opendaylight.mdsal.binding.javav2.dom.adapter.impl.data.BindingDOMDataBrokerAdapter;
 import org.opendaylight.mdsal.binding.javav2.dom.adapter.spi.builder.AdapterBuilder;
 import org.opendaylight.mdsal.binding.javav2.dom.adapter.spi.builder.BindingDOMAdapterBuilder;
 import org.opendaylight.mdsal.binding.javav2.dom.adapter.spi.builder.BindingDOMAdapterBuilder.Factory;
@@ -28,7 +30,9 @@ public abstract class BindingDOMAdapterLoader extends AdapterLoader<BindingServi
     // TODO add all factory of services
     @SuppressWarnings("checkstyle:GenericWhitespace")
     private static final Map<Class<?>, BindingDOMAdapterBuilder.Factory<?>> FACTORIES =
-            ImmutableMap.<Class<?>, BindingDOMAdapterBuilder.Factory<?>> builder().build();
+            ImmutableMap.<Class<?>, BindingDOMAdapterBuilder.Factory<?>> builder()
+                    .put(DataBroker.class, BindingDOMDataBrokerAdapter.BUILDER_FACTORY)
+                    .build();
 
     private final BindingToNormalizedNodeCodec codec;