diff options
Diffstat (limited to 'v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans')
16 files changed, 257 insertions, 95 deletions
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/ReadFailedException.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/ReadFailedException.java new file mode 100644 index 000000000..4da8b0e73 --- /dev/null +++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/ReadFailedException.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.impl.trans; + +import static com.google.common.base.Preconditions.checkNotNull; + +import javax.annotation.Nonnull; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Thrown when Vpp reader or customizer is not able to read data for the given id. + */ +public class ReadFailedException extends VppException { + + private final InstanceIdentifier<?> failedId; + + /** + * Constructs an ReadFailedException given data id and exception cause. + * + * @param failedId instance identifier of the data object that could not be read + * @param cause the cause of read failure + */ + public ReadFailedException(@Nonnull final InstanceIdentifier<?> failedId, final Throwable cause) { + super("Failed to read " + failedId, cause); + this.failedId = checkNotNull(failedId, "failedId should not be null"); + } + + /** + * Constructs an ReadFailedException given data id. + * + * @param failedId instance identifier of the data object that could not be read + */ + public ReadFailedException(@Nonnull final InstanceIdentifier<?> failedId) { + this(failedId, null); + } + + /** + * Returns id of the data object that could not be read. + * + * @return data object instance identifier + */ + @Nonnull + public InstanceIdentifier<?> getFailedId() { + return failedId; + } +} diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/VppApiInvocationException.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/VppApiInvocationException.java index 0bb7c2b19..042c627ef 100644 --- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/VppApiInvocationException.java +++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/VppApiInvocationException.java @@ -21,7 +21,7 @@ import com.google.common.base.Preconditions; import javax.annotation.Nonnull; /** - * Throws when Vpp jAPI method invocation failed. + * Thrown when Vpp jAPI method invocation failed. */ @Beta public class VppApiInvocationException extends VppException { diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/VppException.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/VppException.java index aa18ae705..aadeaa996 100644 --- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/VppException.java +++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/VppException.java @@ -19,7 +19,7 @@ package io.fd.honeycomb.v3po.impl.trans; import com.google.common.annotations.Beta; /** - * Base exception for Vpp writers + * Base exception for Vpp translation layer */ @Beta public class VppException extends Exception { @@ -28,11 +28,11 @@ public class VppException extends Exception { super(s); } - public VppException(final String s, final Throwable throwable) { - super(s, throwable); + public VppException(final String s, final Throwable cause) { + super(s, cause); } - public VppException(final Throwable throwable) { - super(throwable); + public VppException(final Throwable cause) { + super(cause); } } diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/ChildVppReader.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/ChildVppReader.java index 7f4d6fc4b..aad3080d4 100644 --- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/ChildVppReader.java +++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/ChildVppReader.java @@ -17,6 +17,7 @@ package io.fd.honeycomb.v3po.impl.trans.r; import com.google.common.annotations.Beta; +import io.fd.honeycomb.v3po.impl.trans.ReadFailedException; import javax.annotation.Nonnull; import org.opendaylight.yangtools.concepts.Builder; import org.opendaylight.yangtools.yang.binding.DataObject; @@ -38,9 +39,10 @@ public interface ChildVppReader<C extends DataObject> extends VppReader<C> { * determine the exact position within more complex subtrees. * @param parentBuilder Builder of parent DataObject. Objects read on this level (if any) must be placed into the * parent builder. + * @throws ReadFailedException if read was unsuccessful */ void read(@Nonnull final InstanceIdentifier<? extends DataObject> id, - @Nonnull final Builder<? extends DataObject> parentBuilder); + @Nonnull final Builder<? extends DataObject> parentBuilder) throws ReadFailedException; } diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/ListVppReader.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/ListVppReader.java index 8a7f29cb3..ce392c6bc 100644 --- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/ListVppReader.java +++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/ListVppReader.java @@ -17,6 +17,7 @@ package io.fd.honeycomb.v3po.impl.trans.r; import com.google.common.annotations.Beta; +import io.fd.honeycomb.v3po.impl.trans.ReadFailedException; import java.util.List; import javax.annotation.Nonnull; import org.opendaylight.yangtools.yang.binding.DataObject; @@ -38,7 +39,8 @@ public interface ListVppReader<D extends DataObject & Identifiable<K>, K extends * @param id Wildcarded identifier of list managed by this reader * * @return List of all entries in this list + * @throws ReadFailedException if read was unsuccessful */ @Nonnull - List<D> readList(@Nonnull final InstanceIdentifier<D> id); + List<D> readList(@Nonnull final InstanceIdentifier<D> id) throws ReadFailedException; } diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/ReaderRegistry.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/ReaderRegistry.java index 8c592a699..6a9937679 100644 --- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/ReaderRegistry.java +++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/ReaderRegistry.java @@ -18,6 +18,7 @@ package io.fd.honeycomb.v3po.impl.trans.r; import com.google.common.annotations.Beta; import com.google.common.collect.Multimap; +import io.fd.honeycomb.v3po.impl.trans.ReadFailedException; import javax.annotation.Nonnull; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; @@ -29,11 +30,13 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; public interface ReaderRegistry extends VppReader<DataObject> { /** - * Performs read on all registered root readers and merges the results into a Multimap. - * Keys represent identifiers for root DataObjects from the data tree modeled by YANG. + * Performs read on all registered root readers and merges the results into a Multimap. Keys represent identifiers + * for root DataObjects from the data tree modeled by YANG. * * @return multimap that preserves deterministic iteration order across non-distinct key values + * @throws ReadFailedException if read was unsuccessful */ @Nonnull - Multimap<InstanceIdentifier<? extends DataObject>, ? extends DataObject> readAll(); + Multimap<InstanceIdentifier<? extends DataObject>, ? extends DataObject> readAll() + throws ReadFailedException; } diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/VppReader.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/VppReader.java index 1cc76a3a4..02189e42d 100644 --- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/VppReader.java +++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/VppReader.java @@ -18,6 +18,7 @@ package io.fd.honeycomb.v3po.impl.trans.r; import com.google.common.annotations.Beta; import com.google.common.base.Optional; +import io.fd.honeycomb.v3po.impl.trans.ReadFailedException; import io.fd.honeycomb.v3po.impl.trans.SubtreeManager; import javax.annotation.Nonnull; import org.opendaylight.yangtools.yang.binding.DataObject; @@ -42,8 +43,10 @@ public interface VppReader<D extends DataObject> extends SubtreeManager<D> { * identifiers pointing below node managed by this reader, it's reader's responsibility to filter out the * right node or to delegate the read to a child reader. * @return List of DataObjects identified by id. If the ID points to a single node, it will be wrapped in a list + * @throws ReadFailedException if read was unsuccessful */ @Nonnull - Optional<? extends DataObject> read(@Nonnull final InstanceIdentifier<? extends DataObject> id); + Optional<? extends DataObject> read(@Nonnull final InstanceIdentifier<? extends DataObject> id) throws + ReadFailedException; } diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/impl/AbstractCompositeVppReader.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/impl/AbstractCompositeVppReader.java index 61f318b35..061cfc9f3 100644 --- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/impl/AbstractCompositeVppReader.java +++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/impl/AbstractCompositeVppReader.java @@ -22,6 +22,7 @@ import com.google.common.annotations.Beta; import com.google.common.base.Optional; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; +import io.fd.honeycomb.v3po.impl.trans.ReadFailedException; import io.fd.honeycomb.v3po.impl.trans.r.ChildVppReader; import io.fd.honeycomb.v3po.impl.trans.r.VppReader; import io.fd.honeycomb.v3po.impl.trans.util.ReflectionUtils; @@ -68,7 +69,8 @@ abstract class AbstractCompositeVppReader<D extends DataObject, B extends Builde /** * @param id {@link InstanceIdentifier} pointing to current node. In case of keyed list, key must be present. */ - protected Optional<D> readCurrent(final InstanceIdentifier<D> id) { + protected Optional<D> readCurrent(final InstanceIdentifier<D> id) throws + ReadFailedException { LOG.debug("{}: Reading current: {}", this, id); final B builder = getBuilder(id); // Cache empty value to determine if anything has changed later TODO cache in a field @@ -101,7 +103,8 @@ abstract class AbstractCompositeVppReader<D extends DataObject, B extends Builde @Nonnull @Override @SuppressWarnings("unchecked") - public Optional<? extends DataObject> read(@Nonnull final InstanceIdentifier<? extends DataObject> id) { + public Optional<? extends DataObject> read(@Nonnull final InstanceIdentifier<? extends DataObject> id) + throws ReadFailedException { LOG.trace("{}: Reading : {}", this, id); if (id.getTargetType().equals(getManagedDataObjectType().getTargetType())) { return readCurrent((InstanceIdentifier<D>) id); @@ -110,7 +113,8 @@ abstract class AbstractCompositeVppReader<D extends DataObject, B extends Builde } } - private Optional<? extends DataObject> readSubtree(final InstanceIdentifier<? extends DataObject> id) { + private Optional<? extends DataObject> readSubtree(final InstanceIdentifier<? extends DataObject> id) + throws ReadFailedException { LOG.debug("{}: Reading subtree: {}", this, id); final Class<? extends DataObject> next = VppRWUtils.getNextId(id, getManagedDataObjectType()).getType(); final ChildVppReader<? extends ChildOf<D>> vppReader = childReaders.get(next); @@ -139,7 +143,8 @@ abstract class AbstractCompositeVppReader<D extends DataObject, B extends Builde * @param id {@link InstanceIdentifier} pointing to current node. In case of keyed list, key must be present. * @param builder Builder object for current node where the read attributes must be placed */ - protected abstract void readCurrentAttributes(final InstanceIdentifier<D> id, B builder); + protected abstract void readCurrentAttributes(final InstanceIdentifier<D> id, B builder) throws + ReadFailedException; /** * Return new instance of a builder object for current node diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/impl/CompositeChildVppReader.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/impl/CompositeChildVppReader.java index a64a72bc4..f18a5b38a 100644 --- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/impl/CompositeChildVppReader.java +++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/impl/CompositeChildVppReader.java @@ -18,6 +18,7 @@ package io.fd.honeycomb.v3po.impl.trans.r.impl; import com.google.common.annotations.Beta; import com.google.common.base.Optional; +import io.fd.honeycomb.v3po.impl.trans.ReadFailedException; import io.fd.honeycomb.v3po.impl.trans.r.ChildVppReader; import io.fd.honeycomb.v3po.impl.trans.r.impl.spi.ChildVppReaderCustomizer; import io.fd.honeycomb.v3po.impl.trans.util.VppRWUtils; @@ -78,7 +79,7 @@ public final class CompositeChildVppReader<C extends DataObject, B extends Build @Override public final void read(@Nonnull final InstanceIdentifier<? extends DataObject> parentId, - @Nonnull final Builder<? extends DataObject> parentBuilder) { + @Nonnull final Builder<? extends DataObject> parentBuilder) throws ReadFailedException { final Optional<C> read = readCurrent(VppRWUtils.appendTypeToId(parentId, getManagedDataObjectType())); if(read.isPresent()) { @@ -87,7 +88,8 @@ public final class CompositeChildVppReader<C extends DataObject, B extends Build } @Override - protected void readCurrentAttributes(@Nonnull final InstanceIdentifier<C> id, @Nonnull final B builder) { + protected void readCurrentAttributes(@Nonnull final InstanceIdentifier<C> id, @Nonnull final B builder) + throws ReadFailedException { customizer.readCurrentAttributes(id, builder); } diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/impl/CompositeListVppReader.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/impl/CompositeListVppReader.java index 7e3d8452e..a9ca3e788 100644 --- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/impl/CompositeListVppReader.java +++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/impl/CompositeListVppReader.java @@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkArgument; import com.google.common.annotations.Beta; import com.google.common.base.Optional; +import io.fd.honeycomb.v3po.impl.trans.ReadFailedException; import io.fd.honeycomb.v3po.impl.trans.r.ChildVppReader; import io.fd.honeycomb.v3po.impl.trans.r.ListVppReader; import io.fd.honeycomb.v3po.impl.trans.r.impl.spi.ListVppReaderCustomizer; @@ -39,17 +40,16 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * Composite implementation of {@link ChildVppReader} able to place the read result into - * parent builder object intended for list node type. + * Composite implementation of {@link ChildVppReader} able to place the read result into parent builder object intended + * for list node type. * - * This reader checks if the IDs are wildcarded in which case it performs read of all - * list entries. In case the ID has a key, it reads only the specified value. + * This reader checks if the IDs are wildcarded in which case it performs read of all list entries. In case the ID has a + * key, it reads only the specified value. */ @Beta @ThreadSafe public final class CompositeListVppReader<C extends DataObject & Identifiable<K>, K extends Identifier<C>, B extends Builder<C>> - extends AbstractCompositeVppReader<C, B> implements ChildVppReader<C>, ListVppReader<C, K> -{ + extends AbstractCompositeVppReader<C, B> implements ChildVppReader<C>, ListVppReader<C, K> { private static final Logger LOG = LoggerFactory.getLogger(CompositeListVppReader.class); @@ -59,10 +59,9 @@ public final class CompositeListVppReader<C extends DataObject & Identifiable<K> * Create new {@link CompositeListVppReader} * * @param managedDataObjectType Class object for managed data type. Must come from a list node type. - * @param childReaders Child nodes(container, list) readers - * @param augReaders Child augmentations readers - * @param customizer Customizer instance to customize this generic reader - * + * @param childReaders Child nodes(container, list) readers + * @param augReaders Child augmentations readers + * @param customizer Customizer instance to customize this generic reader */ public CompositeListVppReader(@Nonnull final Class<C> managedDataObjectType, @Nonnull final List<ChildVppReader<? extends ChildOf<C>>> childReaders, @@ -87,12 +86,12 @@ public final class CompositeListVppReader<C extends DataObject & Identifiable<K> public CompositeListVppReader(@Nonnull final Class<C> managedDataObjectType, @Nonnull final ListVppReaderCustomizer<C, K, B> customizer) { this(managedDataObjectType, VppRWUtils.<C>emptyChildReaderList(), VppRWUtils.<C>emptyAugReaderList(), - customizer); + customizer); } @Override public void read(@Nonnull final InstanceIdentifier<? extends DataObject> id, - @Nonnull final Builder<? extends DataObject> parentBuilder) { + @Nonnull final Builder<? extends DataObject> parentBuilder) throws ReadFailedException { // Create ID pointing to current node final InstanceIdentifier<C> currentId = VppRWUtils.appendTypeToId(id, getManagedDataObjectType()); // Read all, since current ID is definitely wildcarded @@ -102,7 +101,7 @@ public final class CompositeListVppReader<C extends DataObject & Identifiable<K> @Override @Nonnull - public List<C> readList(@Nonnull final InstanceIdentifier<C> id) { + public List<C> readList(@Nonnull final InstanceIdentifier<C> id) throws ReadFailedException { LOG.trace("{}: Reading all list entries", this); final List<K> allIds = customizer.getAllIds(id); LOG.debug("{}: Reading list entries for: {}", this, allIds); @@ -110,7 +109,7 @@ public final class CompositeListVppReader<C extends DataObject & Identifiable<K> final ArrayList<C> allEntries = new ArrayList<>(allIds.size()); for (K key : allIds) { final InstanceIdentifier.IdentifiableItem<C, K> currentBdItem = - VppRWUtils.getCurrentIdItem(id, key); + VppRWUtils.getCurrentIdItem(id, key); final InstanceIdentifier<C> keyedId = VppRWUtils.replaceLastInId(id, currentBdItem); final Optional<C> read = readCurrent(keyedId); final DataObject singleItem = read.get(); @@ -121,7 +120,8 @@ public final class CompositeListVppReader<C extends DataObject & Identifiable<K> } @Override - protected void readCurrentAttributes(@Nonnull final InstanceIdentifier<C> id, @Nonnull final B builder) { + protected void readCurrentAttributes(@Nonnull final InstanceIdentifier<C> id, @Nonnull final B builder) + throws ReadFailedException { customizer.readCurrentAttributes(id, builder); } diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/impl/CompositeRootVppReader.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/impl/CompositeRootVppReader.java index c87600b26..d5d82e7dd 100644 --- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/impl/CompositeRootVppReader.java +++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/impl/CompositeRootVppReader.java @@ -17,6 +17,7 @@ package io.fd.honeycomb.v3po.impl.trans.r.impl; import com.google.common.annotations.Beta; +import io.fd.honeycomb.v3po.impl.trans.ReadFailedException; import io.fd.honeycomb.v3po.impl.trans.r.ChildVppReader; import io.fd.honeycomb.v3po.impl.trans.r.VppReader; import io.fd.honeycomb.v3po.impl.trans.r.impl.spi.RootVppReaderCustomizer; @@ -76,7 +77,8 @@ public final class CompositeRootVppReader<C extends DataObject, B extends Builde } @Override - protected void readCurrentAttributes(@Nonnull final InstanceIdentifier<C> id, @Nonnull final B builder) { + protected void readCurrentAttributes(@Nonnull final InstanceIdentifier<C> id, @Nonnull final B builder) + throws ReadFailedException { customizer.readCurrentAttributes(id, builder); } diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/impl/spi/RootVppReaderCustomizer.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/impl/spi/RootVppReaderCustomizer.java index a09ed0488..299e94367 100644 --- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/impl/spi/RootVppReaderCustomizer.java +++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/impl/spi/RootVppReaderCustomizer.java @@ -17,6 +17,7 @@ package io.fd.honeycomb.v3po.impl.trans.r.impl.spi; import com.google.common.annotations.Beta; +import io.fd.honeycomb.v3po.impl.trans.ReadFailedException; import javax.annotation.Nonnull; import org.opendaylight.yangtools.concepts.Builder; import org.opendaylight.yangtools.yang.binding.DataObject; @@ -31,16 +32,20 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; @Beta public interface RootVppReaderCustomizer<C extends DataObject, B extends Builder<C>> { - // TODO add (un)checked, well defined exception here to indicate issues in the customizer - /** - * Create new builder that will be used to build read value + * Creates new builder that will be used to build read value. */ @Nonnull B getBuilder(@Nonnull final InstanceIdentifier<C> id); + /** - * Add current data (identified by id) to the provided builder + * Adds current data (identified by id) to the provided builder. + * + * @param id id of current data object + * @param builder builder for creating read value + * @throws ReadFailedException if read was unsuccessful */ - void readCurrentAttributes(@Nonnull final InstanceIdentifier<C> id, @Nonnull final B builder); + void readCurrentAttributes(@Nonnull final InstanceIdentifier<C> id, @Nonnull final B builder) throws + ReadFailedException; } diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/util/DelegatingReaderRegistry.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/util/DelegatingReaderRegistry.java index 0777425b2..20524073e 100644 --- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/util/DelegatingReaderRegistry.java +++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/util/DelegatingReaderRegistry.java @@ -22,6 +22,7 @@ import com.google.common.base.Optional; import com.google.common.collect.Iterables; import com.google.common.collect.LinkedListMultimap; import com.google.common.collect.Multimap; +import io.fd.honeycomb.v3po.impl.trans.ReadFailedException; import io.fd.honeycomb.v3po.impl.trans.r.ListVppReader; import io.fd.honeycomb.v3po.impl.trans.r.ReaderRegistry; import io.fd.honeycomb.v3po.impl.trans.r.VppReader; @@ -36,8 +37,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * Simple reader registry able to perform and aggregated read (ROOT read) on top of all - * provided readers. Also able to delegate a specific read to one of the delegate readers. + * Simple reader registry able to perform and aggregated read (ROOT read) on top of all provided readers. Also able to + * delegate a specific read to one of the delegate readers. * * This could serve as a utility to hold & hide all available readers in upper layers. */ @@ -58,7 +59,8 @@ public final class DelegatingReaderRegistry implements ReaderRegistry { @Override @Nonnull - public Multimap<InstanceIdentifier<? extends DataObject>, ? extends DataObject> readAll() { + public Multimap<InstanceIdentifier<? extends DataObject>, ? extends DataObject> readAll() + throws ReadFailedException { LOG.debug("Reading from all delegates: {}", this); LOG.trace("Reading from all delegates: {}", rootReaders.values()); @@ -66,15 +68,15 @@ public final class DelegatingReaderRegistry implements ReaderRegistry { for (VppReader<? extends DataObject> rootReader : rootReaders.values()) { LOG.debug("Reading from delegate: {}", rootReader); - if(rootReader instanceof ListVppReader) { + if (rootReader instanceof ListVppReader) { final List<? extends DataObject> listEntries = - ((ListVppReader) rootReader).readList(rootReader.getManagedDataObjectType()); - if(!listEntries.isEmpty()) { + ((ListVppReader) rootReader).readList(rootReader.getManagedDataObjectType()); + if (!listEntries.isEmpty()) { objects.putAll(rootReader.getManagedDataObjectType(), listEntries); } } else { final Optional<? extends DataObject> read = rootReader.read(rootReader.getManagedDataObjectType()); - if(read.isPresent()) { + if (read.isPresent()) { objects.putAll(rootReader.getManagedDataObjectType(), Collections.singletonList(read.get())); } } @@ -85,12 +87,13 @@ public final class DelegatingReaderRegistry implements ReaderRegistry { @Nonnull @Override - public Optional<? extends DataObject> read(@Nonnull final InstanceIdentifier<? extends DataObject> id) { + public Optional<? extends DataObject> read(@Nonnull final InstanceIdentifier<? extends DataObject> id) + throws ReadFailedException { final InstanceIdentifier.PathArgument first = checkNotNull( - Iterables.getFirst(id.getPathArguments(), null), "Empty id"); + Iterables.getFirst(id.getPathArguments(), null), "Empty id"); final VppReader<? extends DataObject> vppReader = rootReaders.get(first.getType()); checkNotNull(vppReader, - "Unable to read %s. Missing reader. Current readers for: %s", id, rootReaders.keySet()); + "Unable to read %s. Missing reader. Current readers for: %s", id, rootReaders.keySet()); LOG.debug("Reading from delegate: {}", vppReader); return vppReader.read(id); } diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/VppWriter.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/VppWriter.java index f8a49a271..d338fafa2 100644 --- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/VppWriter.java +++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/VppWriter.java @@ -25,7 +25,8 @@ import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; /** - * Base VPP writer, responsible for translation between DataObjects and VPP APIs. Handling all update operations(create, update, delete) + * Base VPP writer, responsible for translation between DataObjects and VPP APIs. Handling all update operations(create, + * update, delete) * * @param <D> Specific DataObject derived type, that is handled by this writer */ @@ -35,10 +36,11 @@ public interface VppWriter<D extends DataObject> extends SubtreeManager<D> { /** * Handle update operation. U from CRUD. * - * @param id Identifier(from root) of data being written + * @param id Identifier(from root) of data being written * @param dataBefore Old data - * @param dataAfter New, updated data - * @param ctx Write context enabling writer to get information about candidate data as well as current data + * @param dataAfter New, updated data + * @param ctx Write context enabling writer to get information about candidate data as well as current data + * @throws VppException if update failed */ void update(@Nonnull final InstanceIdentifier<? extends DataObject> id, @Nullable final DataObject dataBefore, diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/WriterRegistry.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/WriterRegistry.java index 4b09ff29e..26c294b30 100644 --- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/WriterRegistry.java +++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/WriterRegistry.java @@ -16,8 +16,12 @@ package io.fd.honeycomb.v3po.impl.trans.w; +import static com.google.common.base.Preconditions.checkNotNull; + import com.google.common.annotations.Beta; +import com.google.common.collect.ImmutableList; import io.fd.honeycomb.v3po.impl.trans.VppException; +import java.util.List; import java.util.Map; import javax.annotation.Nonnull; import org.opendaylight.yangtools.yang.binding.DataObject; @@ -33,23 +37,51 @@ public interface WriterRegistry extends VppWriter<DataObject> { * Performs bulk update * * @throws BulkUpdateException in case bulk update fails + * @throws VppException in case some other error occurs while processing update request */ void update(@Nonnull final Map<InstanceIdentifier<?>, DataObject> dataBefore, @Nonnull final Map<InstanceIdentifier<?>, DataObject> dataAfter, - @Nonnull final WriteContext ctx) throws VppException, BulkUpdateException; + @Nonnull final WriteContext ctx) throws VppException; + /** + * Thrown when bulk update failed. + */ @Beta - public class BulkUpdateException extends VppException { + class BulkUpdateException extends VppException { - private final Revert runnable; + private final Reverter reverter; + private final InstanceIdentifier<?> failedId; // TODO change to VppDataModification + + /** + * Constructs an BulkUpdateException. + * + * @param failedId instance identifier of the data object that caused bulk update to fail. + * @param cause the cause of bulk update failure + */ + public BulkUpdateException(@Nonnull final InstanceIdentifier<?> failedId, @Nonnull final Reverter reverter, + final Throwable cause) { + super("Bulk update failed at " + failedId, cause); + this.failedId = checkNotNull(failedId, "failedId should not be null"); + this.reverter = checkNotNull(reverter, "reverter should not be null"); + } - public BulkUpdateException(final InstanceIdentifier<?> id, final RuntimeException e, final Revert runnable) { - super("Bulk edit failed at " + id, e); - this.runnable = runnable; + /** + * Reverts changes that were successfully applied during bulk update before failure occurred. + * + * @throws Reverter.RevertFailedException if revert fails + */ + public void revertChanges() throws Reverter.RevertFailedException { + reverter.revert(); } - public void revertChanges() throws VppException { - runnable.revert(); + /** + * Returns instance identifier of the data object that caused bulk update to fail. + * + * @return data object's instance identifier + */ + @Nonnull + public InstanceIdentifier<?> getFailedId() { + return failedId; } } @@ -57,8 +89,47 @@ public interface WriterRegistry extends VppWriter<DataObject> { * Abstraction over revert mechanism in cast of a bulk update failure */ @Beta - public interface Revert { + interface Reverter { - public void revert() throws VppException; + /** + * Reverts changes that were successfully applied during bulk update before failure occurred. Changes are + * reverted in reverse order they were applied. + * + * @throws RevertFailedException if not all of applied changes were successfully reverted + */ + void revert() throws RevertFailedException; + + /** + * Thrown when some of the changes applied during bulk update were not reverted. + */ + @Beta + class RevertFailedException extends VppException { + + // TODO change to list of VppDataModifications to make debugging easier + private final List<InstanceIdentifier<?>> notRevertedChanges; + + /** + * Constructs an RevertFailedException with the list of changes that were not reverted. + * + * @param notRevertedChanges list of changes that were not reverted + * @param cause the cause of revert failure + */ + public RevertFailedException(@Nonnull final List<InstanceIdentifier<?>> notRevertedChanges, + final Throwable cause) { + super(cause); + checkNotNull(notRevertedChanges, "notRevertedChanges should not be null"); + this.notRevertedChanges = ImmutableList.copyOf(notRevertedChanges); + } + + /** + * Returns the list of changes that were not reverted. + * + * @return list of changes that were not reverted + */ + @Nonnull + public List<InstanceIdentifier<?>> getNotRevertedChanges() { + return notRevertedChanges; + } + } } -} +}
\ No newline at end of file diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/util/DelegatingWriterRegistry.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/util/DelegatingWriterRegistry.java index d20e69a8b..cc1188e17 100644 --- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/util/DelegatingWriterRegistry.java +++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/util/DelegatingWriterRegistry.java @@ -29,8 +29,8 @@ import io.fd.honeycomb.v3po.impl.trans.util.VppRWUtils; import io.fd.honeycomb.v3po.impl.trans.w.VppWriter; import io.fd.honeycomb.v3po.impl.trans.w.WriteContext; import io.fd.honeycomb.v3po.impl.trans.w.WriterRegistry; +import java.util.LinkedList; import java.util.List; -import java.util.ListIterator; import java.util.Map; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -40,8 +40,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * Simple writer registry able to perform and aggregated read (ROOT write) on top of all - * provided writers. Also able to delegate a specific read to one of the delegate writers. + * Simple writer registry able to perform and aggregated read (ROOT write) on top of all provided writers. Also able to + * delegate a specific read to one of the delegate writers. * * This could serve as a utility to hold & hide all available writers in upper layers. */ @@ -50,12 +50,12 @@ public final class DelegatingWriterRegistry implements WriterRegistry { private static final Logger LOG = LoggerFactory.getLogger(DelegatingWriterRegistry.class); private static final Function<InstanceIdentifier<?>, Class<? extends DataObject>> ID_TO_CLASS = - new Function<InstanceIdentifier<?>, Class<? extends DataObject>>() { - @Override - public Class<? extends DataObject> apply(final InstanceIdentifier<?> input) { - return input.getTargetType(); - } - }; + new Function<InstanceIdentifier<?>, Class<? extends DataObject>>() { + @Override + public Class<? extends DataObject> apply(final InstanceIdentifier<?> input) { + return input.getTargetType(); + } + }; private final Map<Class<? extends DataObject>, VppWriter<? extends DataObject>> rootWriters; @@ -84,10 +84,10 @@ public final class DelegatingWriterRegistry implements WriterRegistry { @Nullable final DataObject dataAfter, @Nonnull final WriteContext ctx) throws VppException { final InstanceIdentifier.PathArgument first = checkNotNull( - Iterables.getFirst(id.getPathArguments(), null), "Empty id"); + Iterables.getFirst(id.getPathArguments(), null), "Empty id"); final VppWriter<? extends DataObject> vppWriter = rootWriters.get(first.getType()); checkNotNull(vppWriter, - "Unable to write %s. Missing writer. Current writers for: %s", id, rootWriters.keySet()); + "Unable to write %s. Missing writer. Current writers for: %s", id, rootWriters.keySet()); vppWriter.update(id, dataBefore, dataAfter, ctx); } @@ -101,7 +101,7 @@ public final class DelegatingWriterRegistry implements WriterRegistry { final List<InstanceIdentifier<?>> processedNodes = Lists.newArrayList(); for (Map.Entry<Class<? extends DataObject>, VppWriter<? extends DataObject>> rootWriterEntry : rootWriters - .entrySet()) { + .entrySet()) { final InstanceIdentifier<? extends DataObject> id = rootWriterEntry.getValue().getManagedDataObjectType(); @@ -109,7 +109,7 @@ public final class DelegatingWriterRegistry implements WriterRegistry { final DataObject dataAfter = nodesAfter.get(id); // No change to current writer - if(dataBefore == null && dataAfter == null) { + if (dataBefore == null && dataAfter == null) { continue; } @@ -118,31 +118,32 @@ public final class DelegatingWriterRegistry implements WriterRegistry { try { update(id, dataBefore, dataAfter, ctx); processedNodes.add(id); - } catch (RuntimeException e) { - LOG.error("Error while processing data change of: {} (before={}, after={})", id, dataBefore, dataAfter, e); - throw new BulkUpdateException(id, e, new RevertImpl(this, processedNodes, nodesBefore, nodesAfter, ctx)); + } catch (Exception e) { + LOG.error("Error while processing data change of: {} (before={}, after={})", + id, dataBefore, dataAfter, e); + throw new BulkUpdateException( + id, new ReverterImpl(this, processedNodes, nodesBefore, nodesAfter, ctx), e); } } - } private void checkAllWritersPresent(final @Nonnull Map<InstanceIdentifier<?>, DataObject> nodesBefore) { checkArgument(rootWriters.keySet().containsAll(Collections2.transform(nodesBefore.keySet(), ID_TO_CLASS)), - "Unable to handle all changes. Missing dedicated writers for: %s", - Sets.difference(nodesBefore.keySet(), rootWriters.keySet())); + "Unable to handle all changes. Missing dedicated writers for: %s", + Sets.difference(nodesBefore.keySet(), rootWriters.keySet())); } - private static final class RevertImpl implements Revert { + private static final class ReverterImpl implements Reverter { private final WriterRegistry delegatingWriterRegistry; private final List<InstanceIdentifier<?>> processedNodes; private final Map<InstanceIdentifier<?>, DataObject> nodesBefore; private final Map<InstanceIdentifier<?>, DataObject> nodesAfter; private final WriteContext ctx; - public RevertImpl(final WriterRegistry delegatingWriterRegistry, - final List<InstanceIdentifier<?>> processedNodes, - final Map<InstanceIdentifier<?>, DataObject> nodesBefore, - final Map<InstanceIdentifier<?>, DataObject> nodesAfter, final WriteContext ctx) { + ReverterImpl(final WriterRegistry delegatingWriterRegistry, + final List<InstanceIdentifier<?>> processedNodes, + final Map<InstanceIdentifier<?>, DataObject> nodesBefore, + final Map<InstanceIdentifier<?>, DataObject> nodesAfter, final WriteContext ctx) { this.delegatingWriterRegistry = delegatingWriterRegistry; this.processedNodes = processedNodes; this.nodesBefore = nodesBefore; @@ -151,12 +152,11 @@ public final class DelegatingWriterRegistry implements WriterRegistry { } @Override - public void revert() throws VppException { - - final ListIterator<InstanceIdentifier<?>> iterator = processedNodes.listIterator(processedNodes.size()); + public void revert() throws RevertFailedException { + final LinkedList<InstanceIdentifier<?>> notReverted = new LinkedList<>(processedNodes); - while (iterator.hasPrevious()) { - final InstanceIdentifier<?> node = iterator.previous(); + while (notReverted.size() > 0) { + final InstanceIdentifier<?> node = notReverted.peekLast(); LOG.debug("ChangesProcessor.revertChanges() processing node={}", node); final DataObject dataBefore = nodesBefore.get(node); @@ -165,9 +165,11 @@ public final class DelegatingWriterRegistry implements WriterRegistry { // revert a change by invoking writer with reordered arguments try { delegatingWriterRegistry.update(node, dataAfter, dataBefore, ctx); - } catch (RuntimeException e) { - throw new RuntimeException(); + notReverted.removeLast(); // change was successfully reverted + } catch (Exception e) { + throw new RevertFailedException(notReverted, e); } + } } } |