* Base implementation of a distributed DOMStore.
*/
public abstract class AbstractDataStore implements DistributedDataStoreInterface, SchemaContextListener,
- DatastoreContextConfigAdminOverlay.Listener, DOMStoreTreeChangePublisher,
+ DatastoreContextPropertiesUpdater.Listener, DOMStoreTreeChangePublisher,
DOMDataTreeCommitCohortRegistry, AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(AbstractDataStore.class);
+++ /dev/null
-/*
- * Copyright (c) 2015 Brocade Communications Systems, Inc. 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 java.io.IOException;
-import java.util.Dictionary;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.cm.Configuration;
-import org.osgi.service.cm.ConfigurationAdmin;
-import org.osgi.service.cm.ConfigurationEvent;
-import org.osgi.service.cm.ConfigurationListener;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Class that overlays DatastoreContext settings with settings obtained from an OSGi Config Admin
- * service.
- *
- * @author Thomas Pantelis
- */
-public class DatastoreContextConfigAdminOverlay implements AutoCloseable {
- public static final String CONFIG_ID = "org.opendaylight.controller.cluster.datastore";
-
- public interface Listener {
- void onDatastoreContextUpdated(DatastoreContextFactory contextFactory);
- }
-
- private static final Logger LOG = LoggerFactory.getLogger(DatastoreContextConfigAdminOverlay.class);
-
- private final DatastoreContextIntrospector introspector;
- private final BundleContext bundleContext;
- private ServiceRegistration<?> configListenerServiceRef;
- private Listener listener;
-
- public DatastoreContextConfigAdminOverlay(DatastoreContextIntrospector introspector,
- BundleContext bundleContext) {
- this.introspector = introspector;
- this.bundleContext = bundleContext;
-
- ServiceReference<ConfigurationAdmin> configAdminServiceReference =
- bundleContext.getServiceReference(ConfigurationAdmin.class);
- if (configAdminServiceReference == null) {
- LOG.warn("No ConfigurationAdmin service found");
- } else {
- overlaySettings(configAdminServiceReference);
-
- configListenerServiceRef = bundleContext.registerService(ConfigurationListener.class.getName(),
- new DatastoreConfigurationListener(), null);
- }
- }
-
- public void setListener(Listener listener) {
- this.listener = listener;
- }
-
- @SuppressWarnings({"checkstyle:IllegalCatch",
- "squid:S1166" /* Exception handlers should preserve the original exception */})
- private void overlaySettings(ServiceReference<ConfigurationAdmin> configAdminServiceReference) {
- try {
- ConfigurationAdmin configAdmin = bundleContext.getService(configAdminServiceReference);
-
- Configuration config = configAdmin.getConfiguration(CONFIG_ID);
- if (config != null) {
- Dictionary<String, Object> properties = config.getProperties();
-
- LOG.debug("Overlaying settings: {}", properties);
-
- if (introspector.update(properties) && listener != null) {
- listener.onDatastoreContextUpdated(introspector.newContextFactory());
- }
- } else {
- LOG.debug("No Configuration found for {}", CONFIG_ID);
- }
- } catch (IOException e) {
- LOG.error("Error obtaining Configuration for pid {}", CONFIG_ID, e);
- } catch (IllegalStateException e) {
- // Ignore - indicates the bundleContext has been closed.
- } finally {
- try {
- bundleContext.ungetService(configAdminServiceReference);
- } catch (Exception e) {
- LOG.debug("Error from ungetService", e);
- }
- }
- }
-
- @Override
- public void close() {
- listener = null;
-
- if (configListenerServiceRef != null) {
- configListenerServiceRef.unregister();
- }
- }
-
- private class DatastoreConfigurationListener implements ConfigurationListener {
- @Override
- public void configurationEvent(ConfigurationEvent event) {
- if (CONFIG_ID.equals(event.getPid()) && event.getType() == ConfigurationEvent.CM_UPDATED) {
- LOG.debug("configurationEvent: config {} was updated", CONFIG_ID);
- overlaySettings(event.getReference());
- }
- }
- }
-}
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.Dictionary;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
introspectDatastoreContextBuilder();
introspectDataStoreProperties();
introspectPrimitiveTypes();
- } catch (IntrospectionException e) {
+ } catch (final IntrospectionException e) {
LOG.error("Error initializing DatastoreContextIntrospector", e);
}
}
// Disables "Either log or rethrow this exception" sonar warning
@SuppressWarnings("squid:S1166")
private static void introspectPrimitiveTypes() {
- Set<Class<?>> primitives = ImmutableSet.<Class<?>>builder().addAll(
+ final Set<Class<?>> primitives = ImmutableSet.<Class<?>>builder().addAll(
Primitives.allWrapperTypes()).add(String.class).build();
- for (Class<?> primitive: primitives) {
+ for (final Class<?> primitive: primitives) {
try {
processPropertyType(primitive);
- } catch (NoSuchMethodException e) {
+ } catch (final NoSuchMethodException e) {
// Ignore primitives that can't be constructed from a String, eg Character and Void.
} catch (SecurityException | IntrospectionException e) {
LOG.error("Error introspect primitive type {}", primitive, e);
* the methods that return Builder.
*/
private static void introspectDatastoreContextBuilder() {
- for (Method method: Builder.class.getMethods()) {
+ for (final Method method: Builder.class.getMethods()) {
if (Builder.class.equals(method.getReturnType())) {
BUILDER_SETTERS.put(method.getName(), method);
}
* the appropriate constructor that we will use.
*/
private static void introspectDataStoreProperties() throws IntrospectionException {
- BeanInfo beanInfo = Introspector.getBeanInfo(DataStoreProperties.class);
- for (PropertyDescriptor desc: beanInfo.getPropertyDescriptors()) {
+ final BeanInfo beanInfo = Introspector.getBeanInfo(DataStoreProperties.class);
+ for (final PropertyDescriptor desc: beanInfo.getPropertyDescriptors()) {
processDataStoreProperty(desc.getName(), desc.getPropertyType());
}
// properties and thus aren't returned from getPropertyDescriptors. A getter starting with
// "is" is only supported if it returns primitive boolean. So we'll check for these via
// getMethodDescriptors.
- for (MethodDescriptor desc: beanInfo.getMethodDescriptors()) {
- String methodName = desc.getName();
+ for (final MethodDescriptor desc: beanInfo.getMethodDescriptors()) {
+ final String methodName = desc.getName();
if (Boolean.class.equals(desc.getMethod().getReturnType()) && methodName.startsWith("is")) {
- String propertyName = WordUtils.uncapitalize(methodName.substring(2));
+ final String propertyName = WordUtils.uncapitalize(methodName.substring(2));
processDataStoreProperty(propertyName, Boolean.class);
}
}
* Processes a property defined on the DataStoreProperties interface.
*/
@SuppressWarnings("checkstyle:IllegalCatch")
- private static void processDataStoreProperty(String name, Class<?> propertyType) {
+ private static void processDataStoreProperty(final String name, final Class<?> propertyType) {
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);
- } catch (Exception e) {
+ } catch (final Exception e) {
LOG.error("Error finding constructor for type {}", propertyType, e);
}
}
* Finds the appropriate constructor for the specified type that we will use to construct
* instances.
*/
- private static void processPropertyType(Class<?> propertyType) throws NoSuchMethodException, SecurityException,
- IntrospectionException {
- Class<?> wrappedType = Primitives.wrap(propertyType);
+ private static void processPropertyType(final Class<?> propertyType)
+ throws NoSuchMethodException, SecurityException, IntrospectionException {
+ final Class<?> wrappedType = Primitives.wrap(propertyType);
if (CONSTRUCTORS.containsKey(wrappedType)) {
return;
}
// primitive as the only argument. This will be used to construct instances to perform
// validation (eg range checking). The yang-generated types have a couple single-argument
// constructors but the one we want has the bean ConstructorProperties annotation.
- for (Constructor<?> ctor: propertyType.getConstructors()) {
- ConstructorProperties ctorPropsAnnotation = ctor.getAnnotation(ConstructorProperties.class);
+ for (final Constructor<?> ctor: propertyType.getConstructors()) {
+ final ConstructorProperties ctorPropsAnnotation = ctor.getAnnotation(ConstructorProperties.class);
if (ctor.getParameterTypes().length == 1 && ctorPropsAnnotation != null) {
findYangTypeGetter(propertyType, ctorPropsAnnotation.value()[0]);
CONSTRUCTORS.put(propertyType, ctor);
/**
* Finds the getter method on a yang-generated type for the specified property name.
*/
- private static void findYangTypeGetter(Class<?> type, String propertyName) throws IntrospectionException {
- for (PropertyDescriptor desc: Introspector.getBeanInfo(type).getPropertyDescriptors()) {
+ private static void findYangTypeGetter(final Class<?> type, final String propertyName)
+ throws IntrospectionException {
+ for (final PropertyDescriptor desc: Introspector.getBeanInfo(type).getPropertyDescriptors()) {
if (desc.getName().equals(propertyName)) {
YANG_TYPE_GETTERS.put(type, desc.getReadMethod());
return;
@GuardedBy(value = "this")
private Map<String, Object> currentProperties;
- public DatastoreContextIntrospector(DatastoreContext context) {
+ public DatastoreContextIntrospector(final DatastoreContext context) {
this.context = context;
}
return new DatastoreContextFactory(this);
}
- public synchronized DatastoreContext getShardDatastoreContext(String forShardName) {
+ public synchronized DatastoreContext getShardDatastoreContext(final String forShardName) {
if (currentProperties == null) {
return context;
}
- Builder builder = DatastoreContext.newBuilderFrom(context);
- String dataStoreTypePrefix = context.getDataStoreName() + '.';
+ final Builder builder = DatastoreContext.newBuilderFrom(context);
+ final String dataStoreTypePrefix = context.getDataStoreName() + '.';
final String shardNamePrefix = forShardName + '.';
- List<String> keys = getSortedKeysByDatastoreType(currentProperties.keySet(), dataStoreTypePrefix);
+ final List<String> keys = getSortedKeysByDatastoreType(currentProperties.keySet(), dataStoreTypePrefix);
for (String key: keys) {
- Object value = currentProperties.get(key);
+ final Object value = currentProperties.get(key);
if (key.startsWith(dataStoreTypePrefix)) {
key = key.replaceFirst(dataStoreTypePrefix, "");
}
* @param properties the properties to apply
* @return true if the cached DatastoreContext was updated, false otherwise.
*/
- public synchronized boolean update(Dictionary<String, Object> properties) {
+ public synchronized boolean update(final Map<String, Object> properties) {
currentProperties = null;
if (properties == null || properties.isEmpty()) {
return false;
LOG.debug("In update: properties: {}", properties);
- ImmutableMap.Builder<String, Object> mapBuilder = ImmutableMap.<String, Object>builder();
+ final ImmutableMap.Builder<String, Object> mapBuilder = ImmutableMap.<String, Object>builder();
- Builder builder = DatastoreContext.newBuilderFrom(context);
+ final Builder builder = DatastoreContext.newBuilderFrom(context);
final String dataStoreTypePrefix = context.getDataStoreName() + '.';
- List<String> keys = getSortedKeysByDatastoreType(Collections.list(properties.keys()), dataStoreTypePrefix);
+ final List<String> keys = getSortedKeysByDatastoreType(properties.keySet(), dataStoreTypePrefix);
boolean updated = false;
for (String key: keys) {
- Object value = properties.get(key);
+ final Object value = properties.get(key);
mapBuilder.put(key, value);
// If the key is prefixed with the data store type, strip it off.
return updated;
}
- private static ArrayList<String> getSortedKeysByDatastoreType(Collection<String> inKeys,
+ private static ArrayList<String> getSortedKeysByDatastoreType(final Collection<String> inKeys,
final String dataStoreTypePrefix) {
// Sort the property keys by putting the names prefixed with the data store type last. This
// is done so data store specific settings are applied after global settings.
- ArrayList<String> keys = new ArrayList<>(inKeys);
+ final ArrayList<String> keys = new ArrayList<>(inKeys);
Collections.sort(keys, (key1, key2) -> key1.startsWith(dataStoreTypePrefix) ? 1 :
key2.startsWith(dataStoreTypePrefix) ? -1 : key1.compareTo(key2));
return keys;
}
@SuppressWarnings("checkstyle:IllegalCatch")
- private boolean convertValueAndInvokeSetter(String inKey, Object inValue, Builder builder) {
- String key = convertToCamelCase(inKey);
+ private boolean convertValueAndInvokeSetter(final String inKey, final Object inValue, final Builder builder) {
+ final String key = convertToCamelCase(inKey);
try {
// Convert the value to the right type.
- Object value = convertValue(key, inValue);
+ final Object value = convertValue(key, inValue);
if (value == null) {
return false;
}
key, value, value.getClass().getSimpleName());
// Call the setter method on the Builder instance.
- Method setter = BUILDER_SETTERS.get(key);
+ final Method setter = BUILDER_SETTERS.get(key);
setter.invoke(builder, constructorValueRecursively(
Primitives.wrap(setter.getParameterTypes()[0]), value.toString()));
return false;
}
- private static String convertToCamelCase(String inString) {
+ private static String convertToCamelCase(final String inString) {
String str = inString.trim();
if (StringUtils.contains(str, '-') || StringUtils.contains(str, ' ')) {
str = inString.replace('-', ' ');
return StringUtils.uncapitalize(str);
}
- private Object convertValue(String name, Object from)
+ private Object convertValue(final String name, final Object from)
throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
- Class<?> propertyType = DATA_STORE_PROP_TYPES.get(name);
+ final Class<?> propertyType = DATA_STORE_PROP_TYPES.get(name);
if (propertyType == null) {
LOG.debug("Property not found for {}", name);
return null;
Object converted = constructorValueRecursively(propertyType, from.toString());
// If the converted type is a yang-generated type, call the getter to obtain the actual value.
- Method getter = YANG_TYPE_GETTERS.get(converted.getClass());
+ final Method getter = YANG_TYPE_GETTERS.get(converted.getClass());
if (getter != null) {
converted = getter.invoke(converted);
}
return converted;
}
- private Object constructorValueRecursively(Class<?> toType, Object fromValue)
+ private Object constructorValueRecursively(final Class<?> toType, final Object fromValue)
throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
LOG.trace("convertValueRecursively - toType: {}, fromValue {} ({})",
toType.getSimpleName(), fromValue, fromValue.getClass().getSimpleName());
- Constructor<?> ctor = CONSTRUCTORS.get(toType);
+ final Constructor<?> ctor = CONSTRUCTORS.get(toType);
LOG.trace("Found {}", ctor);
--- /dev/null
+/*
+ * Copyright (c) 2017 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.controller.cluster.datastore;
+
+import java.util.Map;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Update DatastoreContext settings on invoke update method.
+ *
+ */
+public class DatastoreContextPropertiesUpdater implements AutoCloseable {
+
+ public interface Listener {
+ void onDatastoreContextUpdated(DatastoreContextFactory contextFactory);
+ }
+
+ private static final Logger LOG = LoggerFactory.getLogger(DatastoreContextPropertiesUpdater.class);
+
+ private final DatastoreContextIntrospector introspector;
+ private Listener listener;
+
+ /**
+ * Base init of updater for DatastoreContext settings with base properties.
+ *
+ * @param introspector
+ * - introspection on DatastoreContext
+ * @param props
+ * - base properties
+ */
+ public DatastoreContextPropertiesUpdater(final DatastoreContextIntrospector introspector,
+ final Map<String, Object> props) {
+ this.introspector = introspector;
+ update(props);
+ }
+
+ public void setListener(final Listener listener) {
+ this.listener = listener;
+ }
+
+ public void update(final Map<String, Object> properties) {
+ LOG.debug("Overlaying settings: {}", properties);
+
+ if (introspector.update(properties) && listener != null) {
+ listener.onDatastoreContextUpdated(introspector.newContextFactory());
+ }
+ }
+
+ @Override
+ public void close() {
+ listener = null;
+ }
+}
import org.opendaylight.controller.cluster.datastore.config.Configuration;
import org.opendaylight.controller.cluster.datastore.config.ConfigurationImpl;
import org.opendaylight.controller.cluster.datastore.persisted.DatastoreSnapshot;
-import org.opendaylight.controller.sal.core.api.model.SchemaService;
import org.opendaylight.mdsal.dom.api.DOMSchemaService;
-import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class DistributedDataStoreFactory {
+
private static final Logger LOG = LoggerFactory.getLogger(DistributedDataStoreFactory.class);
private static final String DEFAULT_MODULE_SHARDS_PATH = "./configuration/initial/module-shards.conf";
private static final String DEFAULT_MODULES_PATH = "./configuration/initial/modules.conf";
private DistributedDataStoreFactory() {
}
- /**
- * Create a data store instance.
- *
- * @deprecated Use {@link #createInstance(DOMSchemaService, DatastoreContext, DatastoreSnapshotRestore,
- * ActorSystemProvider, BundleContext)} instead.
- */
- @Deprecated
- public static AbstractDataStore createInstance(final SchemaService schemaService,
- final DatastoreContext initialDatastoreContext, final DatastoreSnapshotRestore datastoreSnapshotRestore,
- final ActorSystemProvider actorSystemProvider, final BundleContext bundleContext) {
-
- return createInstance(schemaService, initialDatastoreContext, datastoreSnapshotRestore,
- actorSystemProvider, bundleContext, null);
- }
-
public static AbstractDataStore createInstance(final DOMSchemaService schemaService,
final DatastoreContext initialDatastoreContext, final DatastoreSnapshotRestore datastoreSnapshotRestore,
- final ActorSystemProvider actorSystemProvider, final BundleContext bundleContext) {
+ final ActorSystemProvider actorSystemProvider, final DatastoreContextIntrospector introspector,
+ final DatastoreContextPropertiesUpdater updater) {
return createInstance(schemaService, initialDatastoreContext, datastoreSnapshotRestore, actorSystemProvider,
- bundleContext, null);
+ introspector, updater, null);
}
public static AbstractDataStore createInstance(final DOMSchemaService schemaService,
final DatastoreContext initialDatastoreContext, final DatastoreSnapshotRestore datastoreSnapshotRestore,
- final ActorSystemProvider actorSystemProvider, final BundleContext bundleContext,
- final Configuration orgConfig) {
+ final ActorSystemProvider actorSystemProvider, final DatastoreContextIntrospector introspector,
+ final DatastoreContextPropertiesUpdater updater, final Configuration orgConfig) {
final String datastoreName = initialDatastoreContext.getDataStoreName();
LOG.info("Create data store instance of type : {}", datastoreName);
final ActorSystem actorSystem = actorSystemProvider.getActorSystem();
final DatastoreSnapshot restoreFromSnapshot = datastoreSnapshotRestore.getAndRemove(datastoreName);
- final DatastoreContextIntrospector introspector = new DatastoreContextIntrospector(initialDatastoreContext);
- final DatastoreContextConfigAdminOverlay overlay = new DatastoreContextConfigAdminOverlay(
- introspector, bundleContext);
Configuration config;
if (orgConfig == null) {
restoreFromSnapshot);
LOG.info("Data store {} is using ask-based protocol", datastoreName);
}
-
- overlay.setListener(dataStore);
+ updater.setListener(dataStore);
schemaService.registerSchemaContextListener(dataStore);
- dataStore.setCloseable(overlay);
+ dataStore.setCloseable(updater);
dataStore.waitTillReady();
return dataStore;
<service ref="actorSystemProvider" interface="org.opendaylight.controller.cluster.ActorSystemProvider"/>
- <!-- Distributed Config Datastore -->
+ <!-- Datastore properties -->
+ <cm:cm-properties id="datastoreProps" persistent-id="org.opendaylight.controller.cluster.datastore"/>
+ <!-- Distributed Config Datastore -->
<bean id="datastoreSnapshotRestore" class="org.opendaylight.controller.cluster.datastore.DatastoreSnapshotRestore"
factory-method="instance">
<argument value="./clustered-datastore-restore"/>
<bean id="configDatastoreContext" class="org.opendaylight.controller.config.yang.config.distributed_datastore_provider.DistributedConfigDataStoreProviderModule"
factory-method="newDatastoreContext" />
+ <bean id="introspectorConfig" class="org.opendaylight.controller.cluster.datastore.DatastoreContextIntrospector">
+ <argument ref="configDatastoreContext"/>
+ </bean>
+
+ <bean id="updaterConfig" class="org.opendaylight.controller.cluster.datastore.DatastoreContextPropertiesUpdater">
+ <cm:managed-properties persistent-id="org.opendaylight.controller.cluster.datastore" update-strategy="component-managed" update-method="update"/>
+ <argument ref="introspectorConfig"/>
+ <argument ref="datastoreProps"/>
+ </bean>
+
<bean id="configDatastore" class="org.opendaylight.controller.cluster.datastore.DistributedDataStoreFactory"
factory-method="createInstance" destroy-method="close">
<argument ref="schemaService"/>
<argument ref="configDatastoreContext"/>
<argument ref="datastoreSnapshotRestore"/>
<argument ref="actorSystemProvider"/>
- <argument ref="blueprintBundleContext"/>
+ <argument ref="introspectorConfig"/>
+ <argument ref="updaterConfig"/>
</bean>
<service ref="configDatastore" odl:type="distributed-config">
<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>
+
+ <bean id="updaterOper" class="org.opendaylight.controller.cluster.datastore.DatastoreContextPropertiesUpdater">
+ <cm:managed-properties persistent-id="org.opendaylight.controller.cluster.datastore" update-strategy="component-managed" update-method="update"/>
+ <argument ref="introspectorOper"/>
+ <argument ref="datastoreProps"/>
+ </bean>
+
<bean id="operDatastore" class="org.opendaylight.controller.cluster.datastore.DistributedDataStoreFactory"
factory-method="createInstance" destroy-method="close">
<argument ref="schemaService"/>
<argument ref="operDatastoreContext"/>
<argument ref="datastoreSnapshotRestore"/>
<argument ref="actorSystemProvider"/>
- <argument ref="blueprintBundleContext"/>
+ <argument ref="introspectorOper"/>
+ <argument ref="updaterOper"/>
<argument ref="configurationImpl" />
</bean>
+++ /dev/null
-/*
- * Copyright (c) 2015 Brocade Communications Systems, Inc. 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 static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import java.io.IOException;
-import java.util.Dictionary;
-import java.util.Hashtable;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.cm.Configuration;
-import org.osgi.service.cm.ConfigurationAdmin;
-import org.osgi.service.cm.ConfigurationEvent;
-import org.osgi.service.cm.ConfigurationListener;
-
-/**
- * Unit tests for DatastoreContextConfigAdminOverlay.
- *
- * @author Thomas Pantelis
- */
-@SuppressWarnings("unchecked")
-public class DatastoreContextConfigAdminOverlayTest {
-
- @Mock
- private BundleContext mockBundleContext;
-
- @Mock
- private ServiceReference<ConfigurationAdmin> mockConfigAdminServiceRef;
-
- @Mock
- private ConfigurationAdmin mockConfigAdmin;
-
- @Mock
- private Configuration mockConfig;
-
- @Mock
- private DatastoreContextIntrospector mockIntrospector;
-
- @Mock
- private ServiceRegistration<?> configListenerServiceReg;
-
- @Before
- public void setup() throws IOException {
- MockitoAnnotations.initMocks(this);
-
- doReturn(mockConfigAdminServiceRef).when(mockBundleContext).getServiceReference(ConfigurationAdmin.class);
- doReturn(mockConfigAdmin).when(mockBundleContext).getService(mockConfigAdminServiceRef);
- doReturn(configListenerServiceReg).when(mockBundleContext).registerService(
- eq(ConfigurationListener.class.getName()), any(), any(Dictionary.class));
-
- doReturn(mockConfig).when(mockConfigAdmin).getConfiguration(DatastoreContextConfigAdminOverlay.CONFIG_ID);
-
- doReturn(DatastoreContextConfigAdminOverlay.CONFIG_ID).when(mockConfig).getPid();
-
- }
-
- @Test
- public void testUpdateOnConstruction() {
- Dictionary<String, Object> properties = new Hashtable<>();
- properties.put("property", "value");
- doReturn(properties).when(mockConfig).getProperties();
-
- DatastoreContextConfigAdminOverlay overlay = new DatastoreContextConfigAdminOverlay(
- mockIntrospector, mockBundleContext);
-
- verify(mockIntrospector).update(properties);
-
- verify(mockBundleContext).ungetService(mockConfigAdminServiceRef);
-
- overlay.close();
- }
-
- @Test
- public void testUpdateOnConfigurationEvent() {
- final DatastoreContextConfigAdminOverlay overlay = new DatastoreContextConfigAdminOverlay(
- mockIntrospector, mockBundleContext);
-
- reset(mockIntrospector);
-
- DatastoreContext context = DatastoreContext.newBuilder().build();
- doReturn(context).when(mockIntrospector).getContext();
- DatastoreContextFactory contextFactory = new DatastoreContextFactory(mockIntrospector);
- doReturn(contextFactory).when(mockIntrospector).newContextFactory();
-
- DatastoreContextConfigAdminOverlay.Listener mockListener =
- mock(DatastoreContextConfigAdminOverlay.Listener.class);
-
- overlay.setListener(mockListener);
-
- Dictionary<String, Object> properties = new Hashtable<>();
- properties.put("property", "value");
- doReturn(properties).when(mockConfig).getProperties();
-
- doReturn(true).when(mockIntrospector).update(properties);
-
- ArgumentCaptor<ConfigurationListener> configListener =
- ArgumentCaptor.forClass(ConfigurationListener.class);
- verify(mockBundleContext).registerService(eq(ConfigurationListener.class.getName()),
- configListener.capture(), any(Dictionary.class));
-
- ConfigurationEvent configEvent = mock(ConfigurationEvent.class);
- doReturn(DatastoreContextConfigAdminOverlay.CONFIG_ID).when(configEvent).getPid();
- doReturn(mockConfigAdminServiceRef).when(configEvent).getReference();
- doReturn(ConfigurationEvent.CM_UPDATED).when(configEvent).getType();
-
- configListener.getValue().configurationEvent(configEvent);
-
- verify(mockIntrospector).update(properties);
-
- verify(mockListener).onDatastoreContextUpdated(contextFactory);
-
- verify(mockBundleContext, times(2)).ungetService(mockConfigAdminServiceRef);
-
- overlay.close();
-
- verify(configListenerServiceReg).unregister();
- }
-
- @Test
- public void testConfigurationEventWithDifferentPid() {
- final DatastoreContextConfigAdminOverlay overlay = new DatastoreContextConfigAdminOverlay(
- mockIntrospector, mockBundleContext);
-
- reset(mockIntrospector);
-
- ArgumentCaptor<ConfigurationListener> configListener =
- ArgumentCaptor.forClass(ConfigurationListener.class);
- verify(mockBundleContext).registerService(eq(ConfigurationListener.class.getName()),
- configListener.capture(), any(Dictionary.class));
-
- ConfigurationEvent configEvent = mock(ConfigurationEvent.class);
- doReturn("other-pid").when(configEvent).getPid();
- doReturn(mockConfigAdminServiceRef).when(configEvent).getReference();
- doReturn(ConfigurationEvent.CM_UPDATED).when(configEvent).getType();
-
- configListener.getValue().configurationEvent(configEvent);
-
- verify(mockIntrospector, times(0)).update(any(Dictionary.class));
-
- overlay.close();
- }
-
- @Test
- public void testConfigurationEventWithNonUpdateEventType() {
- final DatastoreContextConfigAdminOverlay overlay = new DatastoreContextConfigAdminOverlay(
- mockIntrospector, mockBundleContext);
-
- reset(mockIntrospector);
-
- ArgumentCaptor<ConfigurationListener> configListener =
- ArgumentCaptor.forClass(ConfigurationListener.class);
- verify(mockBundleContext).registerService(eq(ConfigurationListener.class.getName()),
- configListener.capture(), any(Dictionary.class));
-
- ConfigurationEvent configEvent = mock(ConfigurationEvent.class);
- doReturn(DatastoreContextConfigAdminOverlay.CONFIG_ID).when(configEvent).getPid();
- doReturn(mockConfigAdminServiceRef).when(configEvent).getReference();
- doReturn(ConfigurationEvent.CM_DELETED).when(configEvent).getType();
-
- configListener.getValue().configurationEvent(configEvent);
-
- verify(mockIntrospector, times(0)).update(any(Dictionary.class));
-
- overlay.close();
- }
-}
--- /dev/null
+/*
+ * Copyright (c) 2017 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.controller.cluster.datastore;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.Test;
+import org.opendaylight.controller.cluster.datastore.DatastoreContextPropertiesUpdater.Listener;
+
+public class DatastoreContextContextPropertiesUpdaterTest {
+
+ @SuppressWarnings("unchecked")
+ @Test
+ 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 DatastoreContextPropertiesUpdater updater = new DatastoreContextPropertiesUpdater(introspector,
+ properties);
+ assertNotNull(updater);
+
+ final Map<String, Object> props = (Map<String, Object>) resolveField("currentProperties", introspector);
+
+ assertEquals(props.get("shardTransactionIdleTimeoutInMinutes"), 10);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ 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);
+ assertNotNull(introspector);
+ final DatastoreContextPropertiesUpdater updater = new DatastoreContextPropertiesUpdater(introspector,
+ properties);
+ assertNotNull(updater);
+
+ Map<String, Object> props = (Map<String, Object>) resolveField("currentProperties", introspector);
+ assertTrue(!props.isEmpty());
+
+ properties.put("shardTransactionIdleTimeoutInMinutes", 20);
+ updater.update(properties);
+
+ props = (Map<String, Object>) resolveField("currentProperties", introspector);
+ assertEquals(props.get("shardTransactionIdleTimeoutInMinutes"), 20);
+ }
+
+ @SuppressWarnings("resource")
+ @Test
+ public void listenerTest() {
+ final Map<String, Object> properties = new HashMap<>();
+ properties.put("shardTransactionIdleTimeoutInMinutes", 10);
+
+ final DatastoreContext datastoreContext = DatastoreContext.newBuilder().build();
+ final DatastoreContextIntrospector introspector = new DatastoreContextIntrospector(datastoreContext);
+ final DatastoreContextPropertiesUpdater updater = new DatastoreContextPropertiesUpdater(introspector,
+ properties);
+ final DummyListenerImpl dummyListener = new DummyListenerImpl();
+ updater.setListener(dummyListener);
+
+ assertTrue(dummyListener.getContextFactory() == null);
+ updater.setListener(dummyListener);
+ properties.put("shardTransactionIdleTimeoutInMinutes", 20);
+ updater.update(properties);
+
+ final DatastoreContextFactory contextFactory = dummyListener.getContextFactory();
+ assertNotNull(contextFactory);
+ updater.close();
+ }
+
+ private Object resolveField(final String name, final Object obj) throws Exception {
+ final Field currProps = obj.getClass().getDeclaredField(name);
+ currProps.setAccessible(true);
+ return currProps.get(obj);
+ }
+
+ private class DummyListenerImpl implements Listener {
+
+ private DatastoreContextFactory contextFactory;
+
+ @Override
+ public void onDatastoreContextUpdated(final DatastoreContextFactory contextFactory) {
+ this.contextFactory = contextFactory;
+ }
+
+ public DatastoreContextFactory getContextFactory() {
+ return contextFactory;
+ }
+ }
+}
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 java.util.Dictionary;
+import java.util.HashMap;
import java.util.Hashtable;
+import java.util.Map;
import org.junit.Test;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStoreConfigProperties;
public void testUpdate() {
DatastoreContext context = DatastoreContext.newBuilder()
.logicalStoreType(LogicalDatastoreType.OPERATIONAL).build();
- DatastoreContextIntrospector introspector = new DatastoreContextIntrospector(context);
+ final DatastoreContextIntrospector introspector = new DatastoreContextIntrospector(context);
- Dictionary<String, Object> properties = new Hashtable<>();
+ final Map<String, Object> properties = new HashMap<>();
properties.put("shard-transaction-idle-timeout-in-minutes", "31");
properties.put("operation-timeout-in-seconds", "26");
properties.put("shard-transaction-commit-timeout-in-seconds", "100");
public void testUpdateWithInvalidValues() {
DatastoreContext context = DatastoreContext.newBuilder()
.logicalStoreType(LogicalDatastoreType.OPERATIONAL).build();
- DatastoreContextIntrospector introspector = new DatastoreContextIntrospector(context);
+ final DatastoreContextIntrospector introspector = new DatastoreContextIntrospector(context);
- Dictionary<String, Object> properties = new Hashtable<>();
+ final Map<String, Object> properties = new HashMap<>();
properties.put("shard-transaction-idle-timeout-in-minutes", "0"); // bad - must be > 0
properties.put("shard-journal-recovery-log-batch-size", "199");
properties.put("shard-transaction-commit-timeout-in-seconds", "bogus"); // bad - NaN
properties.put("max-shard-data-change-executor-pool-size", "bogus"); // bad - NaN
properties.put("unknownProperty", "1"); // bad - invalid property name
- boolean updated = introspector.update(properties);
+ final boolean updated = introspector.update(properties);
assertEquals("updated", true, updated);
context = introspector.getContext();
@Test
public void testUpdateWithDatastoreTypeSpecificProperties() {
- Dictionary<String, Object> properties = new Hashtable<>();
+ final Map<String, Object> properties = new HashMap<>();
properties.put("shard-transaction-idle-timeout-in-minutes", "22"); // global setting
properties.put("operational.shard-transaction-idle-timeout-in-minutes", "33"); // operational override
properties.put("config.shard-transaction-idle-timeout-in-minutes", "44"); // config override
DatastoreContext operContext = DatastoreContext.newBuilder()
.logicalStoreType(LogicalDatastoreType.OPERATIONAL).build();
- DatastoreContextIntrospector operIntrospector = new DatastoreContextIntrospector(operContext);
+ final DatastoreContextIntrospector operIntrospector = new DatastoreContextIntrospector(operContext);
boolean updated = operIntrospector.update(properties);
assertEquals("updated", true, updated);
operContext = operIntrospector.getContext();
DatastoreContext configContext = DatastoreContext.newBuilder()
.logicalStoreType(LogicalDatastoreType.CONFIGURATION).build();
- DatastoreContextIntrospector configIntrospector = new DatastoreContextIntrospector(configContext);
+ final DatastoreContextIntrospector configIntrospector = new DatastoreContextIntrospector(configContext);
updated = configIntrospector.update(properties);
assertEquals("updated", true, updated);
configContext = configIntrospector.getContext();
@Test
public void testGetDatastoreContextForShard() {
- Dictionary<String, Object> properties = new Hashtable<>();
+ final Map<String, Object> properties = new HashMap<>();
properties.put("shard-transaction-idle-timeout-in-minutes", "22"); // global setting
properties.put("operational.shard-transaction-idle-timeout-in-minutes", "33"); // operational override
properties.put("config.shard-transaction-idle-timeout-in-minutes", "44"); // config override
DatastoreContext operContext = DatastoreContext.newBuilder()
.logicalStoreType(LogicalDatastoreType.OPERATIONAL).build();
- DatastoreContextIntrospector operIntrospector = new DatastoreContextIntrospector(operContext);
+ final DatastoreContextIntrospector operIntrospector = new DatastoreContextIntrospector(operContext);
DatastoreContext shardContext = operIntrospector.newContextFactory().getShardDatastoreContext("topology");
assertEquals(10, shardContext.getShardTransactionIdleTimeout().toMinutes());
DatastoreContext configContext = DatastoreContext.newBuilder()
.logicalStoreType(LogicalDatastoreType.CONFIGURATION).build();
- DatastoreContextIntrospector configIntrospector = new DatastoreContextIntrospector(configContext);
+ final DatastoreContextIntrospector configIntrospector = new DatastoreContextIntrospector(configContext);
configIntrospector.update(properties);
configContext = configIntrospector.getContext();
assertEquals(44, configContext.getShardTransactionIdleTimeout().toMinutes());