import com.google.common.util.concurrent.FluentFuture;
import com.google.common.util.concurrent.MoreExecutors;
import java.util.Optional;
+import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
-import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeReadOperations;
import org.opendaylight.mdsal.dom.api.DOMDataTreeTransaction;
import org.opendaylight.yangtools.concepts.Delegator;
import org.opendaylight.yangtools.concepts.Identifiable;
abstract class AbstractForwardedTransaction<T extends DOMDataTreeTransaction> implements Delegator<T>,
Identifiable<Object> {
- private final T delegate;
- private final BindingToNormalizedNodeCodec codec;
+ private final @NonNull BindingToNormalizedNodeCodec codec;
+ private final @NonNull T delegate;
AbstractForwardedTransaction(final T delegateTx, final BindingToNormalizedNodeCodec codec) {
this.delegate = requireNonNull(delegateTx, "Delegate must not be null");
this.codec = requireNonNull(codec, "Codec must not be null");
}
-
@Override
public final Object getIdentifier() {
return delegate.getIdentifier();
return delegate;
}
- @SuppressWarnings("unchecked")
protected final <S extends DOMDataTreeTransaction> S getDelegateChecked(final Class<S> txType) {
checkState(txType.isInstance(delegate));
- return (S) delegate;
+ return txType.cast(delegate);
}
protected final BindingToNormalizedNodeCodec getCodec() {
return codec;
}
- protected final <D extends DataObject> FluentFuture<Optional<D>> doRead(
- final DOMDataTreeReadTransaction readTx, final LogicalDatastoreType store,
- final InstanceIdentifier<D> path) {
+ protected final <D extends DataObject> FluentFuture<Optional<D>> doRead(final DOMDataTreeReadOperations readOps,
+ final LogicalDatastoreType store, final InstanceIdentifier<D> path) {
checkArgument(!path.isWildcarded(), "Invalid read of wildcarded path %s", path);
- return readTx.read(store, codec.toYangInstanceIdentifierBlocking(path))
+ return readOps.read(store, codec.toYangInstanceIdentifierBlocking(path))
.transform(codec.getCodecRegistry().deserializeFunction(path)::apply, MoreExecutors.directExecutor());
}
}
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-class BindingDOMReadTransactionAdapter extends AbstractForwardedTransaction<DOMDataTreeReadTransaction> implements
+final class BindingDOMReadTransactionAdapter extends AbstractForwardedTransaction<DOMDataTreeReadTransaction> implements
ReadTransaction {
protected BindingDOMReadTransactionAdapter(final DOMDataTreeReadTransaction delegate,
}
@Override
- public <T extends DataObject> FluentFuture<Optional<T>> read(
- final LogicalDatastoreType store, final InstanceIdentifier<T> path) {
+ public <T extends DataObject> FluentFuture<Optional<T>> read(final LogicalDatastoreType store,
+ final InstanceIdentifier<T> path) {
return doRead(getDelegate(),store, path);
}
@Override
public final <T extends DataObject> FluentFuture<Optional<T>> read(final LogicalDatastoreType store,
final InstanceIdentifier<T> path) {
- return doRead(getDelegate(),store, path);
+ return doRead(getDelegate(), store, path);
}
}
--- /dev/null
+/*
+ * Copyright (c) 2018 Pantheon Technologies. 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.mdsal.dom.api;
+
+import com.google.common.util.concurrent.FluentFuture;
+import java.util.Optional;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.mdsal.common.api.ReadFailedException;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+public interface DOMDataTreeReadOperations {
+ /**
+ * Reads data from provided logical data store located at the provided path.
+ *
+ *<p>
+ * If the target is a subtree, then the whole subtree is read (and will be accessible from the returned data
+ * object).
+ *
+ * @param store Logical data store from which read should occur.
+ * @param path Path which uniquely identifies subtree which client want to read
+ * @return a FluentFuture containing the result of the read. The Future blocks until the commit operation is
+ * complete. Once complete:
+ * <ul>
+ * <li>If the data at the supplied path exists, the Future returns an Optional object containing the data.
+ * </li>
+ * <li>If the data at the supplied path does not exist, the Future returns Optional.empty().</li>
+ * <li>If the read of the data fails, the Future will fail with a {@link ReadFailedException} or
+ * an exception derived from ReadFailedException.</li>
+ * </ul>
+ */
+ FluentFuture<Optional<NormalizedNode<?,?>>> read(LogicalDatastoreType store, YangInstanceIdentifier path);
+
+ /**
+ * Checks if data is available in the logical data store located at provided path.
+ *
+ * <p>
+ * Note: a successful result from this method makes no guarantee that a subsequent call to {@link #read} will
+ * succeed. It is possible that the data resides in a data store on a remote node and, if that node goes down or
+ * a network failure occurs, a subsequent read would fail. Another scenario is if the data is deleted in between
+ * the calls to <code>exists</code> and <code>read</code>
+ *
+ * @param store Logical data store from which read should occur.
+ * @param path Path which uniquely identifies subtree which client want to check existence of
+ * @return a FluentFuture containing the result of the check.
+ * <ul>
+ * <li>If the data at the supplied path exists, the Future returns a Boolean whose value is true,
+ * false otherwise</li>
+ * <li>If checking for the data fails, the Future will fail with a {@link ReadFailedException} or
+ * an exception derived from ReadFailedException.</li>
+ * </ul>
+ */
+ FluentFuture<Boolean> exists(LogicalDatastoreType store, YangInstanceIdentifier path);
+}
*/
package org.opendaylight.mdsal.dom.api;
-import com.google.common.util.concurrent.FluentFuture;
-import java.util.Optional;
-import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
-import org.opendaylight.mdsal.common.api.ReadFailedException;
import org.opendaylight.yangtools.concepts.Registration;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
/**
* A transaction that provides read access to a logical data store.
* java.util.concurrent.Executor)} or other functions from {@link com.google.common.util.concurrent.Futures} to register
* more specific listeners.
*/
-public interface DOMDataTreeReadTransaction extends DOMDataTreeTransaction, Registration {
- /**
- * Reads data from provided logical data store located at the provided path.
- *
- *<p>
- * If the target is a subtree, then the whole subtree is read (and will be accessible from the returned data
- * object).
- *
- * @param store Logical data store from which read should occur.
- * @param path Path which uniquely identifies subtree which client want to read
- * @return a FluentFuture containing the result of the read. The Future blocks until the commit operation is
- * complete. Once complete:
- * <ul>
- * <li>If the data at the supplied path exists, the Future returns an Optional object containing the data.
- * </li>
- * <li>If the data at the supplied path does not exist, the Future returns Optional.empty().</li>
- * <li>If the read of the data fails, the Future will fail with a {@link ReadFailedException} or
- * an exception derived from ReadFailedException.</li>
- * </ul>
- */
- FluentFuture<Optional<NormalizedNode<?,?>>> read(LogicalDatastoreType store, YangInstanceIdentifier path);
-
- /**
- * Checks if data is available in the logical data store located at provided path.
- *
- * <p>
- * Note: a successful result from this method makes no guarantee that a subsequent call to {@link #read} will
- * succeed. It is possible that the data resides in a data store on a remote node and, if that node goes down or
- * a network failure occurs, a subsequent read would fail. Another scenario is if the data is deleted in between
- * the calls to <code>exists</code> and <code>read</code>
- *
- * @param store Logical data store from which read should occur.
- * @param path Path which uniquely identifies subtree which client want to check existence of
- * @return a FluentFuture containing the result of the check.
- * <ul>
- * <li>If the data at the supplied path exists, the Future returns a Boolean whose value is true,
- * false otherwise</li>
- * <li>If checking for the data fails, the Future will fail with a {@link ReadFailedException} or
- * an exception derived from ReadFailedException.</li>
- * </ul>
- */
- FluentFuture<Boolean> exists(LogicalDatastoreType store, YangInstanceIdentifier path);
-
+public interface DOMDataTreeReadTransaction extends DOMDataTreeTransaction, DOMDataTreeReadOperations, Registration {
/**
* Closes this transaction and releases all resources associated with it.
*/
* For more information on usage and examples, please see the documentation in {@link DOMDataTreeReadTransaction}
* and {@link DOMDataTreeWriteTransaction}.
*/
-public interface DOMDataTreeReadWriteTransaction extends DOMDataTreeReadTransaction, DOMDataTreeWriteTransaction {
+// FIXME: 4.0.0: extend DOMDataTreeReadOperations instead of DOMDataTreeReadTransaction
+public interface DOMDataTreeReadWriteTransaction extends DOMDataTreeWriteTransaction, DOMDataTreeReadTransaction {
+ /**
+ * This method is an API design mistake. Users should not use it and use {@link #cancel()} instead. Implementations
+ * should not override it and rely instead of its default implementation, which calls {@link #cancel()}.
+ *
+ * @deprecated Use {@link #cancel()} instead.
+ */
+ @Deprecated
+ @Override
+ default void close() {
+ cancel();
+ }
}
--- /dev/null
+/*
+ * Copyright (c) 2018 Pantheon Technologies. 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.mdsal.dom.api;
+
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+public interface DOMDataTreeWriteOperations {
+ /**
+ * Stores a piece of data at the specified path. This acts as an add / replace operation, which is to say that whole
+ * subtree will be replaced by the specified data.
+ *
+ * <p>
+ * If you need to make sure that a parent object exists but you do not want modify its pre-existing state by using
+ * put, consider using {@link #merge} instead.
+ *
+ * @param store the logical data store which should be modified
+ * @param path the data object path
+ * @param data the data object to be written to the specified path
+ * @throws IllegalStateException if the transaction has already been submitted
+ */
+ void put(LogicalDatastoreType store, YangInstanceIdentifier path, NormalizedNode<?, ?> data);
+
+ /**
+ * Merges a piece of data with the existing data at a specified path. Any pre-existing data which is not explicitly
+ * overwritten will be preserved. This means that if you store a container, its child lists will be merged.
+ *
+ * <p>
+ * If you require an explicit replace operation, use {@link #put} instead.
+ *
+ * @param store the logical data store which should be modified
+ * @param path the data object path
+ * @param data the data object to be merged to the specified path
+ * @throws IllegalStateException if the transaction has already been submitted
+ */
+ void merge(LogicalDatastoreType store, YangInstanceIdentifier path, NormalizedNode<?, ?> data);
+
+ /**
+ * Removes a piece of data from specified path. This operation does not fail if the specified path does not exist.
+ *
+ * @param store Logical data store which should be modified
+ * @param path Data object path
+ * @throws IllegalStateException if the transaction was committed or canceled.
+ */
+ void delete(LogicalDatastoreType store, YangInstanceIdentifier path);
+}
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.mdsal.common.api.CommitInfo;
import org.opendaylight.mdsal.common.api.DataValidationFailedException;
-import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
import org.opendaylight.mdsal.common.api.OptimisticLockFailedException;
import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
/**
* Write transaction provides mutation capabilities for a data tree.
* <b>Implementation Note:</b> This interface is not intended to be implemented
* by users of MD-SAL, but only to be consumed by them.
*/
-public interface DOMDataTreeWriteTransaction extends DOMDataTreeTransaction {
- /**
- * Stores a piece of data at the specified path. This acts as an add / replace operation, which is to say that whole
- * subtree will be replaced by the specified data.
- *
- * <p>
- * If you need to make sure that a parent object exists but you do not want modify its pre-existing state by using
- * put, consider using {@link #merge} instead.
- *
- * @param store the logical data store which should be modified
- * @param path the data object path
- * @param data the data object to be written to the specified path
- * @throws IllegalStateException if the transaction has already been submitted
- */
- void put(LogicalDatastoreType store, YangInstanceIdentifier path, NormalizedNode<?, ?> data);
-
- /**
- * Merges a piece of data with the existing data at a specified path. Any pre-existing data which is not explicitly
- * overwritten will be preserved. This means that if you store a container, its child lists will be merged.
- *
- * <p>
- * If you require an explicit replace operation, use {@link #put} instead.
- *
- * @param store the logical data store which should be modified
- * @param path the data object path
- * @param data the data object to be merged to the specified path
- * @throws IllegalStateException if the transaction has already been submitted
- */
- void merge(LogicalDatastoreType store, YangInstanceIdentifier path, NormalizedNode<?, ?> data);
-
- /**
- * Removes a piece of data from specified path. This operation does not fail if the specified path does not exist.
- *
- * @param store Logical data store which should be modified
- * @param path Data object path
- * @throws IllegalStateException if the transaction was committed or canceled.
- */
- void delete(LogicalDatastoreType store, YangInstanceIdentifier path);
-
+public interface DOMDataTreeWriteTransaction extends DOMDataTreeTransaction, DOMDataTreeWriteOperations {
/**
* Commits this transaction to be asynchronously applied to update the logical data tree. The returned
* {@link FluentFuture} conveys the result of applying the data changes.
*/
package org.opendaylight.mdsal.dom.broker;
-import com.google.common.base.Preconditions;
+import static com.google.common.base.Preconditions.checkState;
+
import com.google.common.util.concurrent.FluentFuture;
import java.util.Collection;
import java.util.EnumMap;
import org.opendaylight.mdsal.dom.spi.store.DOMStoreThreePhaseCommitCohort;
import org.opendaylight.mdsal.dom.spi.store.DOMStoreTransactionFactory;
import org.opendaylight.mdsal.dom.spi.store.DOMStoreWriteTransaction;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
/**
* Abstract composite transaction factory.
*
*<p>
- * Provides an convenience common implementation for composite DOM Transactions,
- * where subtransaction is identified by {@link LogicalDatastoreType} type and
- * implementation of subtransaction is provided by
+ * Provides an convenience common implementation for composite DOM Transactions, where subtransaction is identified by
+ * {@link LogicalDatastoreType} type and implementation of subtransaction is provided by
* {@link DOMStoreTransactionFactory}.
*
- * <b>Note:</b>This class does not have thread-safe implementation of {@link #close()},
- * implementation may allow accessing and allocating new transactions during closing
- * this instance.
+ * <b>Note:</b>This class does not have thread-safe implementation of {@link #close()}, implementation may allow
+ * accessing and allocating new transactions during closing this instance.
*
- * @param <T>
- * Type of {@link DOMStoreTransactionFactory} factory.
+ * @param <T> Type of {@link DOMStoreTransactionFactory} factory.
*/
abstract class AbstractDOMForwardedTransactionFactory<T extends DOMStoreTransactionFactory> implements AutoCloseable {
@SuppressWarnings("rawtypes")
}
/**
- * Implementations must return unique identifier for each and every call of
- * this method.
+ * Implementations must return unique identifier for each and every call of this method.
*
* @return new Unique transaction identifier.
*/
* User-supplied implementation of {@link DOMDataTreeWriteTransaction#commit()} for transaction.
*
*<p>
- * Callback invoked when {@link DOMDataTreeWriteTransaction#commit()} is invoked on transaction
- * created by this factory.
+ * Callback invoked when {@link DOMDataTreeWriteTransaction#commit()} is invoked on transaction created by this
+ * factory.
*
* @param transaction Transaction on which {@link DOMDataTreeWriteTransaction#commit()} was invoked.
- * @param cohorts Iteratable of cohorts for subtransactions associated with the transaction
- * being committed.
- * @return a FluentFuture. if commit coordination on cohorts finished successfully,
- * a CommitInfo is returned from the Future, On failure,
- * the Future fails with a {@link TransactionCommitFailedException}.
+ * @param cohorts Iteratable of cohorts for subtransactions associated with the transaction being committed.
+ * @return a FluentFuture. if commit coordination on cohorts finished successfully, a CommitInfo is returned from
+ * the Future, On failure, the Future fails with a {@link TransactionCommitFailedException}.
*/
protected abstract FluentFuture<? extends CommitInfo> commit(DOMDataTreeWriteTransaction transaction,
Collection<DOMStoreThreePhaseCommitCohort> cohorts);
/**
* Creates a new composite read-only transaction.
*
- *<p>
- * Creates a new composite read-only transaction backed by one transaction per factory in
- * {@link #getTxFactories()}.
+ * <p>
+ * Creates a new composite read-only transaction backed by one transaction per factory in {@link #getTxFactories()}.
*
- *<p>
- * Subtransaction for reading is selected by supplied {@link LogicalDatastoreType} as parameter
- * for
- * {@link DOMDataTreeReadTransaction#read(LogicalDatastoreType,
- * org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier)}
+ * <p>
+ * Subtransaction for reading is selected by supplied {@link LogicalDatastoreType} as parameter for
+ * {@link DOMDataTreeReadTransaction#read(LogicalDatastoreType, YangInstanceIdentifier)}
*
- *<p>
+ * <p>
* Id of returned transaction is retrieved via {@link #newTransactionIdentifier()}.
*
* @return New composite read-only transaction.
* Creates a new composite write-only transaction
*
* <p>
- * Creates a new composite write-only transaction backed by one write-only transaction per
- * factory in {@link #getTxFactories()}.
+ * Creates a new composite write-only transaction backed by one write-only transaction per factory in
+ * {@link #getTxFactories()}.
*
* <p>
* Implementation of composite Write-only transaction is following:
*
* <ul>
- * <li>
- * {@link DOMDataTreeWriteTransaction#put(LogicalDatastoreType,
- * org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier,
- * org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode)}
- * - backing subtransaction is selected by {@link LogicalDatastoreType},
- * {@link DOMStoreWriteTransaction#write(org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier,
- * org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode)}
- * is invoked on selected subtransaction.</li>
- * <li>
- * {@link DOMDataTreeWriteTransaction#merge(LogicalDatastoreType,
- * org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier,
- * org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode)}
- * - backing subtransaction is selected by {@link LogicalDatastoreType},
- * {@link DOMStoreWriteTransaction#merge(org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier,
- * org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode)}
- * is invoked on selected subtransaction.</li>
- * <li>
- * {@link DOMDataTreeWriteTransaction#delete(LogicalDatastoreType,
- * org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier)}
- * - backing subtransaction is selected by {@link LogicalDatastoreType},
- * {@link DOMStoreWriteTransaction#delete(org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier)}
- * is invoked on selected subtransaction.
- * <li> {@link DOMDataTreeWriteTransaction#commit()} - results in invoking
- * {@link DOMStoreWriteTransaction#ready()}, gathering all resulting cohorts and then invoking
- * finalized implementation callback {@link #commit(DOMDataTreeWriteTransaction, Collection)} with
- * transaction which was commited and gathered results.</li>
+ * <li>{@link DOMDataTreeWriteTransaction#put(LogicalDatastoreType, YangInstanceIdentifier, NormalizedNode)}
+ * - backing subtransaction is selected by {@link LogicalDatastoreType},
+ * {@link DOMStoreWriteTransaction#write(YangInstanceIdentifier, NormalizedNode)} is invoked on selected
+ * subtransaction.</li>
+ * <li> {@link DOMDataTreeWriteTransaction#merge(LogicalDatastoreType, YangInstanceIdentifier, NormalizedNode)}
+ * - backing subtransaction is selected by {@link LogicalDatastoreType},
+ * {@link DOMStoreWriteTransaction#merge(YangInstanceIdentifier, NormalizedNode)} is invoked on selected
+ * subtransaction.</li>
+ * <li>{@link DOMDataTreeWriteTransaction#delete(LogicalDatastoreType, YangInstanceIdentifier)}
+ * - backing subtransaction is selected by {@link LogicalDatastoreType},
+ * {@link DOMStoreWriteTransaction#delete(YangInstanceIdentifier)} is invoked on selected subtransaction.
+ * <li>{@link DOMDataTreeWriteTransaction#commit()} - results in invoking {@link DOMStoreWriteTransaction#ready()},
+ * gathering all resulting cohorts and then invoking finalized implementation callback
+ * {@link #commit(DOMDataTreeWriteTransaction, Collection)} with transaction which was committed and gathered
+ * results.</li>
* </ul>
*
* <p>
}
/**
- * Convenience accessor of backing factories intended to be used only by
- * finalization of this class.
+ * Convenience accessor of backing factories intended to be used only by finalization of this class.
*
- * <b>Note:</b>
- * Finalization of this class may want to access other functionality of
- * supplied Transaction factories.
+ * <b>Note:</b> Finalization of this class may want to access other functionality of supplied Transaction factories.
*
* @return Map of backing transaction factories.
*/
* Checks if instance is not closed.
*
* @throws IllegalStateException If instance of this class was closed.
- *
*/
protected final void checkNotClosed() {
- Preconditions.checkState(closed == 0, "Transaction factory was closed. No further operations allowed.");
+ checkState(closed == 0, "Transaction factory was closed. No further operations allowed.");
}
@Override
public void close() {
- final boolean success = UPDATER.compareAndSet(this, 0, 1);
- Preconditions.checkState(success, "Transaction factory was already closed");
+ checkState(UPDATER.compareAndSet(this, 0, 1), "Transaction factory was already closed");
}
}
-
final class DOMForwardedReadWriteTransaction extends DOMForwardedWriteTransaction<DOMStoreReadWriteTransaction>
implements DOMDataTreeReadWriteTransaction {
- protected DOMForwardedReadWriteTransaction(final Object identifier,
- final Map<LogicalDatastoreType, DOMStoreReadWriteTransaction> backingTxs,
+ DOMForwardedReadWriteTransaction(final Object identifier,
+ final Map<LogicalDatastoreType, DOMStoreReadWriteTransaction> backingTxs,
final AbstractDOMForwardedTransactionFactory<?> commitImpl) {
super(identifier, backingTxs, commitImpl);
}
public FluentFuture<Boolean> exists(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
return getSubtransaction(store).exists(path);
}
-
- @Override
- public void close() {
- closeSubtransactions();
- }
}
*/
package org.opendaylight.mdsal.dom.broker;
-import com.google.common.base.Preconditions;
+import static com.google.common.base.Preconditions.checkState;
+import static java.util.Objects.requireNonNull;
+import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFailedFluentFuture;
+
import com.google.common.util.concurrent.FluentFuture;
import com.google.common.util.concurrent.Futures;
import java.util.ArrayList;
import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
import org.opendaylight.mdsal.dom.spi.store.DOMStoreThreePhaseCommitCohort;
import org.opendaylight.mdsal.dom.spi.store.DOMStoreWriteTransaction;
-import org.opendaylight.yangtools.util.concurrent.FluentFutures;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * Read-Write Transaction, which is composed of several
- * {@link DOMStoreWriteTransaction} transactions. A sub-transaction is selected by
- * {@link LogicalDatastoreType} type parameter in:
- *
+ * Read-Write Transaction, which is composed of several {@link DOMStoreWriteTransaction} transactions. A sub-transaction
+ * is selected by {@link LogicalDatastoreType} type parameter in:
* <ul>
* <li>{@link #put(LogicalDatastoreType, YangInstanceIdentifier, NormalizedNode)}
* <li>{@link #delete(LogicalDatastoreType, YangInstanceIdentifier)}
* <p>
* {@link #submit()} will result in invocation of
* {@link DOMDataCommitImplementation#submit(org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction, Iterable)}
- * invocation with all
- * {@link org.opendaylight.mdsal.dom.spi.store.DOMStoreThreePhaseCommitCohort} for
- * underlying transactions.
+ * invocation with all {@link org.opendaylight.mdsal.dom.spi.store.DOMStoreThreePhaseCommitCohort} for underlying
+ * transactions.
*
* @param <T> Subtype of {@link DOMStoreWriteTransaction} which is used as subtransaction.
*/
private static final Logger LOG = LoggerFactory.getLogger(DOMForwardedWriteTransaction.class);
private static final Future<?> CANCELLED_FUTURE = Futures.immediateCancelledFuture();
- /**
- * Implementation of real commit. It also acts as an indication that
- * the transaction is running -- which we flip atomically using
- * {@link #IMPL_UPDATER}.
+ /*
+ * Implementation of real commit. It also acts as an indication that the transaction is running -- which we flip
+ * atomically using {@link #IMPL_UPDATER}.
*/
private volatile AbstractDOMForwardedTransactionFactory<?> commitImpl;
- /**
- * Future task of transaction commit. It starts off as null, but is
- * set appropriately on {@link #submit()} and {@link #cancel()} via
- * {@link AtomicReferenceFieldUpdater#lazySet(Object, Object)}.
+ /*
+ * Future task of transaction commit. It starts off as null, but is set appropriately on {@link #submit()} and
+ * {@link #cancel()} via {@link AtomicReferenceFieldUpdater#lazySet(Object, Object)}.
*
- *<p>
- * Lazy set is safe for use because it is only referenced to in the
- * {@link #cancel()} slow path, where we will busy-wait for it. The
- * fast path gets the benefit of a store-store barrier instead of the
- * usual store-load barrier.
+ * Lazy set is safe for use because it is only referenced to in the {@link #cancel()} slow path, where we will
+ * busy-wait for it. The fast path gets the benefit of a store-store barrier instead of the usual store-load
+ * barrier.
*/
private volatile Future<?> commitFuture;
- protected DOMForwardedWriteTransaction(final Object identifier,
- final Map<LogicalDatastoreType, T> backingTxs, final AbstractDOMForwardedTransactionFactory<?> commitImpl) {
+ protected DOMForwardedWriteTransaction(final Object identifier, final Map<LogicalDatastoreType, T> backingTxs,
+ final AbstractDOMForwardedTransactionFactory<?> commitImpl) {
super(identifier, backingTxs);
- this.commitImpl = Preconditions.checkNotNull(commitImpl, "commitImpl must not be null.");
+ this.commitImpl = requireNonNull(commitImpl, "commitImpl must not be null.");
}
@Override
ret = impl.commit(this, cohorts);
} catch (RuntimeException e) {
- ret = FluentFutures.immediateFailedFluentFuture(
- TransactionCommitFailedExceptionMapper.COMMIT_ERROR_MAPPER.apply(e));
+ ret = immediateFailedFluentFuture(TransactionCommitFailedExceptionMapper.COMMIT_ERROR_MAPPER.apply(e));
}
FUTURE_UPDATER.lazySet(this, ret);
return ret;
}
private void checkRunning(final AbstractDOMForwardedTransactionFactory<?> impl) {
- Preconditions.checkState(impl != null, "Transaction %s is no longer running", getIdentifier());
+ checkState(impl != null, "Transaction %s is no longer running", getIdentifier());
}
}
*/
package org.opendaylight.mdsal.dom.broker;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
+import static com.google.common.base.Preconditions.checkState;
+import static java.util.Objects.requireNonNull;
+
import com.google.common.util.concurrent.FluentFuture;
-import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.SettableFuture;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
+import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
import org.opendaylight.mdsal.dom.api.DOMDataTreeListener;
import org.slf4j.LoggerFactory;
public class ShardedDOMReadTransactionAdapter implements DOMDataTreeReadTransaction {
-
private static final Logger LOG = LoggerFactory.getLogger(ShardedDOMReadTransactionAdapter.class.getName());
- private final List<ListenerRegistration<DOMDataTreeListener>> registrations = Lists.newArrayList();
- private final DOMDataTreeService service;
- private final Object txIdentifier;
+ private final List<ListenerRegistration<DOMDataTreeListener>> registrations = new ArrayList<>();
+ private final @NonNull DOMDataTreeService service;
+ private final @NonNull Object txIdentifier;
private boolean finished = false;
ShardedDOMReadTransactionAdapter(final Object identifier, final DOMDataTreeService service) {
- this.service = Preconditions.checkNotNull(service);
- this.txIdentifier = Preconditions.checkNotNull(identifier);
+ this.service = requireNonNull(service);
+ this.txIdentifier = requireNonNull(identifier);
}
@Override
public void close() {
- // TODO should we also cancel all read futures?
LOG.debug("{}: Closing read transaction", txIdentifier);
if (finished) {
return;
}
registrations.forEach(ListenerRegistration::close);
+ // TODO should we also cancel all read futures?
finished = true;
}
Collections.singleton(new DOMDataTreeIdentifier(store, path)), false, Collections.emptyList());
registrations.add(reg);
} catch (final DOMDataTreeLoopException e) {
- // This should not happen, we are not specifying any
- // producers when registering listener
+ // This should not happen, we are not specifying any producers when registering listener
throw new IllegalStateException("Loop in listener and producers detected", e);
}
// After data tree change future is finished, we can close the listener registration
- initialDataTreeChangeFuture.addCallback(new FutureCallback<Optional<NormalizedNode<?, ?>>>() {
- @Override
- public void onSuccess(final Optional<NormalizedNode<?, ?>> result) {
- reg.close();
- }
-
- @Override
- public void onFailure(final Throwable throwable) {
- reg.close();
- }
- }, MoreExecutors.directExecutor());
-
+ initialDataTreeChangeFuture.addListener(reg::close, MoreExecutors.directExecutor());
return initialDataTreeChangeFuture;
}
}
private void checkRunning() {
- Preconditions.checkState(!finished, "Transaction is already closed");
+ checkState(!finished, "Transaction is already closed");
}
- static class ReadShardedListener implements DOMDataTreeListener {
-
+ static final class ReadShardedListener implements DOMDataTreeListener {
private final SettableFuture<Optional<NormalizedNode<?, ?>>> readResultFuture;
ReadShardedListener(final SettableFuture<Optional<NormalizedNode<?, ?>>> future) {
- this.readResultFuture = Preconditions.checkNotNull(future);
+ this.readResultFuture = requireNonNull(future);
}
@Override
public void onDataTreeChanged(final Collection<DataTreeCandidate> changes,
final Map<DOMDataTreeIdentifier, NormalizedNode<?, ?>> subtrees) {
- Preconditions.checkState(changes.size() == 1 && subtrees.size() == 1,
+ checkState(changes.size() == 1 && subtrees.size() == 1,
"DOMDataTreeListener registered exactly on one subtree");
-
- for (final DataTreeCandidate change : changes) {
- if (change.getRootNode().getModificationType().equals(ModificationType.UNMODIFIED)) {
- readResultFuture.set(Optional.empty());
- return;
- }
- }
-
- for (final NormalizedNode<?, ?> initialState : subtrees.values()) {
- readResultFuture.set(Optional.of(initialState));
+ if (changes.iterator().next().getRootNode().getModificationType().equals(ModificationType.UNMODIFIED)) {
+ readResultFuture.set(Optional.empty());
+ } else {
+ readResultFuture.set(Optional.of(subtrees.values().iterator().next()));
}
}
@Override
public void onDataTreeFailed(final Collection<DOMDataTreeListeningException> causes) {
- // TODO If we get just one exception, we don't need to do
- // chaining
+ // TODO If we get just one exception, we don't need to do chaining
// We chain all exceptions and return aggregated one
readResultFuture.setException(new DOMDataTreeListeningException("Aggregated DOMDataTreeListening exception",
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+// FIXME: 4.0.0: make this class package-protected and final
public class ShardedDOMReadWriteTransactionAdapter extends ShardedDOMWriteTransactionAdapter
implements DOMDataTreeReadWriteTransaction {
private final ShardedDOMReadTransactionAdapter readAdapter;
- ShardedDOMReadWriteTransactionAdapter(Object identifier, DOMDataTreeService transactionDelegator) {
+ ShardedDOMReadWriteTransactionAdapter(final Object identifier, final DOMDataTreeService transactionDelegator) {
super(identifier, transactionDelegator);
readAdapter = new ShardedDOMReadTransactionAdapter(identifier, transactionDelegator);
}
@Override
- public FluentFuture<Optional<NormalizedNode<?, ?>>> read(LogicalDatastoreType store,
- YangInstanceIdentifier path) {
+ public FluentFuture<Optional<NormalizedNode<?, ?>>> read(final LogicalDatastoreType store,
+ final YangInstanceIdentifier path) {
return readAdapter.read(store, path);
}
@Override
- public FluentFuture<Boolean> exists(LogicalDatastoreType store, YangInstanceIdentifier path) {
+ public FluentFuture<Boolean> exists(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
return readAdapter.exists(store, path);
}
@Override
- public void close() {
+ public boolean cancel() {
readAdapter.close();
+ return super.cancel();
}
ShardedDOMReadTransactionAdapter getReadAdapter() {
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-class TransactionChainReadWriteTransaction extends TransactionChainWriteTransaction
+final class TransactionChainReadWriteTransaction extends TransactionChainWriteTransaction
implements DOMDataTreeReadWriteTransaction {
-
private final TransactionChainReadTransaction readTx;
TransactionChainReadWriteTransaction(final Object identifier,
public FluentFuture<Boolean> exists(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
return readTx.exists(store, path);
}
-
- @Override
- public void close() {
- }
}
import org.slf4j.LoggerFactory;
/**
- * An implementation of {@link DOMTransactionChain}, which has a very specific
- * behavior, which some users may find surprising. If keeps the general
- * intent of the contract, but it makes sure there are never more than two
- * transactions allocated at any given time: one of them is being committed,
- * and while that is happening, the other one acts as the scratch pad. Once
- * the committing transaction completes successfully, the scratch transaction
- * is enqueued as soon as it is ready.
+ * An implementation of {@link DOMTransactionChain}, which has a very specific behavior, which some users may find
+ * surprising. If keeps the general intent of the contract, but it makes sure there are never more than two transactions
+ * allocated at any given time: one of them is being committed, and while that is happening, the other one acts as
+ * a scratch pad. Once the committing transaction completes successfully, the scratch transaction is enqueued as soon as
+ * it is ready.
*
* <p>
- * This mode of operation means that there is no inherent isolation between
- * the front-end transactions and transactions cannot be reasonably cancelled.
+ * This mode of operation means that there is no inherent isolation between the front-end transactions and transactions
+ * cannot be reasonably cancelled.
*
* <p>
- * It furthermore means that the transactions returned by {@link #newReadOnlyTransaction()}
- * counts as an outstanding transaction and the user may not allocate multiple
- * read-only transactions at the same time.
+ * It furthermore means that the transactions returned by {@link #newReadOnlyTransaction()} counts as an outstanding
+ * transaction and the user may not allocate multiple read-only transactions at the same time.
*/
public final class PingPongTransactionChain implements DOMTransactionChain {
private static final Logger LOG = LoggerFactory.getLogger(PingPongTransactionChain.class);
+
private final DOMTransactionChainListener listener;
private final DOMTransactionChain delegate;
@GuardedBy("this")
private Entry<PingPongTransaction, Throwable> deadTx;
- /**
- * This updater is used to manipulate the "ready" transaction. We perform only atomic
- * get-and-set on it.
- */
+ // This updater is used to manipulate the "ready" transaction. We perform only atomic get-and-set on it.
private static final AtomicReferenceFieldUpdater<PingPongTransactionChain, PingPongTransaction> READY_UPDATER =
AtomicReferenceFieldUpdater.newUpdater(PingPongTransactionChain.class, PingPongTransaction.class,
"readyTx");
private volatile PingPongTransaction readyTx;
- /**
- * This updater is used to manipulate the "locked" transaction. A locked transaction
- * means we know that the user still holds a transaction and should at some point call
- * us. We perform on compare-and-swap to ensure we properly detect when a user is
- * attempting to allocated multiple transactions concurrently.
+ /*
+ * This updater is used to manipulate the "locked" transaction. A locked transaction means we know that the user
+ * still holds a transaction and should at some point call us. We perform on compare-and-swap to ensure we properly
+ * detect when a user is attempting to allocated multiple transactions concurrently.
*/
- private static final AtomicReferenceFieldUpdater<PingPongTransactionChain, PingPongTransaction> LOCKED_UPDATER
- = AtomicReferenceFieldUpdater
- .newUpdater(PingPongTransactionChain.class, PingPongTransaction.class, "lockedTx");
+ private static final AtomicReferenceFieldUpdater<PingPongTransactionChain, PingPongTransaction> LOCKED_UPDATER =
+ AtomicReferenceFieldUpdater.newUpdater(PingPongTransactionChain.class, PingPongTransaction.class,
+ "lockedTx");
private volatile PingPongTransaction lockedTx;
- /**
- * This updater is used to manipulate the "inflight" transaction. There can be at most
- * one of these at any given time. We perform only compare-and-swap on these.
+ /*
+ * This updater is used to manipulate the "inflight" transaction. There can be at most one of these at any given
+ * time. We perform only compare-and-swap on these.
*/
- private static final AtomicReferenceFieldUpdater<PingPongTransactionChain, PingPongTransaction> INFLIGHT_UPDATER
- = AtomicReferenceFieldUpdater
- .newUpdater(PingPongTransactionChain.class, PingPongTransaction.class, "inflightTx");
+ private static final AtomicReferenceFieldUpdater<PingPongTransactionChain, PingPongTransaction> INFLIGHT_UPDATER =
+ AtomicReferenceFieldUpdater.newUpdater(PingPongTransactionChain.class, PingPongTransaction.class,
+ "inflightTx");
private volatile PingPongTransaction inflightTx;
PingPongTransactionChain(final DOMDataBroker broker, final DOMTransactionChainListener listener) {
failed = true;
/*
- * If we do not have a locked transaction, we need to ensure that
- * the backend transaction is cancelled. Otherwise we can defer
- * until the user calls us.
+ * If we do not have a locked transaction, we need to ensure that the backend transaction is cancelled.
+ * Otherwise we can defer until the user calls us.
*/
if (lockedTx == null) {
processIfReady();
checkState(shutdownTx == null, "Transaction chain %s has been shut down", this);
if (deadTx != null) {
- throw new IllegalStateException(
- String.format("Transaction chain %s has failed due to transaction %s being canceled", this,
- deadTx.getKey()), deadTx.getValue());
+ throw new IllegalStateException(String.format(
+ "Transaction chain %s has failed due to transaction %s being canceled", this, deadTx.getKey()),
+ deadTx.getValue());
}
final DOMDataTreeReadWriteTransaction delegateTx = delegate.newReadWriteTransaction();
if (!LOCKED_UPDATER.compareAndSet(this, null, oldTx)) {
// Ouch. Delegate chain has not detected a duplicate transaction allocation. This is the best we can do.
oldTx.getTransaction().cancel();
- throw new IllegalStateException(
- String.format("Reusable transaction %s raced with transaction %s", oldTx, lockedTx));
+ throw new IllegalStateException(String.format("Reusable transaction %s raced with transaction %s", oldTx,
+ lockedTx));
}
return oldTx;
}
- /*
- * This forces allocateTransaction() on a slow path, which has to happen after
- * this method has completed executing. Also inflightTx may be updated outside
- * the lock, hence we need to re-check.
+ /**
+ * This forces allocateTransaction() on a slow path, which has to happen after this method has completed executing.
+ * Also inflightTx may be updated outside the lock, hence we need to re-check.
*/
@GuardedBy("this")
private void processIfReady() {
}
/**
- * Process a ready transaction. The caller needs to ensure that
- * each transaction is seen only once by this method.
+ * Process a ready transaction. The caller needs to ensure that each transaction is seen only once by this method.
*
* @param tx Transaction which needs processing.
*/
* and return false for everything else. Cancelling such a transaction will result in all transactions in the
* batch to be cancelled.
*
- * @param tx Backend shared transaction
+ * @param tx Backend shared transaction
* @param frontendTx transaction
- * @param isOpen indicator whether the transaction was already closed
+ * @param isOpen indicator whether the transaction was already closed
*/
synchronized void cancelTransaction(final PingPongTransaction tx,
final DOMDataTreeReadWriteTransaction frontendTx) {
return false;
}
-
- @Override
- public void close() {
- // TODO Auto-generated method stub
-
- }
};
tx.recordFrontendTransaction(ret);