2 * Copyright © 2018 Red Hat, Inc. and others.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.mdsal.binding.util;
10 import static java.util.Objects.requireNonNull;
12 import com.google.common.util.concurrent.FluentFuture;
13 import com.google.common.util.concurrent.MoreExecutors;
14 import edu.umd.cs.findbugs.annotations.CheckReturnValue;
15 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
16 import java.util.function.BiFunction;
17 import java.util.function.Supplier;
18 import org.opendaylight.mdsal.binding.api.ReadTransaction;
19 import org.opendaylight.mdsal.binding.api.TransactionFactory;
20 import org.opendaylight.mdsal.binding.api.WriteTransaction;
21 import org.opendaylight.yangtools.util.concurrent.FluentFutures;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
26 * Basic implementation of a {@link ManagedTransactionFactory}.
28 class ManagedTransactionFactoryImpl<T extends TransactionFactory> implements ManagedTransactionFactory {
29 private static final Logger LOG = LoggerFactory.getLogger(ManagedTransactionFactoryImpl.class);
31 private final T transactionFactory;
33 ManagedTransactionFactoryImpl(final T transactionFactory) {
34 this.transactionFactory = requireNonNull(transactionFactory, "transactionFactory must not be null");
38 @SuppressFBWarnings("RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE")
39 public <D extends Datastore, E extends Exception, R> R applyInterruptiblyWithNewReadOnlyTransactionAndClose(
40 final D datastore, final InterruptibleCheckedFunction<TypedReadTransaction<D>, R, E> txFunction)
41 throws E, InterruptedException {
42 try (ReadTransaction realTx = transactionFactory.newReadOnlyTransaction()) {
43 TypedReadTransaction<D> wrappedTx = new TypedReadTransactionImpl<>(datastore, realTx);
44 return txFunction.apply(wrappedTx);
49 @SuppressFBWarnings("RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE")
50 public <D extends Datastore, E extends Exception, R> R applyWithNewReadOnlyTransactionAndClose(final D datastore,
51 final CheckedFunction<TypedReadTransaction<D>, R, E> txFunction) throws E {
52 try (ReadTransaction realTx = transactionFactory.newReadOnlyTransaction()) {
53 TypedReadTransaction<D> wrappedTx = new TypedReadTransactionImpl<>(datastore, realTx);
54 return txFunction.apply(wrappedTx);
60 public <D extends Datastore, E extends Exception, R> FluentFuture<R> applyWithNewReadWriteTransactionAndSubmit(
61 final D datastore, final InterruptibleCheckedFunction<TypedReadWriteTransaction<D>, R, E> txFunction) {
62 return applyWithNewTransactionAndSubmit(datastore, transactionFactory::newReadWriteTransaction,
63 TypedReadWriteTransactionImpl::new, txFunction, (realTx, wrappedTx) -> realTx.commit());
67 @SuppressFBWarnings("RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE")
68 public <D extends Datastore, E extends Exception> void callInterruptiblyWithNewReadOnlyTransactionAndClose(
69 final D datastore, final InterruptibleCheckedConsumer<TypedReadTransaction<D>, E> txConsumer)
70 throws E, InterruptedException {
71 try (ReadTransaction realTx = transactionFactory.newReadOnlyTransaction()) {
72 TypedReadTransaction<D> wrappedTx = new TypedReadTransactionImpl<>(datastore, realTx);
73 txConsumer.accept(wrappedTx);
78 @SuppressFBWarnings("RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE")
79 public <D extends Datastore, E extends Exception> void callWithNewReadOnlyTransactionAndClose(final D datastore,
80 final CheckedConsumer<TypedReadTransaction<D>, E> txConsumer) throws E {
81 try (ReadTransaction realTx = transactionFactory.newReadOnlyTransaction()) {
82 TypedReadTransaction<D> wrappedTx = new TypedReadTransactionImpl<>(datastore, realTx);
83 txConsumer.accept(wrappedTx);
89 public <D extends Datastore, E extends Exception>
90 FluentFuture<? extends Object> callWithNewReadWriteTransactionAndSubmit(final D datastore,
91 final InterruptibleCheckedConsumer<TypedReadWriteTransaction<D>, E> txConsumer) {
92 return callWithNewTransactionAndSubmit(datastore, transactionFactory::newReadWriteTransaction,
93 TypedReadWriteTransactionImpl::new, txConsumer, (realTx, wrappedTx) -> realTx.commit());
98 public <D extends Datastore, E extends Exception>
99 FluentFuture<? extends Object> callWithNewWriteOnlyTransactionAndSubmit(final D datastore,
100 final InterruptibleCheckedConsumer<TypedWriteTransaction<D>, E> txConsumer) {
101 return callWithNewTransactionAndSubmit(datastore, transactionFactory::newWriteOnlyTransaction,
102 TypedWriteTransactionImpl::new, txConsumer, (realTx, wrappedTx) -> realTx.commit());
106 protected <D extends Datastore, X extends WriteTransaction, W, E extends Exception>
107 FluentFuture<? extends Object> callWithNewTransactionAndSubmit(final D datastore, final Supplier<X> txSupplier,
108 final BiFunction<D, X, W> txWrapper, final InterruptibleCheckedConsumer<W, E> txConsumer,
109 final BiFunction<X, W, FluentFuture<?>> txSubmitter) {
110 return applyWithNewTransactionAndSubmit(datastore, txSupplier, txWrapper, tx -> {
111 txConsumer.accept(tx);
117 @SuppressWarnings("checkstyle:IllegalCatch")
118 protected <D extends Datastore, X extends WriteTransaction, W, R, E extends Exception>
119 FluentFuture<R> applyWithNewTransactionAndSubmit(final D datastore, final Supplier<X> txSupplier,
120 final BiFunction<D, X, W> txWrapper, final InterruptibleCheckedFunction<W, R, E> txFunction,
121 final BiFunction<X, W, FluentFuture<?>> txSubmitter) {
122 X realTx = txSupplier.get();
123 W wrappedTx = txWrapper.apply(datastore, realTx);
126 // We must store the result before submitting the transaction; if we inline the next line in the
127 // transform lambda, that's not guaranteed
128 result = txFunction.apply(wrappedTx);
129 } catch (Exception e) {
130 // catch Exception for both the <E extends Exception> thrown by accept() as well as any RuntimeException
131 if (!realTx.cancel()) {
132 LOG.error("Transaction.cancel() returned false - this should never happen (here)");
134 return FluentFutures.immediateFailedFluentFuture(e);
136 return txSubmitter.apply(realTx, wrappedTx).transform(v -> result, MoreExecutors.directExecutor());
139 protected T getTransactionFactory() {
140 return transactionFactory;