summaryrefslogtreecommitdiffstats
path: root/v3po/impl/src/main/java/io
diff options
context:
space:
mode:
authorMaros Marsalek <mmarsale@cisco.com>2016-04-12 10:13:02 +0200
committerMaros Marsalek <mmarsale@cisco.com>2016-04-12 10:13:02 +0200
commit5947a575539402344e450fd34b03f555b84523be (patch)
tree595ab3fc05ecc28d08b4b1d625e4e20980a33b6b /v3po/impl/src/main/java/io
parent9ac68bac54d95b0342cab52bf39a4321f1f42d79 (diff)
HONEYCOMB-9: Exception handling for VPP APIs
Change-Id: Ic71a2ac3d01e88cb38596a24a12a7bf8ebf54da5 Signed-off-by: Marek Gradzki <mgradzki@cisco.com> Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
Diffstat (limited to 'v3po/impl/src/main/java/io')
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppConfigDataTree.java12
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppOperationalDataTree.java66
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppReaderRegistry.java7
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppWriterRegistry.java2
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/ReadFailedException.java60
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/VppApiInvocationException.java2
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/VppException.java10
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/ChildVppReader.java4
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/ListVppReader.java4
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/ReaderRegistry.java9
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/VppReader.java5
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/impl/AbstractCompositeVppReader.java13
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/impl/CompositeChildVppReader.java6
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/impl/CompositeListVppReader.java30
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/impl/CompositeRootVppReader.java4
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/impl/spi/RootVppReaderCustomizer.java15
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/r/util/DelegatingReaderRegistry.java23
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/VppWriter.java10
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/WriterRegistry.java93
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/w/util/DelegatingWriterRegistry.java64
20 files changed, 306 insertions, 133 deletions
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppConfigDataTree.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppConfigDataTree.java
index f14bec3aa..9f34fcbd1 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppConfigDataTree.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppConfigDataTree.java
@@ -118,15 +118,13 @@ public final class VppConfigDataTree implements VppDataTree {
try {
e.revertChanges();
LOG.info("Changes successfully reverted");
- } catch (VppException | RuntimeException e2) {
- LOG.error("Failed to revert successful changes", e2);
+ } catch (WriterRegistry.Reverter.RevertFailedException revertFailedException) {
+ // fail with failed revert
+ LOG.error("Failed to revert successful changes", revertFailedException);
+ throw revertFailedException;
}
- // rethrow as we can't do anything more about it
- // FIXME we need to throw a different kind of exception here to differentiate between:
- // fail with success revert
- // fail with failed revert (this one needs to contain IDs of changes that were not reverted)
- throw e;
+ throw e; // fail with success revert
} catch (VppException e) {
LOG.error("Error while processing data change (before={}, after={})", nodesBefore, nodesAfter, e);
throw e;
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppOperationalDataTree.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppOperationalDataTree.java
index 3fddd108c..d0acd05a8 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppOperationalDataTree.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppOperationalDataTree.java
@@ -26,12 +26,12 @@ import com.google.common.collect.Collections2;
import com.google.common.collect.Multimap;
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.Futures;
+import io.fd.honeycomb.v3po.impl.trans.ReadFailedException;
import io.fd.honeycomb.v3po.impl.trans.r.ReaderRegistry;
import java.util.Collection;
import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -52,7 +52,6 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-
/**
* ReadableVppDataTree implementation for operational data.
*/
@@ -79,34 +78,44 @@ public final class VppOperationalDataTree implements ReadableVppDataTree {
}
@Override
- public CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> read(
+ public CheckedFuture<Optional<NormalizedNode<?, ?>>,
+ org.opendaylight.controller.md.sal.common.api.data.ReadFailedException> read(
@Nonnull final YangInstanceIdentifier yangInstanceIdentifier) {
- if (checkNotNull(yangInstanceIdentifier).equals(YangInstanceIdentifier.EMPTY)) {
- LOG.debug("VppOperationalDataProxy.read(), yangInstanceIdentifier=ROOT");
- return Futures.immediateCheckedFuture(Optional.<NormalizedNode<?, ?>>of(readRoot()));
+ try {
+ if (checkNotNull(yangInstanceIdentifier).equals(YangInstanceIdentifier.EMPTY)) {
+ return Futures.immediateCheckedFuture(readRoot());
+ } else {
+ return Futures.immediateCheckedFuture(readNode(yangInstanceIdentifier));
+ }
+ } catch (ReadFailedException e) {
+ return Futures.immediateFailedCheckedFuture(
+ new org.opendaylight.controller.md.sal.common.api.data.ReadFailedException(
+ "Failed to read VPP data", e));
}
+ }
- LOG.debug("VppOperationalDataProxy.read(), yangInstanceIdentifier={}", yangInstanceIdentifier);
+ private Optional<NormalizedNode<?, ?>> readNode(final YangInstanceIdentifier yangInstanceIdentifier)
+ throws ReadFailedException {
+ LOG.debug("VppOperationalDataTree.readNode(), yangInstanceIdentifier={}", yangInstanceIdentifier);
final InstanceIdentifier<?> path = serializer.fromYangInstanceIdentifier(yangInstanceIdentifier);
checkNotNull(path, "Invalid instance identifier %s. Cannot create BA equivalent.", yangInstanceIdentifier);
- LOG.debug("VppOperationalDataProxy.read(), path={}", path);
+ LOG.debug("VppOperationalDataTree.readNode(), path={}", path);
- final Optional<? extends DataObject> dataObject = readerRegistry.read(path);
+ final Optional<? extends DataObject> dataObject;
+ dataObject = readerRegistry.read(path);
if (dataObject.isPresent()) {
final NormalizedNode<?, ?> value = toNormalizedNodeFunction(path).apply(dataObject.get());
- return Futures.immediateCheckedFuture(Optional.<NormalizedNode<?, ?>>fromNullable(value));
+ return Optional.<NormalizedNode<?, ?>>fromNullable(value);
+ } else {
+ return Optional.absent();
}
-
- return Futures.immediateCheckedFuture(Optional.<NormalizedNode<?, ?>>absent());
}
- private DataSchemaNode getSchemaNode(final @Nonnull YangInstanceIdentifier yangInstanceIdentifier) {
- return globalContext.getDataChildByName(yangInstanceIdentifier.getLastPathArgument().getNodeType());
- }
+ private Optional<NormalizedNode<?, ?>> readRoot() throws ReadFailedException {
+ LOG.debug("VppOperationalDataTree.readRoot()");
- private NormalizedNode<?, ?> readRoot() {
final DataContainerNodeAttrBuilder<YangInstanceIdentifier.NodeIdentifier, ContainerNode> dataNodeBuilder =
Builders.containerBuilder()
.withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(SchemaContext.NAME));
@@ -121,16 +130,17 @@ public final class VppOperationalDataTree implements ReadableVppDataTree {
dataNodeBuilder.withChild((DataContainerChild<?, ?>) node);
}
- return dataNodeBuilder.build();
+ return Optional.<NormalizedNode<?, ?>>of(dataNodeBuilder.build());
}
private NormalizedNode<?, ?> wrapDataObjects(final YangInstanceIdentifier yangInstanceIdentifier,
- final InstanceIdentifier<? extends DataObject> instanceIdentifier,
- final Collection<? extends DataObject> dataObjects) {
+ final InstanceIdentifier<? extends DataObject> instanceIdentifier,
+ final Collection<? extends DataObject> dataObjects) {
final Collection<NormalizedNode<?, ?>> normalizedRootElements = Collections2
.transform(dataObjects, toNormalizedNodeFunction(instanceIdentifier));
- final DataSchemaNode schemaNode = getSchemaNode(yangInstanceIdentifier);
+ final DataSchemaNode schemaNode =
+ globalContext.getDataChildByName(yangInstanceIdentifier.getLastPathArgument().getNodeType());
if (schemaNode instanceof ListSchemaNode) {
// In case of a list, wrap all the values in a Mixin parent node
final ListSchemaNode listSchema = (ListSchemaNode) schemaNode;
@@ -142,19 +152,19 @@ public final class VppOperationalDataTree implements ReadableVppDataTree {
}
private static DataContainerChild<?, ?> wrapListIntoMixinNode(
- final Collection<NormalizedNode<?, ?>> normalizedRootElements, final ListSchemaNode listSchema) {
+ final Collection<NormalizedNode<?, ?>> normalizedRootElements, final ListSchemaNode listSchema) {
if (listSchema.getKeyDefinition().isEmpty()) {
final CollectionNodeBuilder<UnkeyedListEntryNode, UnkeyedListNode> listBuilder =
- Builders.unkeyedListBuilder();
+ Builders.unkeyedListBuilder();
for (NormalizedNode<?, ?> normalizedRootElement : normalizedRootElements) {
listBuilder.withChild((UnkeyedListEntryNode) normalizedRootElement);
}
return listBuilder.build();
} else {
final CollectionNodeBuilder<MapEntryNode, ? extends MapNode> listBuilder =
- listSchema.isUserOrdered()
- ? Builders.orderedMapBuilder()
- : Builders.mapBuilder();
+ listSchema.isUserOrdered()
+ ? Builders.orderedMapBuilder()
+ : Builders.mapBuilder();
for (NormalizedNode<?, ?> normalizedRootElement : normalizedRootElements) {
listBuilder.withChild((MapEntryNode) normalizedRootElement);
@@ -168,11 +178,11 @@ public final class VppOperationalDataTree implements ReadableVppDataTree {
return new Function<DataObject, NormalizedNode<?, ?>>() {
@Override
public NormalizedNode<?, ?> apply(@Nullable final DataObject dataObject) {
- LOG.trace("VppOperationalDataProxy.toNormalizedNode(), path={}, dataObject={}", path, dataObject);
+ LOG.trace("VppOperationalDataTree.toNormalizedNode(), path={}, dataObject={}", path, dataObject);
final Map.Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> entry =
- serializer.toNormalizedNode(path, dataObject);
+ serializer.toNormalizedNode(path, dataObject);
- LOG.trace("VppOperationalDataProxy.toNormalizedNode(), normalizedNodeEntry={}", entry);
+ LOG.trace("VppOperationalDataTree.toNormalizedNode(), normalizedNodeEntry={}", entry);
return entry.getValue();
}
};
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppReaderRegistry.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppReaderRegistry.java
index df7b6568c..72d17b7e2 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppReaderRegistry.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppReaderRegistry.java
@@ -18,6 +18,7 @@ package io.fd.honeycomb.v3po.impl.data;
import com.google.common.base.Optional;
import com.google.common.collect.Multimap;
+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.ReaderRegistry;
import io.fd.honeycomb.v3po.impl.trans.r.VppReader;
@@ -95,13 +96,15 @@ public class VppReaderRegistry implements ReaderRegistry {
@Nonnull
@Override
- public Multimap<InstanceIdentifier<? extends DataObject>, ? extends DataObject> readAll() {
+ public Multimap<InstanceIdentifier<? extends DataObject>, ? extends DataObject> readAll()
+ throws io.fd.honeycomb.v3po.impl.trans.ReadFailedException {
return reader.readAll();
}
@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 {
return reader.read(id);
}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppWriterRegistry.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppWriterRegistry.java
index 83186c2de..defcca47e 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppWriterRegistry.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/data/VppWriterRegistry.java
@@ -98,7 +98,7 @@ public class VppWriterRegistry implements WriterRegistry {
public void update(@Nonnull final Map<InstanceIdentifier<?>, DataObject> dataBefore,
@Nonnull final Map<InstanceIdentifier<?>, DataObject> dataAfter,
@Nonnull final WriteContext ctx)
- throws VppException, BulkUpdateException {
+ throws VppException {
writer.update(dataBefore, dataAfter, ctx);
}
}
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);
}
+
}
}
}