Eliminate PlainPatchDataTransactionUtil 14/107214/6
authorRobert Varga <robert.varga@pantheon.tech>
Wed, 2 Aug 2023 20:08:12 +0000 (22:08 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Thu, 3 Aug 2023 13:42:55 +0000 (15:42 +0200)
Move the implementation and rework synchronization, so that it occurs in
RestconfDataServiceImpl. Also drop a FIXME for optimization follow-up.

JIRA: NETCONF-1113
Change-Id: I0b4f23ecf71fbd0d5f923972d8333434970e9d19
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfDataServiceImpl.java
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/transactions/RestconfStrategy.java
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/utils/PlainPatchDataTransactionUtil.java [deleted file]
restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/rfc8040/rests/transactions/AbstractRestconfStrategyTest.java

index 91e0ab6a4d726118dbf6cb6c5dcf3ead7cb1ebe1..edaa5c43de26fcf431d6f5023c7a4c6396c04637 100644 (file)
@@ -57,7 +57,6 @@ import org.opendaylight.restconf.nb.rfc8040.rests.services.api.RestconfStreamsSu
 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.MdsalRestconfStrategy;
 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfStrategy;
 import org.opendaylight.restconf.nb.rfc8040.rests.utils.PatchDataTransactionUtil;
-import org.opendaylight.restconf.nb.rfc8040.rests.utils.PlainPatchDataTransactionUtil;
 import org.opendaylight.restconf.nb.rfc8040.rests.utils.PostDataTransactionUtil;
 import org.opendaylight.restconf.nb.rfc8040.rests.utils.PutDataTransactionUtil;
 import org.opendaylight.restconf.nb.rfc8040.rests.utils.ReadDataTransactionUtil;
@@ -304,8 +303,9 @@ public class RestconfDataServiceImpl implements RestconfDataService {
         validTopLevelNodeName(path, payload);
         validateListKeysEqualityInPayloadAndUri(payload);
 
-        final RestconfStrategy strategy = getRestconfStrategy(iid.getMountPoint());
-        return PlainPatchDataTransactionUtil.patchData(path, payload.getData(), strategy, iid.getSchemaContext());
+        getRestconfStrategy(iid.getMountPoint()).merge(path, payload.getData(), iid.getSchemaContext())
+            .getOrThrow();
+        return Response.ok().build();
     }
 
     @VisibleForTesting
index 6bc9d8351eecd3514a6324fcf0cbfe43257a2cc2..70f5a7a2fa59e8911f60afdb837cd5e945fcee11 100644 (file)
@@ -9,19 +9,25 @@ package org.opendaylight.restconf.nb.rfc8040.rests.transactions;
 
 import static java.util.Objects.requireNonNull;
 
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
 import java.util.List;
 import java.util.Optional;
 import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.common.api.CommitInfo;
 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
 import org.opendaylight.mdsal.dom.api.DOMMountPoint;
 import org.opendaylight.netconf.dom.api.NetconfDataTreeService;
 import org.opendaylight.restconf.common.errors.RestconfFuture;
 import org.opendaylight.restconf.common.errors.SettableRestconfFuture;
+import org.opendaylight.restconf.nb.rfc8040.rests.utils.TransactionUtil;
 import org.opendaylight.yangtools.yang.common.Empty;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
 
 /**
  * Baseline execution strategy for various RESTCONF operations.
@@ -106,4 +112,41 @@ public abstract class RestconfStrategy {
     }
 
     protected abstract void delete(@NonNull SettableRestconfFuture<Empty> future, @NonNull YangInstanceIdentifier path);
+
+    /**
+     * Merge data into the configuration datastore, as outlined in
+     * <a href="https://www.rfc-editor.org/rfc/rfc8040#section-4.6.1">RFC8040 section 4.6.1</a>.
+     *
+     * @param path Path to merge
+     * @param data Data to merge
+     * @param context Corresponding EffectiveModelContext
+     * @return A {@link RestconfFuture}
+     * @throws NullPointerException if any argument is {@code null}
+     */
+    public final @NonNull RestconfFuture<Empty> merge(final YangInstanceIdentifier path, final NormalizedNode data,
+            final EffectiveModelContext context) {
+        final var ret = new SettableRestconfFuture<Empty>();
+        merge(ret, requireNonNull(path), requireNonNull(data), requireNonNull(context));
+        return ret;
+    }
+
+    private void merge(final @NonNull SettableRestconfFuture<Empty> future,
+            final @NonNull YangInstanceIdentifier path, final @NonNull NormalizedNode data,
+            final @NonNull EffectiveModelContext context) {
+        final var tx = prepareWriteExecution();
+        // FIXME: this method should be further specialized to eliminate this call -- it is only needed for MD-SAL
+        TransactionUtil.ensureParentsByMerge(path, context, tx);
+        tx.merge(path, data);
+        Futures.addCallback(tx.commit(), new FutureCallback<CommitInfo>() {
+            @Override
+            public void onSuccess(final CommitInfo result) {
+                future.set(Empty.value());
+            }
+
+            @Override
+            public void onFailure(final Throwable cause) {
+                future.setFailure(TransactionUtil.decodeException(cause, "MERGE", path));
+            }
+        }, MoreExecutors.directExecutor());
+    }
 }
