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 java.util.function.BiFunction;
15 import java.util.function.Supplier;
16 import javax.annotation.CheckReturnValue;
17 import org.opendaylight.mdsal.binding.api.ReadTransaction;
18 import org.opendaylight.mdsal.binding.api.TransactionFactory;
19 import org.opendaylight.mdsal.binding.api.WriteTransaction;
20 import org.opendaylight.yangtools.util.concurrent.FluentFutures;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
25 * Basic implementation of a {@link ManagedTransactionFactory}.
27 class ManagedTransactionFactoryImpl<T extends TransactionFactory> implements ManagedTransactionFactory {
28 private static final Logger LOG = LoggerFactory.getLogger(ManagedTransactionFactoryImpl.class);
30 private final T transactionFactory;
32 ManagedTransactionFactoryImpl(T transactionFactory) {
33 this.transactionFactory = requireNonNull(transactionFactory, "transactionFactory must not be null");
37 public <D extends Datastore, E extends Exception, R> R applyInterruptiblyWithNewReadOnlyTransactionAndClose(
38 Class<D> datastoreType, InterruptibleCheckedFunction<TypedReadTransaction<D>, R, E> txFunction)
39 throws E, InterruptedException {
40 try (ReadTransaction realTx = transactionFactory.newReadOnlyTransaction()) {
41 TypedReadTransaction<D>
42 wrappedTx = new TypedReadTransactionImpl<>(datastoreType, realTx);
43 return txFunction.apply(wrappedTx);
48 public <D extends Datastore, E extends Exception, R> R applyWithNewReadOnlyTransactionAndClose(
49 Class<D> datastoreType, CheckedFunction<TypedReadTransaction<D>, R, E> txFunction) throws E {
50 try (ReadTransaction realTx = transactionFactory.newReadOnlyTransaction()) {
51 TypedReadTransaction<D>
52 wrappedTx = new TypedReadTransactionImpl<>(datastoreType, realTx);
53 return txFunction.apply(wrappedTx);
59 public <D extends Datastore, E extends Exception, R>
60 FluentFuture<R> applyWithNewReadWriteTransactionAndSubmit(Class<D> datastoreType,
61 InterruptibleCheckedFunction<TypedReadWriteTransaction<D>, R, E> txFunction) {
62 return applyWithNewTransactionAndSubmit(datastoreType, transactionFactory::newReadWriteTransaction,
63 TypedReadWriteTransactionImpl::new, txFunction, (realTx, wrappedTx) -> realTx.commit());
67 public <D extends Datastore, E extends Exception> void callInterruptiblyWithNewReadOnlyTransactionAndClose(
68 Class<D> datastoreType, InterruptibleCheckedConsumer<TypedReadTransaction<D>, E> txConsumer)
69 throws E, InterruptedException {
70 try (ReadTransaction realTx = transactionFactory.newReadOnlyTransaction()) {
71 TypedReadTransaction<D> wrappedTx = new TypedReadTransactionImpl<>(datastoreType, realTx);
72 txConsumer.accept(wrappedTx);
77 public <D extends Datastore, E extends Exception> void callWithNewReadOnlyTransactionAndClose(
78 Class<D> datastoreType, CheckedConsumer<TypedReadTransaction<D>, E> txConsumer) throws E {
79 try (ReadTransaction realTx = transactionFactory.newReadOnlyTransaction()) {
80 TypedReadTransaction<D> wrappedTx = new TypedReadTransactionImpl<>(datastoreType, realTx);
81 txConsumer.accept(wrappedTx);
87 public <D extends Datastore, E extends Exception>
88 FluentFuture<? extends Object> callWithNewReadWriteTransactionAndSubmit(Class<D> datastoreType,
89 InterruptibleCheckedConsumer<TypedReadWriteTransaction<D>, E> txConsumer) {
90 return callWithNewTransactionAndSubmit(datastoreType, transactionFactory::newReadWriteTransaction,
91 TypedReadWriteTransactionImpl::new, txConsumer, (realTx, wrappedTx) -> realTx.commit());
96 public <D extends Datastore, E extends Exception> FluentFuture<? extends Object> callWithNewWriteOnlyTransactionAndSubmit(
97 Class<D> datastoreType, InterruptibleCheckedConsumer<TypedWriteTransaction<D>, E> txConsumer) {
98 return callWithNewTransactionAndSubmit(datastoreType, transactionFactory::newWriteOnlyTransaction,
99 TypedWriteTransactionImpl::new, txConsumer, (realTx, wrappedTx) -> realTx.commit());
103 protected <D extends Datastore, T extends WriteTransaction, W, E extends Exception> FluentFuture<? extends Object>
104 callWithNewTransactionAndSubmit(
105 Class<D> datastoreType, Supplier<T> txSupplier, BiFunction<Class<D>, T, W> txWrapper,
106 InterruptibleCheckedConsumer<W, E> txConsumer, BiFunction<T, W, FluentFuture<?>> txSubmitter) {
107 return applyWithNewTransactionAndSubmit(datastoreType, txSupplier, txWrapper, tx -> {
108 txConsumer.accept(tx);
114 @SuppressWarnings("checkstyle:IllegalCatch")
115 protected <D extends Datastore, T extends WriteTransaction, W, R, E extends Exception> FluentFuture<R>
116 applyWithNewTransactionAndSubmit(
117 Class<D> datastoreType, Supplier<T> txSupplier, BiFunction<Class<D>, T, W> txWrapper,
118 InterruptibleCheckedFunction<W, R, E> txFunction, BiFunction<T, W, FluentFuture<?>> txSubmitter) {
119 T realTx = txSupplier.get();
120 W wrappedTx = txWrapper.apply(datastoreType, realTx);
123 // We must store the result before submitting the transaction; if we inline the next line in the
124 // transform lambda, that's not guaranteed
125 result = txFunction.apply(wrappedTx);
126 } catch (Exception e) {
127 // catch Exception for both the <E extends Exception> thrown by accept() as well as any RuntimeException
128 if (!realTx.cancel()) {
129 LOG.error("Transaction.cancel() returned false - this should never happen (here)");
131 return FluentFutures.immediateFailedFluentFuture(e);
133 return txSubmitter.apply(realTx, wrappedTx).transform(v -> result, MoreExecutors.directExecutor());
136 protected T getTransactionFactory() {
137 return transactionFactory;