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 Class<D> datastoreType, final InterruptibleCheckedFunction<TypedReadTransaction<D>, R, E> txFunction)
41 throws E, InterruptedException {
42 try (ReadTransaction realTx = transactionFactory.newReadOnlyTransaction()) {
43 TypedReadTransaction<D>
44 wrappedTx = new TypedReadTransactionImpl<>(datastoreType, realTx);
45 return txFunction.apply(wrappedTx);
50 @SuppressFBWarnings("RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE")
51 public <D extends Datastore, E extends Exception, R> R applyWithNewReadOnlyTransactionAndClose(
52 final Class<D> datastoreType, final CheckedFunction<TypedReadTransaction<D>, R, E> txFunction) throws E {
53 try (ReadTransaction realTx = transactionFactory.newReadOnlyTransaction()) {
54 TypedReadTransaction<D>
55 wrappedTx = new TypedReadTransactionImpl<>(datastoreType, realTx);
56 return txFunction.apply(wrappedTx);
62 public <D extends Datastore, E extends Exception, R>
63 FluentFuture<R> applyWithNewReadWriteTransactionAndSubmit(final Class<D> datastoreType,
64 final InterruptibleCheckedFunction<TypedReadWriteTransaction<D>, R, E> txFunction) {
65 return applyWithNewTransactionAndSubmit(datastoreType, transactionFactory::newReadWriteTransaction,
66 TypedReadWriteTransactionImpl::new, txFunction, (realTx, wrappedTx) -> realTx.commit());
70 @SuppressFBWarnings("RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE")
71 public <D extends Datastore, E extends Exception> void callInterruptiblyWithNewReadOnlyTransactionAndClose(
72 final Class<D> datastoreType, final InterruptibleCheckedConsumer<TypedReadTransaction<D>, E> txConsumer)
73 throws E, InterruptedException {
74 try (ReadTransaction realTx = transactionFactory.newReadOnlyTransaction()) {
75 TypedReadTransaction<D> wrappedTx = new TypedReadTransactionImpl<>(datastoreType, realTx);
76 txConsumer.accept(wrappedTx);
81 @SuppressFBWarnings("RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE")
82 public <D extends Datastore, E extends Exception> void callWithNewReadOnlyTransactionAndClose(
83 final Class<D> datastoreType, final CheckedConsumer<TypedReadTransaction<D>, E> txConsumer) throws E {
84 try (ReadTransaction realTx = transactionFactory.newReadOnlyTransaction()) {
85 TypedReadTransaction<D> wrappedTx = new TypedReadTransactionImpl<>(datastoreType, realTx);
86 txConsumer.accept(wrappedTx);
92 public <D extends Datastore, E extends Exception>
93 FluentFuture<? extends Object> callWithNewReadWriteTransactionAndSubmit(final Class<D> datastoreType,
94 final InterruptibleCheckedConsumer<TypedReadWriteTransaction<D>, E> txConsumer) {
95 return callWithNewTransactionAndSubmit(datastoreType, transactionFactory::newReadWriteTransaction,
96 TypedReadWriteTransactionImpl::new, txConsumer, (realTx, wrappedTx) -> realTx.commit());
101 public <D extends Datastore, E extends Exception> FluentFuture<? extends Object>
102 callWithNewWriteOnlyTransactionAndSubmit(final Class<D> datastoreType,
103 final InterruptibleCheckedConsumer<TypedWriteTransaction<D>, E> txConsumer) {
104 return callWithNewTransactionAndSubmit(datastoreType, transactionFactory::newWriteOnlyTransaction,
105 TypedWriteTransactionImpl::new, txConsumer, (realTx, wrappedTx) -> realTx.commit());
109 protected <D extends Datastore, X extends WriteTransaction, W, E extends Exception> FluentFuture<? extends Object>
110 callWithNewTransactionAndSubmit(
111 final Class<D> datastoreType, final Supplier<X> txSupplier, final BiFunction<Class<D>, X, W> txWrapper,
112 final InterruptibleCheckedConsumer<W, E> txConsumer, final BiFunction<X, W, FluentFuture<?>> txSubmitter) {
113 return applyWithNewTransactionAndSubmit(datastoreType, txSupplier, txWrapper, tx -> {
114 txConsumer.accept(tx);
120 @SuppressWarnings("checkstyle:IllegalCatch")
121 protected <D extends Datastore, X extends WriteTransaction, W, R, E extends Exception> FluentFuture<R>
122 applyWithNewTransactionAndSubmit(
123 final Class<D> datastoreType, final Supplier<X> txSupplier, final BiFunction<Class<D>, X, W> txWrapper,
124 final InterruptibleCheckedFunction<W, R, E> txFunction,
125 final BiFunction<X, W, FluentFuture<?>> txSubmitter) {
126 X realTx = txSupplier.get();
127 W wrappedTx = txWrapper.apply(datastoreType, realTx);
130 // We must store the result before submitting the transaction; if we inline the next line in the
131 // transform lambda, that's not guaranteed
132 result = txFunction.apply(wrappedTx);
133 } catch (Exception e) {
134 // catch Exception for both the <E extends Exception> thrown by accept() as well as any RuntimeException
135 if (!realTx.cancel()) {
136 LOG.error("Transaction.cancel() returned false - this should never happen (here)");
138 return FluentFutures.immediateFailedFluentFuture(e);
140 return txSubmitter.apply(realTx, wrappedTx).transform(v -> result, MoreExecutors.directExecutor());
143 protected T getTransactionFactory() {
144 return transactionFactory;