import static java.util.Objects.requireNonNull;
import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableMap.Builder;
-import java.util.Optional;
-import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.tree.api.DataTreeConfiguration;
import org.opendaylight.yangtools.yang.data.tree.impl.AbstractNodeContainerModificationStrategy.Visible;
-import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
*/
class DataNodeContainerModificationStrategy<T extends DataNodeContainer & WithStatus> extends Visible<T> {
private static final Logger LOG = LoggerFactory.getLogger(DataNodeContainerModificationStrategy.class);
+ private static final VarHandle CHILDREN;
+
+ static {
+ try {
+ CHILDREN = MethodHandles.lookup().findVarHandle(
+ DataNodeContainerModificationStrategy.class, "children", ImmutableMap.class);
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
private final @NonNull DataTreeConfiguration treeConfig;
- @SuppressWarnings("rawtypes")
- private static final AtomicReferenceFieldUpdater<DataNodeContainerModificationStrategy, ImmutableMap> UPDATER =
- AtomicReferenceFieldUpdater.newUpdater(DataNodeContainerModificationStrategy.class, ImmutableMap.class,
- "children");
+ @SuppressWarnings("unused")
private volatile ImmutableMap<PathArgument, ModificationApplyOperation> children = ImmutableMap.of();
DataNodeContainerModificationStrategy(final NormalizedNodeContainerSupport<?, ?> support, final T schema,
@Override
public final ModificationApplyOperation childByArg(final PathArgument arg) {
- final ImmutableMap<PathArgument, ModificationApplyOperation> local = children;
- final ModificationApplyOperation existing = local.get(arg);
+ final var local = (ImmutableMap<PathArgument, ModificationApplyOperation>) CHILDREN.getAcquire(this);
+ final var existing = local.get(arg);
if (existing != null) {
return existing;
}
- final ModificationApplyOperation childOperation = resolveChild(arg);
+ final var childOperation = resolveChild(arg);
return childOperation != null ? appendChild(local, arg, childOperation) : null;
}
private ModificationApplyOperation resolveChild(final PathArgument identifier) {
final T schema = getSchema();
- if (identifier instanceof AugmentationIdentifier && schema instanceof AugmentationTarget) {
- return SchemaAwareApplyOperation.from(schema, (AugmentationTarget) schema,
- (AugmentationIdentifier) identifier, treeConfig);
- }
-
- final QName qname = identifier.getNodeType();
- final Optional<DataSchemaNode> child = schema.findDataChildByName(qname);
- if (!child.isPresent()) {
+ final var qname = identifier.getNodeType();
+ final var child = schema.dataChildByName(qname);
+ if (child == null) {
LOG.trace("Child {} not present in container schema {} children {}", identifier, this,
schema.getChildNodes());
return null;
}
try {
- return SchemaAwareApplyOperation.from(child.get(), treeConfig);
+ return SchemaAwareApplyOperation.from(child, treeConfig);
} catch (ExcludedDataSchemaNodeException e) {
LOG.trace("Failed to instantiate child {} in container schema {} children {}", identifier, this,
schema.getChildNodes(), e);
private @Nullable ModificationApplyOperation appendChild(
final ImmutableMap<PathArgument, ModificationApplyOperation> initial, final PathArgument identifier,
final ModificationApplyOperation computed) {
-
- ImmutableMap<PathArgument, ModificationApplyOperation> previous = initial;
+ var previous = initial;
while (true) {
// Build up a new map based on observed snapshot and computed child
- final Builder<PathArgument, ModificationApplyOperation> builder = ImmutableMap.builderWithExpectedSize(
- previous.size() + 1);
- builder.putAll(previous);
- builder.put(identifier, computed);
- final ImmutableMap<PathArgument, ModificationApplyOperation> updated = builder.build();
+ final var updated = ImmutableMap
+ .<PathArgument, ModificationApplyOperation>builderWithExpectedSize(previous.size() + 1)
+ .putAll(previous)
+ .put(identifier, computed)
+ .build();
// Attempt to install the updated map
- if (UPDATER.compareAndSet(this, previous, updated)) {
+ final var witness = (ImmutableMap<PathArgument, ModificationApplyOperation>)
+ CHILDREN.compareAndExchangeRelease(this, previous, updated);
+ if (witness == previous) {
return computed;
}
// We have raced, acquire a new snapshot, recheck presence and retry if needed
- previous = children;
- final ModificationApplyOperation raced = previous.get(identifier);
+ previous = witness;
+ final var raced = previous.get(identifier);
if (raced != null) {
return raced;
}