Teach BindingRuntimeContext how to lookup action paths 82/91682/3
authorRobert Varga <robert.varga@pantheon.tech>
Mon, 27 Jul 2020 11:19:41 +0000 (13:19 +0200)
committerRobert Varga <nite@hq.sk>
Mon, 3 Aug 2020 09:15:02 +0000 (09:15 +0000)
We do not want to rely on SchemaPath in binding-dom-adapter, so that
addressing is kept internal to BindingRuntimeTypes.

JIRA: MDSAL-581
Change-Id: I464582fa43b208de1ba347388cbde26161f3e304
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/CurrentAdapterSerializer.java
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/AbstractBindingRuntimeContext.java
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/BindingRuntimeContext.java
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/BindingRuntimeTypes.java
binding/mdsal-binding-runtime-spi/src/main/java/org/opendaylight/mdsal/binding/runtime/spi/ForwardingBindingRuntimeContext.java

index bad7ff3c3ecc91ad58ae1d28afec1c0833d56693..216cd07924011f03b641863c1deeb4772e2e85b0 100644 (file)
@@ -17,7 +17,6 @@ import com.google.common.cache.CacheBuilder;
 import com.google.common.cache.CacheLoader;
 import com.google.common.cache.LoadingCache;
 import com.google.common.collect.ImmutableBiMap;
-import com.google.common.collect.ImmutableList;
 import java.lang.reflect.Method;
 import java.util.Collection;
 import java.util.stream.Collectors;
@@ -36,7 +35,6 @@ import org.opendaylight.yangtools.yang.binding.RpcService;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.model.api.ActionDefinition;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
@@ -84,10 +82,9 @@ public final class CurrentAdapterSerializer extends ForwardingBindingDOMCodecSer
     }
 
     @NonNull Absolute getActionPath(final @NonNull Class<? extends Action<?, ?, ?>> type) {
-        // FIXME: we really just want a SchemaNodeIdentifier.Absolute here
-        final ActionDefinition schema = getRuntimeContext().getActionDefinition(type);
-        checkArgument(schema != null, "Failed to find schema for %s", type);
-        return Absolute.of(ImmutableList.copyOf(schema.getPath().getPathFromRoot()));
+        final Absolute identifier = getRuntimeContext().getActionIdentifier(type);
+        checkArgument(identifier != null, "Failed to find schema for %s", type);
+        return identifier;
     }
 
     // FIXME: This should be probably part of Binding Runtime context
index 6b7b625b5a948122b9bf7878620096fe0a575ab5..33a0a1ba6ccfa58559d0100b4380c9ab8bba7448 100644 (file)
@@ -47,6 +47,7 @@ import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
 import org.opendaylight.yangtools.yang.model.util.EffectiveAugmentationSchema;
 import org.opendaylight.yangtools.yang.model.util.SchemaNodeUtils;
 import org.slf4j.Logger;
@@ -132,6 +133,11 @@ public abstract class AbstractBindingRuntimeContext implements BindingRuntimeCon
         return (ActionDefinition) getTypes().findSchema(DefaultType.of(cls)).orElse(null);
     }
 
