import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
import javax.annotation.concurrent.GuardedBy;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.WordUtils;
import org.opendaylight.controller.cluster.datastore.DatastoreContext.Builder;
+import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.distributed.datastore.provider.rev140612.DataStoreProperties;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.distributed.datastore.provider.rev140612.DataStorePropertiesContainer;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class DatastoreContextIntrospector {
private static final Logger LOG = LoggerFactory.getLogger(DatastoreContextIntrospector.class);
- private static final Map<String, Class<?>> DATA_STORE_PROP_TYPES = new HashMap<>();
+ private static final Map<String, Entry<Class<?>, Method>> DATA_STORE_PROP_INFO = new HashMap<>();
private static final Map<Class<?>, Constructor<?>> CONSTRUCTORS = new HashMap<>();
private static void introspectDataStoreProperties() throws IntrospectionException {
final BeanInfo beanInfo = Introspector.getBeanInfo(DataStoreProperties.class);
for (final PropertyDescriptor desc: beanInfo.getPropertyDescriptors()) {
- processDataStoreProperty(desc.getName(), desc.getPropertyType());
+ processDataStoreProperty(desc.getName(), desc.getPropertyType(), desc.getReadMethod());
}
// Getter methods that return Boolean and start with "is" instead of "get" aren't recognized as
final String methodName = desc.getName();
if (Boolean.class.equals(desc.getMethod().getReturnType()) && methodName.startsWith("is")) {
final String propertyName = WordUtils.uncapitalize(methodName.substring(2));
- processDataStoreProperty(propertyName, Boolean.class);
+ processDataStoreProperty(propertyName, Boolean.class, desc.getMethod());
}
}
}
* Processes a property defined on the DataStoreProperties interface.
*/
@SuppressWarnings("checkstyle:IllegalCatch")
- private static void processDataStoreProperty(final String name, final Class<?> propertyType) {
+ private static void processDataStoreProperty(final String name, final Class<?> propertyType, Method readMethod) {
Preconditions.checkArgument(BUILDER_SETTERS.containsKey(name), String.format(
"DataStoreProperties property \"%s\" does not have corresponding setter in DatastoreContext.Builder",
name));
try {
processPropertyType(propertyType);
- DATA_STORE_PROP_TYPES.put(name, propertyType);
+ DATA_STORE_PROP_INFO.put(name, new SimpleImmutableEntry<>(propertyType, readMethod));
} catch (final Exception e) {
LOG.error("Error finding constructor for type {}", propertyType, e);
}
@GuardedBy(value = "this")
private Map<String, Object> currentProperties;
- public DatastoreContextIntrospector(final DatastoreContext context) {
- this.context = context;
+ public DatastoreContextIntrospector(final DatastoreContext context,
+ final BindingNormalizedNodeSerializer bindingSerializer) {
+ final QName qname = BindingReflections.findQName(DataStorePropertiesContainer.class);
+ final DataStorePropertiesContainer defaultPropsContainer = (DataStorePropertiesContainer)
+ bindingSerializer.fromNormalizedNode(bindingSerializer.toYangInstanceIdentifier(
+ InstanceIdentifier.builder(DataStorePropertiesContainer.class).build()),
+ ImmutableNodes.containerNode(qname)).getValue();
+
+ final Builder builder = DatastoreContext.newBuilderFrom(context);
+ for (Entry<String, Entry<Class<?>, Method>> entry: DATA_STORE_PROP_INFO.entrySet()) {
+ Object value;
+ try {
+ value = entry.getValue().getValue().invoke(defaultPropsContainer);
+ } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+ LOG.error("Error obtaining default value for property {}", entry.getKey(), e);
+ value = null;
+ }
+
+ if (value != null) {
+ convertValueAndInvokeSetter(entry.getKey(), value, builder);
+ }
+ }
+
+ this.context = builder.build();
}
public synchronized DatastoreContext getContext() {
if (key.startsWith(shardNamePrefix)) {
key = key.replaceFirst(shardNamePrefix, "");
- convertValueAndInvokeSetter(key, value, builder);
+ convertValueAndInvokeSetter(key, value.toString(), builder);
}
}
key = key.replaceFirst(dataStoreTypePrefix, "");
}
- if (convertValueAndInvokeSetter(key, value, builder)) {
+ if (convertValueAndInvokeSetter(key, value.toString(), builder)) {
updated = true;
}
}
private Object convertValue(final String name, final Object from)
throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
- final Class<?> propertyType = DATA_STORE_PROP_TYPES.get(name);
- if (propertyType == null) {
+ final Entry<Class<?>, Method> propertyInfo = DATA_STORE_PROP_INFO.get(name);
+ if (propertyInfo == null) {
LOG.debug("Property not found for {}", name);
return null;
}
+ final Class<?> propertyType = propertyInfo.getKey();
+
LOG.debug("Type for property {}: {}, converting value {} ({})",
name, propertyType.getSimpleName(), from, from.getClass().getSimpleName());
// Recurse the chain of constructors depth-first to get the resulting value. Eg, if the
// property type is the yang-generated NonZeroUint32Type, it's constructor takes a Long so
// we have to first construct a Long instance from the input value.
- Object converted = constructorValueRecursively(propertyType, from.toString());
+ Object converted = constructorValueRecursively(propertyType, from);
// If the converted type is a yang-generated type, call the getter to obtain the actual value.
final Method getter = YANG_TYPE_GETTERS.get(converted.getClass());
LOG.trace("convertValueRecursively - toType: {}, fromValue {} ({})",
toType.getSimpleName(), fromValue, fromValue.getClass().getSimpleName());
+ if (toType.equals(fromValue.getClass())) {
+ return fromValue;
+ }
+
final Constructor<?> ctor = CONSTRUCTORS.get(toType);
LOG.trace("Found {}", ctor);
Object value = fromValue;
- // Since the original input type is a String, once we find a constructor that takes a String
- // argument, we're done recursing.
- if (!ctor.getParameterTypes()[0].equals(String.class)) {
+ // Once we find a constructor that takes the original type as an argument, we're done recursing.
+ if (!ctor.getParameterTypes()[0].equals(fromValue.getClass())) {
value = constructorValueRecursively(ctor.getParameterTypes()[0], fromValue);
}
--- /dev/null
+/*
+ * Copyright (c) 2018 Inocybe Technologies 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.controller.cluster.datastore;
+
+import com.google.common.annotations.VisibleForTesting;
+import javassist.ClassPool;
+import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
+import org.opendaylight.mdsal.binding.dom.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.mdsal.binding.dom.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.mdsal.binding.generator.api.ClassLoadingStrategy;
+import org.opendaylight.mdsal.binding.generator.util.BindingRuntimeContext;
+import org.opendaylight.mdsal.binding.generator.util.JavassistUtils;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.mdsal.dom.api.DOMSchemaService;
+
+/**
+ * Factory for creating DatastoreContextIntrospector instances.
+ *
+ * @author Thomas Pantelis
+ */
+public class DatastoreContextIntrospectorFactory {
+ private final DOMSchemaService schemaService;
+ private final ClassLoadingStrategy classLoadingStrategy;
+
+ public DatastoreContextIntrospectorFactory(DOMSchemaService schemaService,
+ ClassLoadingStrategy classLoadingStrategy) {
+ this.schemaService = schemaService;
+ this.classLoadingStrategy = classLoadingStrategy;
+ }
+
+ public DatastoreContextIntrospector newInstance(LogicalDatastoreType datastoreType) {
+ return new DatastoreContextIntrospector(DatastoreContext.newBuilder()
+ .logicalStoreType(datastoreType).tempFileDirectory("./data").build(), newBindingSerializer());
+ }
+
+ @VisibleForTesting
+ DatastoreContextIntrospector newInstance(DatastoreContext context) {
+ return new DatastoreContextIntrospector(context, newBindingSerializer());
+ }
+
+ private BindingNormalizedNodeSerializer newBindingSerializer() {
+ BindingNormalizedNodeCodecRegistry codecRegistry = new BindingNormalizedNodeCodecRegistry(
+ StreamWriterGenerator.create(JavassistUtils.forClassPool(ClassPool.getDefault())));
+ codecRegistry.onBindingRuntimeContextUpdated(BindingRuntimeContext.create(classLoadingStrategy,
+ schemaService.getGlobalContext()));
+ return codecRegistry;
+ }
+}
package org.opendaylight.controller.config.yang.config.distributed_datastore_provider;
-import org.opendaylight.controller.cluster.datastore.DatastoreContext;
import org.opendaylight.controller.cluster.datastore.DistributedDataStoreInterface;
import org.opendaylight.controller.cluster.datastore.compat.LegacyDOMStoreAdapter;
import org.opendaylight.controller.config.api.DependencyResolver;
import org.opendaylight.controller.config.api.ModuleIdentifier;
import org.opendaylight.controller.config.api.osgi.WaitingServiceTracker;
-import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
import org.osgi.framework.BundleContext;
@Deprecated
};
}
- public static DatastoreContext newDatastoreContext() {
- return newDatastoreContext(null);
- }
-
- private static DatastoreContext newDatastoreContext(final ConfigProperties inProps) {
- ConfigProperties props = inProps;
- if (props == null) {
- props = new ConfigProperties();
- }
-
- return DatastoreContext.newBuilder()
- .logicalStoreType(LogicalDatastoreType.CONFIGURATION)
- .tempFileDirectory("./data")
- .fileBackedStreamingThresholdInMegabytes(props.getFileBackedStreamingThresholdInMegabytes()
- .getValue().intValue())
- .maxShardDataChangeExecutorPoolSize(props.getMaxShardDataChangeExecutorPoolSize().getValue().intValue())
- .maxShardDataChangeExecutorQueueSize(props.getMaxShardDataChangeExecutorQueueSize()
- .getValue().intValue())
- .maxShardDataChangeListenerQueueSize(props.getMaxShardDataChangeListenerQueueSize()
- .getValue().intValue())
- .maxShardDataStoreExecutorQueueSize(props.getMaxShardDataStoreExecutorQueueSize().getValue().intValue())
- .shardTransactionIdleTimeoutInMinutes(props.getShardTransactionIdleTimeoutInMinutes().getValue())
- .operationTimeoutInSeconds(props.getOperationTimeoutInSeconds().getValue())
- .shardJournalRecoveryLogBatchSize(props.getShardJournalRecoveryLogBatchSize()
- .getValue().intValue())
- .shardSnapshotBatchCount(props.getShardSnapshotBatchCount().getValue().intValue())
- .shardSnapshotDataThresholdPercentage(props.getShardSnapshotDataThresholdPercentage()
- .getValue().intValue())
- .shardHeartbeatIntervalInMillis(props.getShardHeartbeatIntervalInMillis().getValue())
- .shardInitializationTimeoutInSeconds(props.getShardInitializationTimeoutInSeconds().getValue())
- .shardLeaderElectionTimeoutInSeconds(props.getShardLeaderElectionTimeoutInSeconds().getValue())
- .shardTransactionCommitTimeoutInSeconds(
- props.getShardTransactionCommitTimeoutInSeconds().getValue().intValue())
- .shardTransactionCommitQueueCapacity(
- props.getShardTransactionCommitQueueCapacity().getValue().intValue())
- .persistent(props.getPersistent().booleanValue())
- .shardIsolatedLeaderCheckIntervalInMillis(
- props.getShardIsolatedLeaderCheckIntervalInMillis().getValue())
- .shardElectionTimeoutFactor(props.getShardElectionTimeoutFactor().getValue())
- .transactionCreationInitialRateLimit(props.getTransactionCreationInitialRateLimit().getValue())
- .shardBatchedModificationCount(props.getShardBatchedModificationCount().getValue().intValue())
- .shardCommitQueueExpiryTimeoutInSeconds(
- props.getShardCommitQueueExpiryTimeoutInSeconds().getValue().intValue())
- .transactionDebugContextEnabled(props.getTransactionDebugContextEnabled())
- .customRaftPolicyImplementation(props.getCustomRaftPolicyImplementation())
- .maximumMessageSliceSize(props.getMaximumMessageSliceSize().getValue().intValue())
- .useTellBasedProtocol(props.getUseTellBasedProtocol())
- .syncIndexThreshold(props.getSyncIndexThreshold().getValue())
- .backendAlivenessTimerIntervalInSeconds(props.getBackendAlivenessTimerIntervalInSeconds().getValue())
- .frontendRequestTimeoutInSeconds(props.getFrontendRequestTimeoutInSeconds().getValue())
- .frontendNoProgressTimeoutInSeconds(props.getFrontendNoProgressTimeoutInSeconds().getValue())
- .build();
- }
-
public void setBundleContext(final BundleContext bundleContext) {
this.bundleContext = bundleContext;
}
package org.opendaylight.controller.config.yang.config.distributed_datastore_provider;
-import org.opendaylight.controller.cluster.datastore.DatastoreContext;
import org.opendaylight.controller.cluster.datastore.DistributedDataStoreInterface;
import org.opendaylight.controller.cluster.datastore.compat.LegacyDOMStoreAdapter;
import org.opendaylight.controller.config.api.DependencyResolver;
import org.opendaylight.controller.config.api.ModuleIdentifier;
import org.opendaylight.controller.config.api.osgi.WaitingServiceTracker;
-import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
import org.osgi.framework.BundleContext;
@Deprecated
};
}
- public static DatastoreContext newDatastoreContext() {
- return newDatastoreContext(null);
- }
-
- private static DatastoreContext newDatastoreContext(final OperationalProperties inProps) {
- OperationalProperties props = inProps;
- if (props == null) {
- props = new OperationalProperties();
- }
-
- return DatastoreContext.newBuilder()
- .logicalStoreType(LogicalDatastoreType.OPERATIONAL)
- .tempFileDirectory("./data")
- .fileBackedStreamingThresholdInMegabytes(props.getFileBackedStreamingThresholdInMegabytes()
- .getValue().intValue())
- .maxShardDataChangeExecutorPoolSize(props.getMaxShardDataChangeExecutorPoolSize().getValue().intValue())
- .maxShardDataChangeExecutorQueueSize(props.getMaxShardDataChangeExecutorQueueSize()
- .getValue().intValue())
- .maxShardDataChangeListenerQueueSize(props.getMaxShardDataChangeListenerQueueSize()
- .getValue().intValue())
- .maxShardDataStoreExecutorQueueSize(props.getMaxShardDataStoreExecutorQueueSize().getValue().intValue())
- .shardTransactionIdleTimeoutInMinutes(props.getShardTransactionIdleTimeoutInMinutes().getValue())
- .operationTimeoutInSeconds(props.getOperationTimeoutInSeconds().getValue())
- .shardJournalRecoveryLogBatchSize(props.getShardJournalRecoveryLogBatchSize()
- .getValue().intValue())
- .shardSnapshotBatchCount(props.getShardSnapshotBatchCount().getValue().intValue())
- .shardSnapshotDataThresholdPercentage(props.getShardSnapshotDataThresholdPercentage()
- .getValue().intValue())
- .shardHeartbeatIntervalInMillis(props.getShardHeartbeatIntervalInMillis().getValue())
- .shardInitializationTimeoutInSeconds(props.getShardInitializationTimeoutInSeconds().getValue())
- .shardLeaderElectionTimeoutInSeconds(props.getShardLeaderElectionTimeoutInSeconds().getValue())
- .shardTransactionCommitTimeoutInSeconds(
- props.getShardTransactionCommitTimeoutInSeconds().getValue().intValue())
- .shardTransactionCommitQueueCapacity(
- props.getShardTransactionCommitQueueCapacity().getValue().intValue())
- .persistent(props.getPersistent().booleanValue())
- .shardIsolatedLeaderCheckIntervalInMillis(
- props.getShardIsolatedLeaderCheckIntervalInMillis().getValue())
- .shardElectionTimeoutFactor(props.getShardElectionTimeoutFactor().getValue())
- .transactionCreationInitialRateLimit(props.getTransactionCreationInitialRateLimit().getValue())
- .shardBatchedModificationCount(props.getShardBatchedModificationCount().getValue().intValue())
- .shardCommitQueueExpiryTimeoutInSeconds(
- props.getShardCommitQueueExpiryTimeoutInSeconds().getValue().intValue())
- .transactionDebugContextEnabled(props.getTransactionDebugContextEnabled())
- .customRaftPolicyImplementation(props.getCustomRaftPolicyImplementation())
- .maximumMessageSliceSize(props.getMaximumMessageSliceSize().getValue().intValue())
- .useTellBasedProtocol(props.getUseTellBasedProtocol())
- .syncIndexThreshold(props.getSyncIndexThreshold().getValue())
- .backendAlivenessTimerIntervalInSeconds(props.getBackendAlivenessTimerIntervalInSeconds().getValue())
- .frontendRequestTimeoutInSeconds(props.getFrontendRequestTimeoutInSeconds().getValue())
- .frontendNoProgressTimeoutInSeconds(props.getFrontendNoProgressTimeoutInSeconds().getValue())
- .build();
- }
-
public void setBundleContext(final BundleContext bundleContext) {
this.bundleContext = bundleContext;
}
<odl:static-reference id="schemaService" interface="org.opendaylight.mdsal.dom.api.DOMSchemaService" />
+ <reference id="classLoadingStrategy" interface="org.opendaylight.mdsal.binding.generator.api.ClassLoadingStrategy" />
+
<!-- ActorSystemProvider -->
<bean id="bundleClassLoader" class="org.opendaylight.controller.config.yang.config.actor_system_provider.impl.factory.osgi.BundleClassLoaderFactory"
<argument value="./clustered-datastore-restore"/>
</bean>
- <bean id="configDatastoreContext" class="org.opendaylight.controller.config.yang.config.distributed_datastore_provider.DistributedConfigDataStoreProviderModule"
- factory-method="newDatastoreContext" />
+ <bean id="introspectorFactory" class="org.opendaylight.controller.cluster.datastore.DatastoreContextIntrospectorFactory">
+ <argument ref="schemaService"/>
+ <argument ref="classLoadingStrategy"/>
+ </bean>
- <bean id="introspectorConfig" class="org.opendaylight.controller.cluster.datastore.DatastoreContextIntrospector">
- <argument ref="configDatastoreContext"/>
+ <bean id="introspectorConfig" factory-ref="introspectorFactory" factory-method="newInstance">
+ <argument type="org.opendaylight.mdsal.common.api.LogicalDatastoreType" value="CONFIGURATION"/>
</bean>
<bean id="updaterConfig" class="org.opendaylight.controller.cluster.datastore.DatastoreContextPropertiesUpdater">
<bean id="configDatastore" class="org.opendaylight.controller.cluster.datastore.DistributedDataStoreFactory"
factory-method="createInstance" destroy-method="close">
<argument ref="schemaService"/>
- <argument ref="configDatastoreContext"/>
+ <argument>
+ <bean factory-ref="introspectorConfig" factory-method="getContext" />
+ </argument>
<argument ref="datastoreSnapshotRestore"/>
<argument ref="actorSystemProvider"/>
<argument ref="introspectorConfig"/>
<argument ref="fileModuleShardConfigProvider"/>
</bean>
- <bean id="operDatastoreContext" class="org.opendaylight.controller.config.yang.config.distributed_datastore_provider.DistributedOperationalDataStoreProviderModule"
- factory-method="newDatastoreContext" />
-
- <bean id="introspectorOper" class="org.opendaylight.controller.cluster.datastore.DatastoreContextIntrospector">
- <argument ref="operDatastoreContext"/>
+ <bean id="introspectorOper" factory-ref="introspectorFactory" factory-method="newInstance">
+ <argument type="org.opendaylight.mdsal.common.api.LogicalDatastoreType" value="OPERATIONAL"/>
</bean>
<bean id="updaterOper" class="org.opendaylight.controller.cluster.datastore.DatastoreContextPropertiesUpdater">
<bean id="operDatastore" class="org.opendaylight.controller.cluster.datastore.DistributedDataStoreFactory"
factory-method="createInstance" destroy-method="close">
<argument ref="schemaService"/>
- <argument ref="operDatastoreContext"/>
+ <argument>
+ <bean factory-ref="introspectorOper" factory-method="getContext" />
+ </argument>
<argument ref="datastoreSnapshotRestore"/>
<argument ref="actorSystemProvider"/>
<argument ref="introspectorOper"/>
}
}
+ container data-store-properties-container {
+ uses data-store-properties;
+ }
+
// Augments the 'configuration' choice node under modules/module.
augment "/config:modules/config:module/config:configuration" {
case distributed-config-datastore-provider {
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.opendaylight.controller.cluster.datastore.DatastoreContextIntrospectorTest.INTROSPECTOR_FACTORY;
+import static org.opendaylight.mdsal.common.api.LogicalDatastoreType.CONFIGURATION;
import java.lang.reflect.Field;
import java.util.HashMap;
public void updateOnConstructionTest() throws Exception {
final Map<String, Object> properties = new HashMap<>();
properties.put("shardTransactionIdleTimeoutInMinutes", 10);
- final DatastoreContext datastoreContext = DatastoreContext.newBuilder().build();
- final DatastoreContextIntrospector introspector = new DatastoreContextIntrospector(datastoreContext);
+ final DatastoreContextIntrospector introspector = INTROSPECTOR_FACTORY.newInstance(CONFIGURATION);
final DatastoreContextPropertiesUpdater updater = new DatastoreContextPropertiesUpdater(introspector,
properties);
public void onUpdateTest() throws Exception {
final Map<String, Object> properties = new HashMap<>();
properties.put("shardTransactionIdleTimeoutInMinutes", 10);
- final DatastoreContext datastoreContext = DatastoreContext.newBuilder().build();
- assertNotNull(datastoreContext);
- final DatastoreContextIntrospector introspector = new DatastoreContextIntrospector(datastoreContext);
+
+ final DatastoreContextIntrospector introspector = INTROSPECTOR_FACTORY.newInstance(CONFIGURATION);
assertNotNull(introspector);
final DatastoreContextPropertiesUpdater updater = new DatastoreContextPropertiesUpdater(introspector,
properties);
final Map<String, Object> properties = new HashMap<>();
properties.put("shardTransactionIdleTimeoutInMinutes", 10);
- final DatastoreContext datastoreContext = DatastoreContext.newBuilder().build();
- final DatastoreContextIntrospector introspector = new DatastoreContextIntrospector(datastoreContext);
+ final DatastoreContextIntrospector introspector = INTROSPECTOR_FACTORY.newInstance(CONFIGURATION);
final DatastoreContextPropertiesUpdater updater = new DatastoreContextPropertiesUpdater(introspector,
properties);
final DummyListenerImpl dummyListener = new DummyListenerImpl();
package org.opendaylight.controller.cluster.datastore;
import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import static org.opendaylight.controller.cluster.datastore.DatastoreContext.DEFAULT_HEARTBEAT_INTERVAL_IN_MILLIS;
import static org.opendaylight.controller.cluster.datastore.DatastoreContext.DEFAULT_OPERATION_TIMEOUT_IN_MS;
import static org.opendaylight.controller.cluster.datastore.DatastoreContext.DEFAULT_SHARD_INITIALIZATION_TIMEOUT;
import static org.opendaylight.controller.cluster.datastore.DatastoreContext.DEFAULT_SHARD_SNAPSHOT_DATA_THRESHOLD_PERCENTAGE;
import static org.opendaylight.controller.cluster.datastore.DatastoreContext.DEFAULT_SHARD_TRANSACTION_IDLE_TIMEOUT;
import static org.opendaylight.controller.cluster.datastore.DatastoreContext.DEFAULT_SHARD_TX_COMMIT_TIMEOUT_IN_SECONDS;
+import static org.opendaylight.mdsal.common.api.LogicalDatastoreType.CONFIGURATION;
+import static org.opendaylight.mdsal.common.api.LogicalDatastoreType.OPERATIONAL;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import org.junit.Test;
-import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.mdsal.binding.generator.impl.GeneratedClassLoadingStrategy;
+import org.opendaylight.mdsal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.mdsal.dom.api.DOMSchemaService;
import org.opendaylight.mdsal.dom.store.inmemory.InMemoryDOMDataStoreConfigProperties;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.distributed.datastore.provider.rev140612.DataStorePropertiesContainer;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
/**
* Unit tests for DatastoreContextIntrospector.
*
* @author Thomas Pantelis
*/
+@SuppressWarnings("checkstyle:IllegalCatch")
public class DatastoreContextIntrospectorTest {
+ static SchemaContext SCHEMA_CONTEXT;
+ static DatastoreContextIntrospectorFactory INTROSPECTOR_FACTORY;
+
+ static {
+ final ModuleInfoBackedContext moduleContext = ModuleInfoBackedContext.create();
+ try {
+ moduleContext.addModuleInfos(Arrays.asList(
+ BindingReflections.getModuleInfo(DataStorePropertiesContainer.class)));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ SCHEMA_CONTEXT = moduleContext.tryToCreateSchemaContext().get();
+
+ DOMSchemaService mockSchemaService = mock(DOMSchemaService.class);
+ doReturn(SCHEMA_CONTEXT).when(mockSchemaService).getGlobalContext();
+ INTROSPECTOR_FACTORY = new DatastoreContextIntrospectorFactory(mockSchemaService,
+ GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy());
+ }
+
+ @Test
+ public void testYangDefaults() {
+ final DatastoreContextIntrospector introspector = INTROSPECTOR_FACTORY.newInstance(
+ DatastoreContext.newBuilder().shardBatchedModificationCount(2)
+ .transactionDebugContextEnabled(true).build());
+ DatastoreContext context = introspector.getContext();
+
+ assertEquals(1000, context.getShardBatchedModificationCount());
+ assertEquals(false, context.isTransactionDebugContextEnabled());
+ }
+
@Test
public void testUpdate() {
- DatastoreContext context = DatastoreContext.newBuilder()
- .logicalStoreType(LogicalDatastoreType.OPERATIONAL).build();
- final DatastoreContextIntrospector introspector = new DatastoreContextIntrospector(context);
+ final DatastoreContextIntrospector introspector = INTROSPECTOR_FACTORY.newInstance(OPERATIONAL);
final Map<String, Object> properties = new HashMap<>();
properties.put("shard-transaction-idle-timeout-in-minutes", "31");
boolean updated = introspector.update(properties);
assertEquals("updated", true, updated);
- context = introspector.getContext();
+ DatastoreContext context = introspector.getContext();
assertEquals(31, context.getShardTransactionIdleTimeout().toMinutes());
assertEquals(26000, context.getOperationTimeoutInMillis());
@Test
public void testUpdateWithInvalidValues() {
- DatastoreContext context = DatastoreContext.newBuilder()
- .logicalStoreType(LogicalDatastoreType.OPERATIONAL).build();
- final DatastoreContextIntrospector introspector = new DatastoreContextIntrospector(context);
+ final DatastoreContextIntrospector introspector = INTROSPECTOR_FACTORY.newInstance(OPERATIONAL);
final Map<String, Object> properties = new HashMap<>();
properties.put("shard-transaction-idle-timeout-in-minutes", "0"); // bad - must be > 0
final boolean updated = introspector.update(properties);
assertEquals("updated", true, updated);
- context = introspector.getContext();
+ DatastoreContext context = introspector.getContext();
assertEquals(DEFAULT_SHARD_TRANSACTION_IDLE_TIMEOUT, context.getShardTransactionIdleTimeout());
assertEquals(199, context.getShardRaftConfig().getJournalRecoveryLogBatchSize());
properties.put("persistent", "false"); // global setting
properties.put("operational.Persistent", "true"); // operational override
- DatastoreContext operContext = DatastoreContext.newBuilder()
- .logicalStoreType(LogicalDatastoreType.OPERATIONAL).build();
- final DatastoreContextIntrospector operIntrospector = new DatastoreContextIntrospector(operContext);
+ final DatastoreContextIntrospector operIntrospector = INTROSPECTOR_FACTORY.newInstance(OPERATIONAL);
boolean updated = operIntrospector.update(properties);
assertEquals("updated", true, updated);
- operContext = operIntrospector.getContext();
+ DatastoreContext operContext = operIntrospector.getContext();
assertEquals(33, operContext.getShardTransactionIdleTimeout().toMinutes());
assertEquals(true, operContext.isPersistent());
assertEquals(333, operContext.getDataStoreProperties().getMaxDataChangeExecutorPoolSize());
- DatastoreContext configContext = DatastoreContext.newBuilder()
- .logicalStoreType(LogicalDatastoreType.CONFIGURATION).build();
- final DatastoreContextIntrospector configIntrospector = new DatastoreContextIntrospector(configContext);
+ final DatastoreContextIntrospector configIntrospector = INTROSPECTOR_FACTORY.newInstance(CONFIGURATION);
updated = configIntrospector.update(properties);
assertEquals("updated", true, updated);
- configContext = configIntrospector.getContext();
+ DatastoreContext configContext = configIntrospector.getContext();
assertEquals(44, configContext.getShardTransactionIdleTimeout().toMinutes());
assertEquals(false, configContext.isPersistent());
properties.put("config.shard-transaction-idle-timeout-in-minutes", "44"); // config override
properties.put("topology.shard-transaction-idle-timeout-in-minutes", "55"); // global shard override
- DatastoreContext operContext = DatastoreContext.newBuilder()
- .logicalStoreType(LogicalDatastoreType.OPERATIONAL).build();
- final DatastoreContextIntrospector operIntrospector = new DatastoreContextIntrospector(operContext);
+ final DatastoreContextIntrospector operIntrospector = INTROSPECTOR_FACTORY.newInstance(OPERATIONAL);
DatastoreContext shardContext = operIntrospector.newContextFactory().getShardDatastoreContext("topology");
assertEquals(10, shardContext.getShardTransactionIdleTimeout().toMinutes());
operIntrospector.update(properties);
- operContext = operIntrospector.getContext();
+ DatastoreContext operContext = operIntrospector.getContext();
assertEquals(33, operContext.getShardTransactionIdleTimeout().toMinutes());
shardContext = operIntrospector.newContextFactory().getShardDatastoreContext("topology");
assertEquals(55, shardContext.getShardTransactionIdleTimeout().toMinutes());
- DatastoreContext configContext = DatastoreContext.newBuilder()
- .logicalStoreType(LogicalDatastoreType.CONFIGURATION).build();
- final DatastoreContextIntrospector configIntrospector = new DatastoreContextIntrospector(configContext);
+ final DatastoreContextIntrospector configIntrospector = INTROSPECTOR_FACTORY.newInstance(CONFIGURATION);
configIntrospector.update(properties);
- configContext = configIntrospector.getContext();
+ DatastoreContext configContext = configIntrospector.getContext();
assertEquals(44, configContext.getShardTransactionIdleTimeout().toMinutes());
shardContext = configIntrospector.newContextFactory().getShardDatastoreContext("topology");