diff --git a/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/utils/PlainPatchDataTransactionUtil.java b/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/utils/PlainPatchDataTransactionUtil.java
deleted file mode 100644 (file)
index 178b035..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2020 Lumina Networks, Inc. and others.  All rights reserved.
- * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.restconf.nb.rfc8040.rests.utils;
-
-import javax.ws.rs.core.Response;
-import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
-import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
-import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfStrategy;
-import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfTransaction;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Util class for plain patch data to DS.
- */
-public final class PlainPatchDataTransactionUtil {
-    private static final Logger LOG = LoggerFactory.getLogger(PlainPatchDataTransactionUtil.class);
-
-    private PlainPatchDataTransactionUtil() {
-        // Hidden on purpose
-    }
-
-    /**
-     * Prepare variables for put data to DS. Close {@link DOMTransactionChain} if any inside of object
-     * {@link RestconfStrategy} provided as a parameter if any.
-     *
-     * @param path          data path
-     * @param data          data to put
-     * @param schemaContext reference to {@link EffectiveModelContext}
-     * @param strategy      object that perform the actual DS operations
-     * @return {@link Response}
-     */
-    public static Response patchData(final YangInstanceIdentifier path, final NormalizedNode data,
-            final RestconfStrategy strategy, final EffectiveModelContext schemaContext) {
-        final RestconfTransaction transaction = strategy.prepareWriteExecution();
-
-        try {
-            LOG.trace("Merge CONFIGURATION within Restconf Patch: {} with payload {}", path, data);
-            TransactionUtil.ensureParentsByMerge(path, schemaContext, transaction);
-            transaction.merge(path, data);
-        } catch (final RestconfDocumentedException e) {
-            transaction.cancel();
-            throw new IllegalArgumentException(e);
-        }
-
-        TransactionUtil.syncCommit(transaction.commit(), PatchDataTransactionUtil.PATCH_TX_TYPE, path);
-        return Response.ok().build();
-    }
-}
index d6a8088c56b577f9e6639b26b607c9e9283eb830..e251345a27852a4944dd86cce407c07efda0b282 100644 (file)
@@ -44,7 +44,6 @@ import org.opendaylight.restconf.common.patch.PatchStatusContext;
 import org.opendaylight.restconf.nb.rfc8040.AbstractJukeboxTest;
 import org.opendaylight.restconf.nb.rfc8040.WriteDataParams;
 import org.opendaylight.restconf.nb.rfc8040.rests.utils.PatchDataTransactionUtil;
-import org.opendaylight.restconf.nb.rfc8040.rests.utils.PlainPatchDataTransactionUtil;
 import org.opendaylight.restconf.nb.rfc8040.rests.utils.PostDataTransactionUtil;
 import org.opendaylight.restconf.nb.rfc8040.rests.utils.ReadDataTransactionUtil;
 import org.opendaylight.yangtools.yang.common.ErrorTag;
@@ -301,27 +300,21 @@ abstract class AbstractRestconfStrategyTest extends AbstractJukeboxTest {
 
     @Test
     public final void testPatchContainerData() {
-        final var response = PlainPatchDataTransactionUtil.patchData(JUKEBOX_IID, EMPTY_JUKEBOX,
-            testPatchContainerDataStrategy(), JUKEBOX_SCHEMA);
-        assertEquals(200, response.getStatus());
+        testPatchContainerDataStrategy().merge(JUKEBOX_IID, EMPTY_JUKEBOX, JUKEBOX_SCHEMA).getOrThrow();
     }
 
     abstract @NonNull RestconfStrategy testPatchContainerDataStrategy();
 
     @Test
     public final void testPatchLeafData() {
-        final var response = PlainPatchDataTransactionUtil.patchData(GAP_IID, GAP_LEAF,
-            testPatchLeafDataStrategy(), JUKEBOX_SCHEMA);
-        assertEquals(200, response.getStatus());
+        testPatchLeafDataStrategy().merge(GAP_IID, GAP_LEAF, JUKEBOX_SCHEMA).getOrThrow();
     }
 
     abstract @NonNull RestconfStrategy testPatchLeafDataStrategy();
 
     @Test
     public final void testPatchListData() {
-        final var response = PlainPatchDataTransactionUtil.patchData(JUKEBOX_IID, JUKEBOX_WITH_PLAYLIST,
-            testPatchListDataStrategy(), JUKEBOX_SCHEMA);
-        assertEquals(200, response.getStatus());
+        testPatchListDataStrategy().merge(JUKEBOX_IID, JUKEBOX_WITH_PLAYLIST, JUKEBOX_SCHEMA).getOrThrow();
     }
 
     abstract @NonNull RestconfStrategy testPatchListDataStrategy();