package org.opendaylight.mdsal.binding.dom.adapter;
import static java.util.Objects.requireNonNull;
+import static org.opendaylight.mdsal.binding.dom.adapter.StaticConfiguration.ENABLE_CODEC_SHORTCUT;
import static org.opendaylight.yangtools.yang.common.YangConstants.operationInputQName;
import com.google.common.util.concurrent.FluentFuture;
getCodec().toLazyNormalizedNodeActionInput(type, inputName, input));
// Invocation returned a future we know about -- return that future instead
- if (future instanceof BindingRpcFutureAware) {
+ if (ENABLE_CODEC_SHORTCUT && future instanceof BindingRpcFutureAware) {
return ((BindingRpcFutureAware) future).getBindingFuture();
}
*/
package org.opendaylight.mdsal.binding.dom.adapter;
-import com.google.common.base.Preconditions;
+import static java.util.Objects.requireNonNull;
+import static org.opendaylight.mdsal.binding.dom.adapter.StaticConfiguration.ENABLE_CODEC_SHORTCUT;
+
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.util.concurrent.FluentFuture;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
public class BindingDOMRpcImplementationAdapter implements DOMRpcImplementation {
+ private static final Cache<Class<?>, RpcServiceInvoker> SERVICE_INVOKERS = CacheBuilder.newBuilder().weakKeys()
+ .build();
- private static final Cache<Class<?>, RpcServiceInvoker> SERVICE_INVOKERS
- = CacheBuilder.newBuilder().weakKeys().build();
// Default implementations are 0, we need to perform some translation, hence we have a slightly higher cost
private static final int COST = 1;
throw new IllegalArgumentException("Failed to create invokers for type " + type, e);
}
- this.codec = Preconditions.checkNotNull(codec);
- this.delegate = Preconditions.checkNotNull(delegate);
+ this.codec = requireNonNull(codec);
+ this.delegate = requireNonNull(delegate);
inputQname = YangConstants.operationInputQName(BindingReflections.getQNameModule(type)).intern();
}
}
private DataObject deserialize(final SchemaPath rpcPath, final NormalizedNode<?, ?> input) {
- if (input instanceof BindingDataAware) {
+ if (ENABLE_CODEC_SHORTCUT && input instanceof BindingDataAware) {
return ((BindingDataAware) input).bindingData();
}
final SchemaPath inputSchemaPath = rpcPath.createChild(inputQname);
*/
package org.opendaylight.mdsal.binding.dom.adapter;
+import static java.util.Objects.requireNonNull;
+import static org.opendaylight.mdsal.binding.dom.adapter.StaticConfiguration.ENABLE_CODEC_SHORTCUT;
+
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.util.concurrent.Futures;
RpcServiceAdapter(final Class<? extends RpcService> type, final BindingToNormalizedNodeCodec codec,
final DOMRpcService domService) {
- this.type = Preconditions.checkNotNull(type);
- this.codec = Preconditions.checkNotNull(codec);
- this.delegate = Preconditions.checkNotNull(domService);
+ this.type = requireNonNull(type);
+ this.codec = requireNonNull(codec);
+ this.delegate = requireNonNull(domService);
final ImmutableMap.Builder<Method, RpcInvocationStrategy> rpcBuilder = ImmutableMap.builder();
for (final Entry<Method, RpcDefinition> rpc : codec.getRpcMethodToSchema(type).entrySet()) {
rpcBuilder.put(rpc.getKey(), createStrategy(rpc.getKey(), rpc.getValue()));
ListenableFuture<RpcResult<?>> invoke0(final SchemaPath schemaPath, final ContainerNode input) {
final ListenableFuture<DOMRpcResult> result = delegate.invokeRpc(schemaPath, input);
- if (result instanceof BindingRpcFutureAware) {
+ if (ENABLE_CODEC_SHORTCUT && result instanceof BindingRpcFutureAware) {
return ((BindingRpcFutureAware) result).getBindingFuture();
}
--- /dev/null
+/*
+ * Copyright (c) 2018 Pantheon Technologies, s.r.o. 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.mdsal.binding.dom.adapter;
+
+import org.slf4j.LoggerFactory;
+
+/**
+ * Static JVM-wide configuration.
+ */
+final class StaticConfiguration {
+ /**
+ * When we are invoking a Binding-Aware RPC implementation, we can side-step translation through NormalizedNodes,
+ * which is an obvious performance win.
+ *
+ * <p>
+ * Unfortunately Binding Specification does not truthfully cover YANG semantics, in that grouping instantiations
+ * are not treated separately, which leads to constructs which are Binding-valid, but are actually YANG-invalid.
+ * These are usually easily rectified when identified, but the existence of this shortcut means that in single-node
+ * scenario we do not detect these mismatches and thus these issues remain unidentified -- only to break when
+ * in multi-node scenarios or the shortcut becomes otherwise ineffective.
+ *
+ * <p>
+ * We therefore allow the shortcuts to be globally disabled via a property, which is evaluated when this component
+ * loads.
+ */
+ static final boolean ENABLE_CODEC_SHORTCUT = !Boolean.getBoolean(
+ "org.opendaylight.mdsal.binding.dom.adapter.disableCodecShortcut");
+
+ static {
+ // Do not retain the logger
+ LoggerFactory.getLogger(StaticConfiguration.class).info("Binding-over-DOM codec shortcuts are {}",
+ ENABLE_CODEC_SHORTCUT ? "enabled" : "disabled");
+ }
+
+ private StaticConfiguration() {
+
+ }
+}