X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=binding%2Fmdsal-binding-dom-codec%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fmdsal%2Fbinding%2Fdom%2Fcodec%2Fimpl%2FDataContainerCodecPrototype.java;h=2a6abd3d7942472a169cdb8dfbac015303d0f5e2;hb=refs%2Fchanges%2F44%2F99844%2F1;hp=9fa864d825305eb60793ff2c5d7832f38ac44a58;hpb=c241dcfa5322ac10810a1068ccd2eb57f6f2dbb2;p=mdsal.git diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecPrototype.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecPrototype.java index 9fa864d825..2a6abd3d79 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecPrototype.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecPrototype.java @@ -8,8 +8,10 @@ package org.opendaylight.mdsal.binding.dom.codec.impl; import com.google.common.collect.Iterables; -import javax.annotation.concurrent.GuardedBy; -import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTreeNode.ChildAddressabilitySummary; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; +import org.eclipse.jdt.annotation.NonNull; +import org.opendaylight.mdsal.binding.dom.codec.api.BindingDataObjectCodecTreeNode.ChildAddressabilitySummary; import org.opendaylight.mdsal.binding.dom.codec.impl.NodeCodecContext.CodecContextFactory; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.DataRoot; @@ -19,15 +21,17 @@ import org.opendaylight.yangtools.yang.common.QNameModule; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; -import org.opendaylight.yangtools.yang.model.api.AnyDataSchemaNode; -import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode; +import org.opendaylight.yangtools.yang.model.api.AnydataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.AnyxmlSchemaNode; import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode; import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode; import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode; +import org.opendaylight.yangtools.yang.model.api.ContainerLike; import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; 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.EffectiveModelContext; import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; import org.opendaylight.yangtools.yang.model.api.NotificationDefinition; import org.opendaylight.yangtools.yang.model.api.SchemaContext; @@ -38,6 +42,17 @@ import org.slf4j.LoggerFactory; final class DataContainerCodecPrototype implements NodeContextSupplier { private static final Logger LOG = LoggerFactory.getLogger(DataContainerCodecPrototype.class); + private static final VarHandle INSTANCE; + + static { + try { + INSTANCE = MethodHandles.lookup().findVarHandle(DataContainerCodecPrototype.class, + "instance", DataContainerCodecContext.class); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new ExceptionInInitializerError(e); + } + } + private final T schema; private final QNameModule namespace; private final CodecContextFactory factory; @@ -45,7 +60,9 @@ final class DataContainerCodecPrototype implements NodeCon private final PathArgument yangArg; private final ChildAddressabilitySummary childAddressabilitySummary; - private volatile DataContainerCodecContext instance = null; + // Accessed via INSTANCE + @SuppressWarnings("unused") + private volatile DataContainerCodecContext instance; @SuppressWarnings("unchecked") private DataContainerCodecPrototype(final Class cls, final PathArgument arg, final T nodeSchema, @@ -83,7 +100,7 @@ final class DataContainerCodecPrototype implements NodeCon } else { haveAddressable = true; } - } else if (child instanceof AnyDataSchemaNode || child instanceof AnyXmlSchemaNode + } else if (child instanceof AnydataSchemaNode || child instanceof AnyxmlSchemaNode || child instanceof TypedDataSchemaNode) { haveUnaddressable = true; } else if (child instanceof ChoiceSchemaNode) { @@ -115,7 +132,7 @@ final class DataContainerCodecPrototype implements NodeCon } else if (nodeSchema instanceof ChoiceSchemaNode) { boolean haveAddressable = false; boolean haveUnaddressable = false; - for (CaseSchemaNode child : ((ChoiceSchemaNode) nodeSchema).getCases().values()) { + for (CaseSchemaNode child : ((ChoiceSchemaNode) nodeSchema).getCases()) { switch (computeChildAddressabilitySummary(child)) { case ADDRESSABLE: haveAddressable = true; @@ -143,28 +160,25 @@ final class DataContainerCodecPrototype implements NodeCon return ChildAddressabilitySummary.UNADDRESSABLE; } - static DataContainerCodecPrototype rootPrototype(final CodecContextFactory factory) { - final SchemaContext schema = factory.getRuntimeContext().getSchemaContext(); - final NodeIdentifier arg = NodeIdentifier.create(schema.getQName()); + static DataContainerCodecPrototype rootPrototype(final CodecContextFactory factory) { + final EffectiveModelContext schema = factory.getRuntimeContext().getEffectiveModelContext(); + final NodeIdentifier arg = NodeIdentifier.create(SchemaContext.NAME); return new DataContainerCodecPrototype<>(DataRoot.class, arg, schema, factory); } - @SuppressWarnings({ "unchecked", "rawtypes" }) static DataContainerCodecPrototype from(final Class cls, final T schema, final CodecContextFactory factory) { - return new DataContainerCodecPrototype(cls, NodeIdentifier.create(schema.getQName()), schema, factory); + return new DataContainerCodecPrototype<>(cls, NodeIdentifier.create(schema.getQName()), schema, factory); } - @SuppressWarnings({ "unchecked", "rawtypes" }) static DataContainerCodecPrototype from(final Item bindingArg, final T schema, final CodecContextFactory factory) { - return new DataContainerCodecPrototype(bindingArg, NodeIdentifier.create(schema.getQName()), schema, factory); + return new DataContainerCodecPrototype<>(bindingArg, NodeIdentifier.create(schema.getQName()), schema, factory); } - @SuppressWarnings({ "rawtypes", "unchecked" }) - static DataContainerCodecPrototype from(final Class augClass, final AugmentationIdentifier arg, - final AugmentationSchemaNode schema, final CodecContextFactory factory) { - return new DataContainerCodecPrototype(augClass, arg, schema, factory); + static DataContainerCodecPrototype from(final Class augClass, + final AugmentationIdentifier arg, final AugmentationSchemaNode schema, final CodecContextFactory factory) { + return new DataContainerCodecPrototype<>(augClass, arg, schema, factory); } static DataContainerCodecPrototype from(final Class augClass, @@ -173,7 +187,7 @@ final class DataContainerCodecPrototype implements NodeCon return new DataContainerCodecPrototype<>(augClass,arg, schema, factory); } - protected T getSchema() { + T getSchema() { return schema; } @@ -181,51 +195,48 @@ final class DataContainerCodecPrototype implements NodeCon return childAddressabilitySummary; } - protected QNameModule getNamespace() { + QNameModule getNamespace() { return namespace; } - protected CodecContextFactory getFactory() { + CodecContextFactory getFactory() { return factory; } - protected Class getBindingClass() { + Class getBindingClass() { return bindingArg.getType(); } - protected Item getBindingArg() { + Item getBindingArg() { return bindingArg; } - protected PathArgument getYangArg() { + PathArgument getYangArg() { return yangArg; } @Override - public DataContainerCodecContext get() { - DataContainerCodecContext tmp = instance; - if (tmp == null) { - synchronized (this) { - tmp = instance; - if (tmp == null) { - tmp = createInstance(); - instance = tmp; - } - } - } + public DataContainerCodecContext get() { + final DataContainerCodecContext existing = (DataContainerCodecContext) INSTANCE.getAcquire(this); + return existing != null ? existing : loadInstance(); + } - return tmp; + private @NonNull DataContainerCodecContext loadInstance() { + final var tmp = createInstance(); + final var witness = (DataContainerCodecContext) INSTANCE.compareAndExchangeRelease(this, null, tmp); + return witness == null ? tmp : witness; } - @GuardedBy("this") @SuppressWarnings({ "rawtypes", "unchecked" }) - private DataContainerCodecContext createInstance() { + // This method must allow concurrent loading, i.e. nothing in it may have effects outside of the loaded object + private @NonNull DataContainerCodecContext createInstance() { // FIXME: make protected abstract - if (schema instanceof ContainerSchemaNode) { + if (schema instanceof ContainerLike) { return new ContainerNodeCodecContext(this); } else if (schema instanceof ListSchemaNode) { - return Identifiable.class.isAssignableFrom(getBindingClass()) ? new KeyedListNodeCodecContext(this) - : new ListNodeCodecContext(this); + return Identifiable.class.isAssignableFrom(getBindingClass()) + ? KeyedListNodeCodecContext.create((DataContainerCodecPrototype) this) + : new ListNodeCodecContext(this); } else if (schema instanceof ChoiceSchemaNode) { return new ChoiceNodeCodecContext(this); } else if (schema instanceof AugmentationSchemaNode) { @@ -236,6 +247,7 @@ final class DataContainerCodecPrototype implements NodeCon throw new IllegalArgumentException("Unsupported type " + getBindingClass() + " " + schema); } + // FIXME: eliminate with above createInstance() item boolean isChoice() { return schema instanceof ChoiceSchemaNode; }