2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yangtools.yang.data.tree.impl;
10 import static java.util.Objects.requireNonNull;
12 import com.google.common.collect.ImmutableMap;
13 import java.lang.invoke.MethodHandles;
14 import java.lang.invoke.VarHandle;
15 import org.eclipse.jdt.annotation.NonNull;
16 import org.eclipse.jdt.annotation.Nullable;
17 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
18 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeConfiguration;
19 import org.opendaylight.yangtools.yang.data.tree.impl.AbstractNodeContainerModificationStrategy.Visible;
20 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
21 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
26 * Base strategy for applying changes to a ContainerNode, irrespective of its actual type.
28 * @param <T> Type of the container node
30 sealed class DataNodeContainerModificationStrategy<T extends DataSchemaNode & DataNodeContainer> extends Visible<T>
31 permits ContainerModificationStrategy, MapEntryModificationStrategy {
32 private static final Logger LOG = LoggerFactory.getLogger(DataNodeContainerModificationStrategy.class);
33 private static final VarHandle CHILDREN;
37 CHILDREN = MethodHandles.lookup().findVarHandle(
38 DataNodeContainerModificationStrategy.class, "children", ImmutableMap.class);
39 } catch (NoSuchFieldException | IllegalAccessException e) {
40 throw new ExceptionInInitializerError(e);
44 private final @NonNull DataTreeConfiguration treeConfig;
46 @SuppressWarnings("unused")
47 private volatile ImmutableMap<PathArgument, ModificationApplyOperation> children = ImmutableMap.of();
49 DataNodeContainerModificationStrategy(final NormalizedNodeContainerSupport<?, ?> support, final T schema,
50 final DataTreeConfiguration treeConfig) {
51 super(support, treeConfig, schema);
52 this.treeConfig = requireNonNull(treeConfig, "treeConfig");
56 public final ModificationApplyOperation childByArg(final PathArgument arg) {
57 final var local = (ImmutableMap<PathArgument, ModificationApplyOperation>) CHILDREN.getAcquire(this);
58 final var existing = local.get(arg);
59 if (existing != null) {
63 final var childOperation = resolveChild(arg);
64 return childOperation != null ? appendChild(local, arg, childOperation) : null;
67 private ModificationApplyOperation resolveChild(final PathArgument identifier) {
68 final var schema = getSchema();
69 final var qname = identifier.getNodeType();
70 final var child = schema.dataChildByName(qname);
72 LOG.trace("Child {} not present in container schema {} children {}", identifier, this,
73 schema.getChildNodes());
78 return SchemaAwareApplyOperation.from(child, treeConfig);
79 } catch (ExcludedDataSchemaNodeException e) {
80 LOG.trace("Failed to instantiate child {} in container schema {} children {}", identifier, this,
81 schema.getChildNodes(), e);
86 private @Nullable ModificationApplyOperation appendChild(
87 final ImmutableMap<PathArgument, ModificationApplyOperation> initial, final PathArgument identifier,
88 final ModificationApplyOperation computed) {
89 var previous = initial;
91 // Build up a new map based on observed snapshot and computed child
92 final var updated = ImmutableMap
93 .<PathArgument, ModificationApplyOperation>builderWithExpectedSize(previous.size() + 1)
95 .put(identifier, computed)
98 // Attempt to install the updated map
99 final var witness = (ImmutableMap<PathArgument, ModificationApplyOperation>)
100 CHILDREN.compareAndExchangeRelease(this, previous, updated);
101 if (witness == previous) {
105 // We have raced, acquire a new snapshot, recheck presence and retry if needed
107 final var raced = previous.get(identifier);