+    @Override
+    public final Absolute getActionIdentifier(final Class<? extends Action<?, ?, ?>> cls) {
+        return getTypes().findSchemaNodeIdentifier(DefaultType.of(cls)).orElse(null);
+    }
+
     @Override
     public final Entry<AugmentationIdentifier, AugmentationSchemaNode> getResolvedAugmentationSchema(
             final DataNodeContainer target, final Class<? extends Augmentation<?>> aug) {
index 001e03fdd4fd6644568ceda3a86320b400aff38e..f375c134268be6f85a7eb62c9475df7d614a8daa 100644 (file)
@@ -33,6 +33,7 @@ import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContextProvider;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
 
 /**
  * Runtime Context for Java YANG Binding classes. It provides information derived from the backing effective model,
@@ -99,6 +100,8 @@ public interface BindingRuntimeContext extends EffectiveModelContextProvider, Im
 
     @Nullable ActionDefinition getActionDefinition(Class<? extends Action<?, ?, ?>> cls);
 
+    @Nullable Absolute getActionIdentifier(Class<? extends Action<?, ?, ?>> cls);
+
     @NonNull Entry<AugmentationIdentifier, AugmentationSchemaNode> getResolvedAugmentationSchema(
             DataNodeContainer target, Class<? extends Augmentation<?>> aug);
 
index 70cad8fc9a6d3edea742f36dffdba6bb927e6313..3ab49d66e5751e79822291fd13de9b6c003c3d50 100644 (file)
@@ -13,9 +13,12 @@ import com.google.common.annotations.Beta;
 import com.google.common.base.MoreObjects;
 import com.google.common.collect.BiMap;
 import com.google.common.collect.ImmutableBiMap;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableMultimap;
 import com.google.common.collect.Multimap;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.Collection;
 import java.util.Map;
 import java.util.Optional;
@@ -27,18 +30,35 @@ import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContextProvider;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
 
 /**
  * The result of BindingGenerator run. Contains mapping between Types and SchemaNodes.
  */
 @Beta
 public final class BindingRuntimeTypes implements EffectiveModelContextProvider, Immutable {
+    private static final VarHandle TYPE_TO_IDENTIFIER;
+
+    static {
+        try {
+            TYPE_TO_IDENTIFIER = MethodHandles.lookup().findVarHandle(BindingRuntimeTypes.class, "typeToIdentifier",
+                ImmutableMap.class);
+        } catch (NoSuchFieldException | IllegalAccessException e) {
+            throw new ExceptionInInitializerError(e);
+        }
+    }
+
     private final @NonNull EffectiveModelContext schemaContext;
     private final ImmutableMap<Type, AugmentationSchemaNode> typeToAugmentation;
     private final ImmutableBiMap<Type, WithStatus> typeToSchema;
     private final ImmutableMultimap<Type, Type> choiceToCases;
     private final ImmutableMap<QName, Type> identities;
 
+    @SuppressWarnings("unused")
+    // Accessed via TYPE_TO_IDENTIFIER
+    private volatile ImmutableMap<Type, Absolute> typeToIdentifier = ImmutableMap.of();
+
     public BindingRuntimeTypes(final EffectiveModelContext schemaContext,
             final Map<Type, AugmentationSchemaNode> typeToAugmentation,
             final BiMap<Type, WithStatus> typeToDefiningSchema, final Multimap<Type, Type> choiceToCases,
@@ -67,6 +87,12 @@ public final class BindingRuntimeTypes implements EffectiveModelContextProvider,
         return Optional.ofNullable(typeToSchema.get(type));
     }
 
+    public Optional<Absolute> findSchemaNodeIdentifier(final Type type) {
+        final ImmutableMap<Type, Absolute> local = (ImmutableMap<Type, Absolute>) TYPE_TO_IDENTIFIER.getAcquire(this);
+        final Absolute existing = local.get(type);
+        return existing != null ? Optional.of(existing) : loadSchemaNodeIdentifier(local, type);
+    }
+
     public Optional<Type> findType(final WithStatus schema) {
         return Optional.ofNullable(typeToSchema.inverse().get(schema));
     }
@@ -88,4 +114,40 @@ public final class BindingRuntimeTypes implements EffectiveModelContextProvider,
                 .add("identities", identities)
                 .toString();
     }
+
+    private Optional<Absolute> loadSchemaNodeIdentifier(final ImmutableMap<Type, Absolute> local, final Type type) {
+        final WithStatus schema = typeToSchema.get(type);
+        if (!(schema instanceof SchemaNode)) {
+            return Optional.empty();
+        }
+
+        // TODO: do not rely on getPath() here
+        final Absolute created = Absolute.of(ImmutableList.copyOf(((SchemaNode) schema).getPath().getPathFromRoot()))
+                .intern();
+
+        ImmutableMap<Type, Absolute> prev = local;
+        while (true) {
+            // Compute next cache
+            final ImmutableMap<Type, Absolute> next =
+                    ImmutableMap.<Type, Absolute>builderWithExpectedSize(prev.size() + 1)
+                        .putAll(prev)
+                        .put(type, created).build();
+
+            final Object witness = TYPE_TO_IDENTIFIER.compareAndExchangeRelease(this, prev, next);
+            if (witness == prev) {
+                // Cache populated successfully, we are all done now
+                return Optional.of(created);
+            }
+
+            // Remember cache for next computation
+            prev = (ImmutableMap<Type, Absolute>) witness;
+            final Absolute raced = prev.get(type);
+            if (raced != null) {
+                // We have raced on this item, use it from cache
+                return Optional.of(raced);
+            }
+
+            // We have raced on a different item, loop around and repeat
+        }
+    }
 }
index b2281b2fa34d994a0587e1672c4ea50c14475b47..fd90b05864dff6c90f894c163627c01aaec85cec 100644 (file)
@@ -31,6 +31,7 @@ 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.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
 
 @Beta
 public abstract class ForwardingBindingRuntimeContext extends ForwardingObject implements BindingRuntimeContext {
@@ -62,6 +63,11 @@ public abstract class ForwardingBindingRuntimeContext extends ForwardingObject i
         return delegate().getActionDefinition(cls);
     }
 
+    @Override
+    public Absolute getActionIdentifier(final Class<? extends Action<?, ?, ?>> cls) {
+        return delegate().getActionIdentifier(cls);
+    }
+
     @Override
     public Entry<AugmentationIdentifier, AugmentationSchemaNode> getResolvedAugmentationSchema(
             final DataNodeContainer target, final Class<? extends Augmentation<?>> aug) {