Clean up Datastore addressing
[mdsal.git] / binding / mdsal-binding-util / src / main / java / org / opendaylight / mdsal / binding / util / ManagedTransactionFactoryImpl.java
1 /*
2  * Copyright © 2018 Red Hat, Inc. and others.
3  *
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
7  */
8 package org.opendaylight.mdsal.binding.util;
9
10 import static java.util.Objects.requireNonNull;
11
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;
24
25 /**
26  * Basic implementation of a {@link ManagedTransactionFactory}.
27  */
28 class ManagedTransactionFactoryImpl<T extends TransactionFactory> implements ManagedTransactionFactory {
29     private static final Logger LOG = LoggerFactory.getLogger(ManagedTransactionFactoryImpl.class);
30
31     private final T transactionFactory;
32
33     ManagedTransactionFactoryImpl(final T transactionFactory) {
34         this.transactionFactory = requireNonNull(transactionFactory, "transactionFactory must not be null");
35     }
36
37     @Override
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);
45         }
46     }
47
48     @Override
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);
55         }
56     }
57
58     @Override
59     @CheckReturnValue
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());
64     }
65
66     @Override
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);
74         }
75     }
76
77     @Override
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);
84         }
85     }
86
87     @Override
88     @CheckReturnValue
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());
94     }
95
96     @Override
97     @CheckReturnValue
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());
103     }
104
105     @CheckReturnValue
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);
112             return null;
113         }, txSubmitter);
114     }
115
116     @CheckReturnValue
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);
124         R result;
125         try {
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)");
133             }
134             return FluentFutures.immediateFailedFluentFuture(e);
135         }
136         return txSubmitter.apply(realTx, wrappedTx).transform(v -> result, MoreExecutors.directExecutor());
137     }
138
139     protected T getTransactionFactory() {
140         return transactionFactory;
141     }
142 }