/*
* Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.genius.datastoreutils;
import com.google.common.base.Optional;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Utility methods for single transaction DataBroker usage.
*
* @author Michael Vorburger
*/
// do *NOT* make this a BP @Singleton; see https://wiki.opendaylight.org/view/BestPractices/DI_Guidelines#Nota_Bene for why
public class SingleTransactionDataBroker {
private static final Logger LOG = LoggerFactory.getLogger(SingleTransactionDataBroker.class);
private final DataBroker broker;
// do *NOT* use BP @Inject here, see comment above
public SingleTransactionDataBroker(DataBroker broker) {
this.broker = broker;
}
/**
* Synchronously read; preferred & strongly recommended method variant
* over other ones offered by this class (because this is the most explicit
* variant).
*
*
See {@link ReadTransaction#read(LogicalDatastoreType, InstanceIdentifier)}.
*
* @param datastoreType
* Logical data store from which read should occur.
* @param path
* Path which uniquely identifies subtree which client want to read
* @param
* DataObject subclass
*
* @return If the data at the supplied path exists, returns an Optional
* object containing the data; if the data at the supplied path does
* not exist, returns Optional#absent().
* @throws ReadFailedException in case of a technical (!) error while reading
*/
public Optional syncReadOptional(
LogicalDatastoreType datastoreType, InstanceIdentifier path)
throws ReadFailedException {
return syncReadOptional(broker, datastoreType, path);
}
public static Optional syncReadOptional(
DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier path)
throws ReadFailedException {
try (ReadOnlyTransaction tx = broker.newReadOnlyTransaction()) {
return tx.read(datastoreType, path).checkedGet();
}
}
/**
* Synchronously read; method variant to use by code which expecting that data MUST exist at given path.
*
* This variant is only recommended if the calling code would treat the Optional
* returned by the other method variant as a terminal failure anyway, and would itself throw
* an Exception for that.
*
*
If calling code can more sensibly handle non-present data, then use
* {@link #syncRead(LogicalDatastoreType, InstanceIdentifier)} instead of this.
*
*
See {@link ReadTransaction#read(LogicalDatastoreType, InstanceIdentifier)}.
*
* @param datastoreType
* Logical data store from which read should occur.
* @param path
* Path which uniquely identifies subtree which client want to read
* @param
* DataObject subclass
*
* @return If the data at the supplied path exists, returns the data.
* @throws ReadFailedException in case of a technical (!) error while reading
* @throws ExpectedDataObjectNotFoundException a ReadFailedException sub-type, if no data exists at path
*/
public T syncRead(
LogicalDatastoreType datastoreType, InstanceIdentifier path)
throws ReadFailedException {
return syncRead(broker, datastoreType, path);
}
public static T syncRead(
DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier path)
throws ReadFailedException {
try (ReadOnlyTransaction tx = broker.newReadOnlyTransaction()) {
Optional optionalDataObject = tx.read(datastoreType, path).checkedGet();
if (optionalDataObject.isPresent()) {
return optionalDataObject.get();
} else {
throw new ExpectedDataObjectNotFoundException(datastoreType, path);
}
}
}
/**
* Synchronously read; swallowing (!) ReadFailedException.
*
* See {@link ReadTransaction#read(LogicalDatastoreType, InstanceIdentifier)}.
*
* @deprecated This variant is not recommended, and only exists for legacy
* purposes for code which does not yet correctly propagate
* technical exceptions. Prefer using
* {@link #syncReadOptional(LogicalDatastoreType, InstanceIdentifier)}.
*
* @param datastoreType
* Logical data store from which read should occur.
* @param path
* Path which uniquely identifies subtree which client want to read
* @param
* DataObject subclass
*
* @return If the data at the supplied path exists, returns an Optional
* object containing the data; if the data at the supplied path does
* not exist, or a technical error occurred (logged), returns
* Optional#absent().
*/
@Deprecated
public Optional syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(
LogicalDatastoreType datastoreType, InstanceIdentifier path) {
return syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker, datastoreType, path);
}
/**
* Synchronously read; swallowing (!) ReadFailedException.
*
* @deprecated This variant is not recommended, and only exists for legacy
* purposes for code which does not yet correctly propagate
* technical exceptions. Prefer using
* {@link #syncReadOptional(DataBroker, LogicalDatastoreType, InstanceIdentifier)}.
*/
@Deprecated
public static Optional syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(
DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier path) {
try (ReadOnlyTransaction tx = broker.newReadOnlyTransaction()) {
return tx.read(datastoreType, path).checkedGet();
} catch (ReadFailedException e) {
LOG.error("ReadFailedException while reading data from {} store path {}; returning Optional.absent()",
datastoreType, path, e);
return Optional.absent();
}
}
public void syncWrite(
LogicalDatastoreType datastoreType, InstanceIdentifier path, T data)
throws TransactionCommitFailedException {
syncWrite(broker, datastoreType, path, data);
}
public static void syncWrite(
DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier path, T data)
throws TransactionCommitFailedException {
WriteTransaction tx = broker.newWriteOnlyTransaction();
tx.put(datastoreType, path, data, true);
tx.submit().checkedGet();
}
public void syncUpdate(
LogicalDatastoreType datastoreType, InstanceIdentifier path, T data)
throws TransactionCommitFailedException {
syncUpdate(broker, datastoreType, path, data);
}
public static void syncUpdate(
DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier path, T data)
throws TransactionCommitFailedException {
WriteTransaction tx = broker.newWriteOnlyTransaction();
tx.merge(datastoreType, path, data, true);
tx.submit().checkedGet();
}
public void syncDelete(
LogicalDatastoreType datastoreType, InstanceIdentifier path)
throws TransactionCommitFailedException {
syncDelete(broker, datastoreType, path);
}
public static void syncDelete(
DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier path)
throws TransactionCommitFailedException {
WriteTransaction tx = broker.newWriteOnlyTransaction();
tx.delete(datastoreType, path);
tx.submit().checkedGet();
}
// TODO Move asyncWrite/asyncUpdate/asyncRemove from org.opendaylight.genius.mdsalutil.MDSALDataStoreUtils to here
}