2 * Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved.
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.genius.datastoreutils;
10 import static java.util.Objects.requireNonNull;
11 import static org.opendaylight.genius.datastoreutils.TransactionCommitFailedExceptionMapper.SUBMIT_MAPPER;
13 import com.google.common.base.Optional;
14 import org.eclipse.jdt.annotation.NonNull;
15 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
16 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
17 import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
18 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
19 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
20 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
21 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
22 import org.opendaylight.genius.infra.RetryingManagedNewTransactionRunner;
23 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
24 import org.opendaylight.yangtools.yang.binding.DataObject;
25 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
30 * Utility methods for single transaction DataBroker usage.
32 * <p>Please consider using a {@link ManagedNewTransactionRunner} instead.
34 * @author Michael Vorburger
36 // do *NOT* make this a BP @Singleton; see https://wiki.opendaylight.org/view/BestPractices/DI_Guidelines#Nota_Bene for why
37 public class SingleTransactionDataBroker {
39 private static final Logger LOG = LoggerFactory.getLogger(SingleTransactionDataBroker.class);
41 private static final int DEFAULT_RETRIES = 3; // duplicated in RetryingManagedNewTransactionRunnerImpl
43 private final DataBroker broker;
45 // do *NOT* use BP @Inject here, see comment above
46 public SingleTransactionDataBroker(@NonNull DataBroker broker) {
47 this.broker = requireNonNull(broker, "dataBroker");
51 * Synchronously read; preferred & strongly recommended method variant
52 * over other ones offered by this class (because this is the most explicit
55 * <p>See {@link ReadTransaction#read(LogicalDatastoreType, InstanceIdentifier)}.
57 * @param datastoreType
58 * Logical data store from which read should occur.
60 * Path which uniquely identifies subtree which client want to read
64 * @return If the data at the supplied path exists, returns an Optional
65 * object containing the data; if the data at the supplied path does
66 * not exist, returns Optional#absent().
67 * @throws ReadFailedException in case of a technical (!) error while reading
69 public <T extends DataObject> Optional<T> syncReadOptional(
70 LogicalDatastoreType datastoreType, InstanceIdentifier<T> path)
71 throws ReadFailedException {
72 return syncReadOptional(broker, datastoreType, path);
75 public static <T extends DataObject> Optional<T> syncReadOptional(
76 DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path)
77 throws ReadFailedException {
79 try (ReadOnlyTransaction tx = broker.newReadOnlyTransaction()) {
80 return tx.read(datastoreType, path).checkedGet();
85 * Synchronously read; method variant to use by code which expecting that data MUST exist at given path.
87 * <p>This variant is only recommended if the calling code would treat the Optional
88 * returned by the other method variant as a terminal failure anyway, and would itself throw
89 * an Exception for that.
91 * <p>If calling code can more sensibly handle non-present data, then use
92 * {@link #syncReadOptional(LogicalDatastoreType, InstanceIdentifier)} instead of this.
94 * <p>See {@link ReadTransaction#read(LogicalDatastoreType, InstanceIdentifier)}.
96 * @param datastoreType
97 * Logical data store from which read should occur.
99 * Path which uniquely identifies subtree which client want to read
101 * DataObject subclass
103 * @return If the data at the supplied path exists, returns the data.
104 * @throws ReadFailedException in case of a technical (!) error while reading
105 * @throws ExpectedDataObjectNotFoundException a ReadFailedException sub-type, if no data exists at path
107 public <T extends DataObject> T syncRead(
108 LogicalDatastoreType datastoreType, InstanceIdentifier<T> path)
109 throws ReadFailedException {
110 return syncRead(broker, datastoreType, path);
113 public static <T extends DataObject> T syncRead(
114 DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path)
115 throws ReadFailedException {
117 try (ReadOnlyTransaction tx = broker.newReadOnlyTransaction()) {
118 Optional<T> optionalDataObject = tx.read(datastoreType, path).checkedGet();
119 if (optionalDataObject.isPresent()) {
120 return optionalDataObject.get();
122 throw new ExpectedDataObjectNotFoundException(datastoreType, path);
128 * Synchronously read; swallowing (!) ReadFailedException.
130 * <p>See {@link ReadTransaction#read(LogicalDatastoreType, InstanceIdentifier)}.
132 * @deprecated This variant is not recommended, and only exists for legacy
133 * purposes for code which does not yet correctly propagate
134 * technical exceptions. Prefer using
135 * {@link #syncReadOptional(LogicalDatastoreType, InstanceIdentifier)}.
137 * @param datastoreType
138 * Logical data store from which read should occur.
140 * Path which uniquely identifies subtree which client want to read
142 * DataObject subclass
144 * @return If the data at the supplied path exists, returns an Optional
145 * object containing the data; if the data at the supplied path does
146 * not exist, or a technical error occurred (logged), returns
150 public <T extends DataObject> Optional<T> syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(
151 LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
152 return syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker, datastoreType, path);
156 * Synchronously read; swallowing (!) ReadFailedException.
158 * @deprecated This variant is not recommended, and only exists for legacy
159 * purposes for code which does not yet correctly propagate
160 * technical exceptions. Prefer using
161 * {@link #syncReadOptional(DataBroker, LogicalDatastoreType, InstanceIdentifier)}.
164 public static <T extends DataObject> Optional<T> syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(
165 DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
167 try (ReadOnlyTransaction tx = broker.newReadOnlyTransaction()) {
168 return tx.read(datastoreType, path).checkedGet();
169 } catch (ReadFailedException e) {
170 LOG.error("ReadFailedException while reading data from {} store path {}; returning Optional.absent()",
171 datastoreType, path, e);
172 return Optional.absent();
176 public <T extends DataObject> void syncWrite(
177 LogicalDatastoreType datastoreType, InstanceIdentifier<T> path, T data)
178 throws TransactionCommitFailedException {
179 syncWrite(broker, datastoreType, path, data);
182 public <T extends DataObject> void syncWrite(
183 LogicalDatastoreType datastoreType, InstanceIdentifier<T> path, T data, int maxRetries)
184 throws TransactionCommitFailedException {
185 syncWrite(broker, datastoreType, path, data, maxRetries);
188 public static <T extends DataObject> void syncWrite(
189 DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path, T data)
190 throws TransactionCommitFailedException {
191 syncWrite(broker, datastoreType, path, data, DEFAULT_RETRIES);
194 public static <T extends DataObject> void syncWrite(
195 DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path, T data, int maxRetries)
196 throws TransactionCommitFailedException {
198 RetryingManagedNewTransactionRunner runner = new RetryingManagedNewTransactionRunner(broker, maxRetries);
199 ListenableFutures.checkedGet(
200 runner.callWithNewWriteOnlyTransactionAndSubmit(tx -> tx.put(datastoreType, path, data, true)),
204 public <T extends DataObject> void syncUpdate(
205 LogicalDatastoreType datastoreType, InstanceIdentifier<T> path, T data)
206 throws TransactionCommitFailedException {
207 syncUpdate(broker, datastoreType, path, data);
210 public <T extends DataObject> void syncUpdate(
211 LogicalDatastoreType datastoreType, InstanceIdentifier<T> path, T data, int maxRetries)
212 throws TransactionCommitFailedException {
213 syncUpdate(broker, datastoreType, path, data, maxRetries);
216 public static <T extends DataObject> void syncUpdate(
217 DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path, T data)
218 throws TransactionCommitFailedException {
219 syncUpdate(broker, datastoreType, path, data, DEFAULT_RETRIES);
222 public static <T extends DataObject> void syncUpdate(
223 DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path, T data, int maxRetries)
224 throws TransactionCommitFailedException {
225 RetryingManagedNewTransactionRunner runner = new RetryingManagedNewTransactionRunner(broker, maxRetries);
226 ListenableFutures.checkedGet(
227 runner.callWithNewWriteOnlyTransactionAndSubmit(tx -> tx.merge(datastoreType, path, data, true)),
231 public <T extends DataObject> void syncDelete(
232 LogicalDatastoreType datastoreType, InstanceIdentifier<T> path)
233 throws TransactionCommitFailedException {
234 syncDelete(broker, datastoreType, path);
237 public <T extends DataObject> void syncDelete(
238 LogicalDatastoreType datastoreType, InstanceIdentifier<T> path, int maxRetries)
239 throws TransactionCommitFailedException {
240 syncDelete(broker, datastoreType, path, maxRetries);
243 public static <T extends DataObject> void syncDelete(
244 DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path)
245 throws TransactionCommitFailedException {
246 syncDelete(broker, datastoreType, path, DEFAULT_RETRIES);
249 public static <T extends DataObject> void syncDelete(
250 DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path, int maxRetries)
251 throws TransactionCommitFailedException {
253 RetryingManagedNewTransactionRunner runner = new RetryingManagedNewTransactionRunner(broker, maxRetries);
254 ListenableFutures.checkedGet(
255 runner.callWithNewWriteOnlyTransactionAndSubmit(tx -> tx.delete(datastoreType, path)), SUBMIT_MAPPER);