summaryrefslogtreecommitdiffstats
path: root/infra/translate-api
diff options
context:
space:
mode:
authorJan Srnicek <jsrnicek@cisco.com>2017-10-23 10:57:13 +0200
committerMarek Gradzki <mgradzki@cisco.com>2017-10-23 12:26:02 +0000
commit5503731d866d318e9d5a2183608092a9d332dfe6 (patch)
tree10470b27b8ddb1a7776f78c733546be4d1a48b29 /infra/translate-api
parent0762f9aa1a7894056c2ddbc72421b933e9ea8dcf (diff)
HONEYCOMB-405 - Revert fix for indirect updates
If indirect update(delete+create) fails in a way, that delete passed, but update part failed, delete part must be reverted Moves reverter creation to MDTG and test cases related too it to ModifiableDataTreeDelegatorRevertTest Fixes tracking of allready processed changes by tracking them from perspective of processModifications() method Introduces UpdateFailedException as replacement for BulkUpdateException(now thrown also for single updates) Separates ReverterImpl from FlatWriterRegistry and ads unit tests Change-Id: If0066d0716d9476be89b1d99985b6745becac15e Signed-off-by: Jan Srnicek <jsrnicek@cisco.com>
Diffstat (limited to 'infra/translate-api')
-rw-r--r--infra/translate-api/src/main/java/io/fd/honeycomb/translate/write/registry/UpdateFailedException.java58
-rw-r--r--infra/translate-api/src/main/java/io/fd/honeycomb/translate/write/registry/WriterRegistry.java147
-rw-r--r--infra/translate-api/src/test/java/io/fd/honeycomb/translate/write/registry/BulkUpdateExceptionTest.java63
-rw-r--r--infra/translate-api/src/test/java/io/fd/honeycomb/translate/write/registry/RevertFailedExceptionTest.java55
4 files changed, 68 insertions, 255 deletions
diff --git a/infra/translate-api/src/main/java/io/fd/honeycomb/translate/write/registry/UpdateFailedException.java b/infra/translate-api/src/main/java/io/fd/honeycomb/translate/write/registry/UpdateFailedException.java
new file mode 100644
index 000000000..82a08e46c
--- /dev/null
+++ b/infra/translate-api/src/main/java/io/fd/honeycomb/translate/write/registry/UpdateFailedException.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2017 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.translate.write.registry;
+
+import io.fd.honeycomb.translate.TranslationException;
+import io.fd.honeycomb.translate.write.DataObjectUpdate;
+import java.util.List;
+import javax.annotation.Nonnull;
+
+/**
+ * Thrown when CRUD operation fails.
+ */
+public class UpdateFailedException extends TranslationException {
+
+ private final List<DataObjectUpdate> processed;
+ private final DataObjectUpdate failed;
+
+ /**
+ * @param cause original cause of failure
+ * @param processed updates that were processed up until the point of failure
+ * @param failed update that cause the failure
+ */
+ public UpdateFailedException(@Nonnull final Throwable cause,
+ @Nonnull final List<DataObjectUpdate> processed,
+ @Nonnull final DataObjectUpdate failed) {
+ super(cause);
+ this.processed = processed;
+ this.failed = failed;
+ }
+
+ /**
+ * Returns set of nodes that has been processed by this operation till the failure happened, in execution order
+ */
+ public List<DataObjectUpdate> getProcessed() {
+ return processed;
+ }
+
+ /**
+ * Returns update that caused failure
+ */
+ public DataObjectUpdate getFailed() {
+ return failed;
+ }
+}
diff --git a/infra/translate-api/src/main/java/io/fd/honeycomb/translate/write/registry/WriterRegistry.java b/infra/translate-api/src/main/java/io/fd/honeycomb/translate/write/registry/WriterRegistry.java
index a297b6de8..e2924f84a 100644
--- a/infra/translate-api/src/main/java/io/fd/honeycomb/translate/write/registry/WriterRegistry.java
+++ b/infra/translate-api/src/main/java/io/fd/honeycomb/translate/write/registry/WriterRegistry.java
@@ -16,8 +16,6 @@
package io.fd.honeycomb.translate.write.registry;
-import static com.google.common.base.Preconditions.checkNotNull;
-
import com.google.common.annotations.Beta;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
@@ -26,6 +24,8 @@ import io.fd.honeycomb.translate.write.DataObjectUpdate;
import io.fd.honeycomb.translate.write.WriteContext;
import io.fd.honeycomb.translate.write.Writer;
import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import javax.annotation.Nonnull;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -38,8 +38,7 @@ public interface WriterRegistry {
/**
* Performs bulk update.
*
- * @throws BulkUpdateException in case bulk update fails
- * @throws TranslationException in case some other error occurs while processing update request
+ * @throws TranslationException in case update fails or there was some other problem while processing
*/
void processModifications(@Nonnull DataObjectUpdates updates,
@Nonnull WriteContext ctx) throws TranslationException;
@@ -52,8 +51,8 @@ public interface WriterRegistry {
boolean writerSupportsUpdate(@Nonnull InstanceIdentifier<?> type);
/**
- * Simple DTO containing updates for {@link WriterRegistry}. Currently only deletes and updates (create +
- * update) are distinguished.
+ * Simple DTO containing updates for {@link WriterRegistry}. Currently only deletes and updates (create + update)
+ * are distinguished.
*/
@Beta
final class DataObjectUpdates {
@@ -97,6 +96,11 @@ public interface WriterRegistry {
return Sets.union(deletes.keySet(), updates.keySet());
}
+ public Set<DataObjectUpdate> getAllModifications() {
+ return Stream.concat(updates.values().stream(), deletes.values().stream())
+ .collect(Collectors.toSet());
+ }
+
/**
* Check whether there is only a single type of data object to be updated.
*
@@ -132,135 +136,4 @@ public interface WriterRegistry {
}
}
-
- /**
- * Thrown when bulk update failed.
- */
- @Beta
- class BulkUpdateException extends TranslationException {
-
- private final transient Reverter reverter;
- private final InstanceIdentifier<?> failedSubtree;
- private final DataObjectUpdate failedData;
- private final Set<InstanceIdentifier<?>> unrevertedSubtrees;
-
- /**
- * Constructs an BulkUpdateException.
- * @param unhandledSubtrees instance identifiers of the data objects that were not processed during bulk update.
- * @param cause the cause of bulk update failure
- */
- public BulkUpdateException(@Nonnull final InstanceIdentifier<?> failedSubtree,
- @Nonnull final DataObjectUpdate failedData,
- @Nonnull final Set<InstanceIdentifier<?>> unhandledSubtrees,
- @Nonnull final Reverter reverter,
- @Nonnull final Throwable cause) {
- super("Bulk update failed at: " + failedSubtree + " ignored updates: " + unhandledSubtrees, cause);
- this.failedSubtree = failedSubtree;
- this.failedData = failedData;
- this.unrevertedSubtrees = unhandledSubtrees;
- this.reverter = checkNotNull(reverter, "reverter should not be null");
- }
-
- /**
- * Reverts changes that were successfully applied during bulk update before failure occurred.
- *
- * @param writeContext Non-closed {@code WriteContext} to be used by reverting logic.<br> <b>Do not use same
- * write context as was used in previous write</b>
- * @throws Reverter.RevertFailedException if revert fails
- */
- public void revertChanges(@Nonnull final WriteContext writeContext) throws Reverter.RevertFailedException {
- reverter.revert(writeContext);
- }
-
- public Set<InstanceIdentifier<?>> getUnrevertedSubtrees() {
- return unrevertedSubtrees;
- }
-
- public InstanceIdentifier<?> getFailedSubtree() {
- return failedSubtree;
- }
-
- public DataObjectUpdate getFailedData() {
- return failedData;
- }
- }
-
- /**
- * Abstraction over revert mechanism in case of a bulk update failure.
- */
- @Beta
- interface Reverter {
-
- /**
- * Reverts changes that were successfully applied during bulk update before failure occurred. Changes are
- * reverted in reverse order they were applied.
- * Used {@code WriteContext} needs to be in non-closed state, creating fresh one for revert
- * is recommended, same way as for write, to allow {@code Reverter} use same logic as write.
- *
- * @param writeContext Non-closed {@code WriteContext} to be used by reverting logic
- * @throws RevertFailedException if not all of applied changes were successfully reverted
- */
- void revert(@Nonnull final WriteContext writeContext) throws RevertFailedException;
-
- /**
- * Thrown when some of the changes applied during bulk update were not reverted.
- */
- @Beta
- class RevertFailedException extends TranslationException {
-
- /**
- * Constructs a RevertFailedException with the list of changes that were not reverted.
- *
- * @param cause the cause of revert failure
- */
- public RevertFailedException(@Nonnull final BulkUpdateException cause) {
- super("Unable to revert changes after failure. Revert failed for "
- + cause.getFailedSubtree() + " unreverted subtrees: " + cause.getUnrevertedSubtrees(), cause);
- }
-
- /**
- * Returns the list of changes that were not reverted.
- *
- * @return list of changes that were not reverted
- */
- @Nonnull
- public Set<InstanceIdentifier<?>> getNotRevertedChanges() {
- return ((BulkUpdateException) getCause()).getUnrevertedSubtrees();
- }
-
- /**
- * Returns the update that caused the failure.
- *
- * @return update that caused the failure
- */
- @Nonnull
- public DataObjectUpdate getFailedUpdate() {
- return ((BulkUpdateException) getCause()).getFailedData();
- }
- }
-
- /**
- * Thrown after bulk operation was successfully reverted,
- * to maintain marking of transaction as failed,without double logging of
- * cause of update fail(its logged before reverting in ModifiableDataTreeDelegator
- */
- @Beta
- class RevertSuccessException extends TranslationException {
- private final Set<InstanceIdentifier<?>> failedIds;
-
- /**
- * Constructs an RevertSuccessException.
- *
- * @param failedIds instance identifiers of the data objects that were not processed during bulk update.
- */
- public RevertSuccessException(@Nonnull final Set<InstanceIdentifier<?>> failedIds) {
- super("Bulk update failed for: " + failedIds);
- this.failedIds = failedIds;
- }
-
- public Set<InstanceIdentifier<?>> getFailedIds() {
- return failedIds;
- }
- }
- }
} \ No newline at end of file
diff --git a/infra/translate-api/src/test/java/io/fd/honeycomb/translate/write/registry/BulkUpdateExceptionTest.java b/infra/translate-api/src/test/java/io/fd/honeycomb/translate/write/registry/BulkUpdateExceptionTest.java
deleted file mode 100644
index 9623db5bc..000000000
--- a/infra/translate-api/src/test/java/io/fd/honeycomb/translate/write/registry/BulkUpdateExceptionTest.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.translate.write.registry;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.verify;
-
-import com.google.common.collect.Sets;
-import io.fd.honeycomb.translate.write.DataObjectUpdate;
-import io.fd.honeycomb.translate.write.WriteContext;
-import java.util.HashSet;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-public class BulkUpdateExceptionTest {
-
- private InstanceIdentifier<?> id = InstanceIdentifier.create(DataObject.class);
-
- @Mock
- private WriteContext writeContext;
- @Mock
- private WriterRegistry.Reverter reverter;
- @Mock
- private DataObject before;
- @Mock
- private DataObject after;
-
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
- }
-
- @Test
- public void testRevert() throws Exception {
- final HashSet<InstanceIdentifier<?>> failedIds = Sets.newHashSet(id);
- final WriterRegistry.BulkUpdateException bulkUpdateException =
- new WriterRegistry.BulkUpdateException(id, DataObjectUpdate.create(id, before, after),
- failedIds, reverter, new RuntimeException());
-
- assertEquals(failedIds, bulkUpdateException.getUnrevertedSubtrees());
-
- bulkUpdateException.revertChanges(writeContext);
- verify(reverter).revert(writeContext);
- }
-} \ No newline at end of file
diff --git a/infra/translate-api/src/test/java/io/fd/honeycomb/translate/write/registry/RevertFailedExceptionTest.java b/infra/translate-api/src/test/java/io/fd/honeycomb/translate/write/registry/RevertFailedExceptionTest.java
deleted file mode 100644
index 6502235d0..000000000
--- a/infra/translate-api/src/test/java/io/fd/honeycomb/translate/write/registry/RevertFailedExceptionTest.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.translate.write.registry;
-
-import static org.junit.Assert.assertEquals;
-
-import com.google.common.collect.Sets;
-import io.fd.honeycomb.translate.write.DataObjectUpdate;
-import java.util.Set;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-public class RevertFailedExceptionTest {
-
- private InstanceIdentifier<?> id = InstanceIdentifier.create(DataObject.class);
- @Mock
- private WriterRegistry.Reverter reverter;
- @Mock
- private DataObject before;
- @Mock
- private DataObject after;
-
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
- }
-
- @Test
- public void testNonRevert() throws Exception {
- final Set<InstanceIdentifier<?>> notReverted = Sets.newHashSet(id);
- final WriterRegistry.Reverter.RevertFailedException revertFailedException =
- new WriterRegistry.Reverter.RevertFailedException(
- new WriterRegistry.BulkUpdateException(id, DataObjectUpdate.create(id, before, after),
- notReverted, reverter, new RuntimeException()));
- assertEquals(notReverted, revertFailedException.getNotRevertedChanges());
- }
-} \ No newline at end of file