From: Ed Warnicke Date: Wed, 27 Nov 2013 21:34:49 +0000 (+0000) Subject: Merge "Moved Schema Aware logic from DataStore to SchemaAwareDataStore adapter" X-Git-Tag: jenkins-controller-bulk-release-prepare-only-2-1~327 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=76925347a1925c00c8d479f455783565c0caaaa0;hp=df1eef1a88c6e96aac7071cae97c4ae41ea72b1d;p=controller.git Merge "Moved Schema Aware logic from DataStore to SchemaAwareDataStore adapter" --- diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/AbstractDataServiceTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/AbstractDataServiceTest.java index 5b35861e9d..9f3a6e8652 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/AbstractDataServiceTest.java +++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/AbstractDataServiceTest.java @@ -8,6 +8,7 @@ import java.util.Set; import javassist.ClassPool; +import org.junit.After; import org.junit.Before; import org.opendaylight.controller.sal.binding.api.data.DataProviderService; import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl; @@ -15,78 +16,96 @@ import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndepende import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentMappingService; import org.opendaylight.controller.sal.binding.dom.serializer.impl.RuntimeGeneratedMappingServiceImpl; import org.opendaylight.controller.sal.core.api.data.DataBrokerService; +import org.opendaylight.controller.sal.core.api.data.DataStore; +import org.opendaylight.controller.sal.dom.broker.impl.DataStoreStatsWrapper; import org.opendaylight.controller.sal.dom.broker.impl.HashMapDataStore; +import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareDataStoreAdapter; import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl; import org.reflections.Reflections; import org.reflections.scanners.ResourcesScanner; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.google.common.base.Predicate; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; -public abstract class AbstractDataServiceTest { +public abstract class AbstractDataServiceTest { + private static Logger log = LoggerFactory.getLogger(AbstractDataServiceTest.class); + protected org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService; protected DataProviderService baDataService; - + /** * Workaround for JUNIT sharing classloaders * */ protected static final ClassPool POOL = new ClassPool(); - + protected RuntimeGeneratedMappingServiceImpl mappingServiceImpl; protected BindingIndependentMappingService mappingService; protected DataBrokerImpl baDataImpl; protected org.opendaylight.controller.sal.dom.broker.DataBrokerImpl biDataImpl; protected ListeningExecutorService executor; protected BindingIndependentDataServiceConnector connectorServiceImpl; - protected HashMapDataStore dataStore; - - + protected HashMapDataStore rawDataStore; + private SchemaAwareDataStoreAdapter schemaAwareDataStore; + private DataStoreStatsWrapper dataStoreStats; + + protected DataStore dataStore; + @Before public void setUp() { executor = MoreExecutors.sameThreadExecutor(); baDataImpl = new DataBrokerImpl(); baDataService = baDataImpl; baDataImpl.setExecutor(executor); - + biDataImpl = new org.opendaylight.controller.sal.dom.broker.DataBrokerImpl(); - biDataService = biDataImpl; + biDataService = biDataImpl; biDataImpl.setExecutor(executor); - - dataStore = new HashMapDataStore(); - org.opendaylight.yangtools.yang.data.api.InstanceIdentifier treeRoot = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder().toInstance(); + + rawDataStore = new HashMapDataStore(); + schemaAwareDataStore = new SchemaAwareDataStoreAdapter(); + schemaAwareDataStore.changeDelegate(rawDataStore); + dataStoreStats = new DataStoreStatsWrapper(schemaAwareDataStore); + dataStore = dataStoreStats; + + org.opendaylight.yangtools.yang.data.api.InstanceIdentifier treeRoot = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier + .builder().toInstance(); biDataImpl.registerConfigurationReader(treeRoot, dataStore); biDataImpl.registerOperationalReader(treeRoot, dataStore); biDataImpl.registerCommitHandler(treeRoot, dataStore); - + mappingServiceImpl = new RuntimeGeneratedMappingServiceImpl(); mappingServiceImpl.setPool(POOL); mappingService = mappingServiceImpl; File pathname = new File("target/gen-classes-debug"); - //System.out.println("Generated classes are captured in " + pathname.getAbsolutePath()); + // System.out.println("Generated classes are captured in " + + // pathname.getAbsolutePath()); mappingServiceImpl.start(null); - //mappingServiceImpl.getBinding().setClassFileCapturePath(pathname); - + // mappingServiceImpl.getBinding().setClassFileCapturePath(pathname); + connectorServiceImpl = new BindingIndependentDataServiceConnector(); connectorServiceImpl.setBaDataService(baDataService); connectorServiceImpl.setBiDataService(biDataService); connectorServiceImpl.setMappingService(mappingServiceImpl); connectorServiceImpl.start(); - - String[] yangFiles= getModelFilenames(); - if(yangFiles != null && yangFiles.length > 0) { - mappingServiceImpl.onGlobalContextUpdated(getContext(yangFiles)); + + String[] yangFiles = getModelFilenames(); + if (yangFiles != null && yangFiles.length > 0) { + SchemaContext context = getContext(yangFiles); + mappingServiceImpl.onGlobalContextUpdated(context); + schemaAwareDataStore.onGlobalContextUpdated(context); } } - - protected String[] getModelFilenames() { + protected String[] getModelFilenames() { return getAllModelFilenames(); } - + public static String[] getAllModelFilenames() { Predicate predicate = new Predicate() { @Override @@ -94,11 +113,11 @@ public abstract class AbstractDataServiceTest { return input.endsWith(".yang"); } }; - Reflections reflection= new Reflections("META-INF.yang", new ResourcesScanner()); + Reflections reflection = new Reflections("META-INF.yang", new ResourcesScanner()); Set result = reflection.getResources(predicate); return (String[]) result.toArray(new String[result.size()]); } - + public static SchemaContext getContext(String[] yangFiles) { ClassLoader loader = AbstractDataServiceTest.class.getClassLoader(); @@ -114,4 +133,21 @@ public abstract class AbstractDataServiceTest { Set modules = parser.parseYangModelsFromStreams(streams); return parser.resolveSchemaContext(modules); } + + @After + public void afterTest() { + + log.info("BIDataStore Statistics: Configuration Read Count: {} TotalTime: {} ns AverageTime (ns): {} ns", + dataStoreStats.getConfigurationReadCount(), dataStoreStats.getConfigurationReadTotalTime(), + dataStoreStats.getConfigurationReadAverageTime()); + + log.info("BIDataStore Statistics: Operational Read Count: {} TotalTime: {} ns AverageTime (ns): {} ns", + dataStoreStats.getOperationalReadCount(), dataStoreStats.getOperationalReadTotalTime(), + dataStoreStats.getOperationalReadAverageTime()); + + log.info("BIDataStore Statistics: Request Commit Count: {} TotalTime: {} ns AverageTime (ns): {} ns", + dataStoreStats.getRequestCommitCount(), dataStoreStats.getRequestCommitTotalTime(), + dataStoreStats.getRequestCommitAverageTime()); + + } } diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChangeEvent.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChangeEvent.java index 144a81b256..d62e176e62 100644 --- a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChangeEvent.java +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChangeEvent.java @@ -11,15 +11,31 @@ import org.opendaylight.yangtools.concepts.Immutable; public interface DataChangeEvent extends DataChange, Immutable { + /** + * Returns a orignal subtree of data, which starts at the path + * where listener was registered. + * + */ + D getOriginalConfigurationSubtree(); + /** * Returns a new subtree of data, which starts at the path * where listener was registered. * */ + D getOriginalOperationalSubtree(); + + + + /** + * Returns a updated subtree of data, which starts at the path + * where listener was registered. + * + */ D getUpdatedConfigurationSubtree(); /** - * Returns a new subtree of data, which starts at the path + * Returns a udpated subtree of data, which starts at the path * where listener was registered. * */ diff --git a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/AbstractDataBroker.xtend b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/AbstractDataBroker.xtend index e3d2b567a7..a18e5a9c82 100644 --- a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/AbstractDataBroker.xtend +++ b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/AbstractDataBroker.xtend @@ -38,6 +38,7 @@ import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandlerRegis import org.opendaylight.controller.md.sal.common.api.RegistrationListener import org.opendaylight.yangtools.concepts.util.ListenerRegistry import java.util.concurrent.atomic.AtomicLong +import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent abstract class AbstractDataBroker

, D, DCL extends DataChangeListener> implements DataModificationTransactionFactory, // DataReader, // @@ -91,6 +92,10 @@ DataProvisionService { override final def registerDataChangeListener(P path, DCL listener) { val reg = new DataChangeListenerRegistration(path, listener, this); listeners.put(path, reg); + val initialConfig = dataReadRouter.readConfigurationData(path); + val initialOperational = dataReadRouter.readOperationalData(path); + val event = createInitialListenerEvent(path,initialConfig,initialOperational); + listener.onDataChanged(event); return reg; } @@ -108,6 +113,10 @@ DataProvisionService { return ret; } + protected def DataChangeEvent createInitialListenerEvent(P path,D initialConfig,D initialOperational) { + return new InitialDataChangeEventImpl(initialConfig,initialOperational); + + } protected final def removeListener(DataChangeListenerRegistration registration) { listeners.remove(registration.path, registration); diff --git a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/DataChangeEventImpl.java b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/DataChangeEventImpl.java index 4eb9586fdf..68f9506c56 100644 --- a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/DataChangeEventImpl.java +++ b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/DataChangeEventImpl.java @@ -11,6 +11,8 @@ public class DataChangeEventImpl implements DataChangeEvent { private final DataChange dataChange; private final D originalConfigurationSubtree; + + private final D originalOperationalSubtree; private final D updatedOperationalSubtree; private final D updatedConfigurationSubtree; @@ -28,6 +30,16 @@ public class DataChangeEventImpl implements DataChangeEvent { this.updatedConfigurationSubtree = updatedConfigurationSubtree; } + @Override + public D getOriginalConfigurationSubtree() { + return originalConfigurationSubtree; + } + + @Override + public D getOriginalOperationalSubtree() { + return originalOperationalSubtree; + } + @Override public D getUpdatedOperationalSubtree() { return updatedOperationalSubtree; diff --git a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/InitialDataChangeEventImpl.java b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/InitialDataChangeEventImpl.java new file mode 100644 index 0000000000..2764635720 --- /dev/null +++ b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/InitialDataChangeEventImpl.java @@ -0,0 +1,75 @@ +package org.opendaylight.controller.md.sal.common.impl.service; + +import java.util.Collections; +import java.util.Map; +import java.util.Set; + +import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent; + +public class InitialDataChangeEventImpl implements DataChangeEvent { + + private final D originalOperationalTree; + private final D originalConfigurationTree; + + public InitialDataChangeEventImpl(D configTree, D operTree) { + originalConfigurationTree = configTree; + originalOperationalTree = operTree; + } + + @Override + public Map getCreatedConfigurationData() { + return Collections.emptyMap(); + } + + @Override + public Map getCreatedOperationalData() { + return Collections.emptyMap(); + } + + @Override + public Map getOriginalConfigurationData() { + return Collections.emptyMap(); + } + @Override + public Map getOriginalOperationalData() { + return Collections.emptyMap(); + } + @Override + public Set

getRemovedConfigurationData() { + return Collections.emptySet(); + } + @Override + public Set

getRemovedOperationalData() { + return Collections.emptySet(); + } + @Override + public Map getUpdatedConfigurationData() { + return Collections.emptyMap(); + } + + @Override + public D getUpdatedConfigurationSubtree() { + return originalConfigurationTree; + } + @Override + public D getUpdatedOperationalSubtree() { + return originalOperationalTree; + } + + @Override + public D getOriginalConfigurationSubtree() { + return originalConfigurationTree; + } + + @Override + public D getOriginalOperationalSubtree() { + return originalOperationalTree; + } + + @Override + public Map getUpdatedOperationalData() { + return Collections.emptyMap(); + } + + +} diff --git a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/util/AbstractLockableDelegator.java b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/util/AbstractLockableDelegator.java new file mode 100644 index 0000000000..61abe664aa --- /dev/null +++ b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/util/AbstractLockableDelegator.java @@ -0,0 +1,76 @@ +package org.opendaylight.controller.md.sal.common.impl.util; + +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; +import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; + +import org.opendaylight.yangtools.concepts.Delegator; + +import com.google.common.base.Preconditions; + +public class AbstractLockableDelegator implements Delegator { + + private final ReentrantReadWriteLock delegateLock = new ReentrantReadWriteLock(); + private final ReadLock delegateReadLock = delegateLock.readLock(); + private final WriteLock delegateWriteLock = delegateLock.writeLock(); + + + protected Lock getDelegateReadLock() { + return delegateReadLock; + } + + private T delegate; + + public AbstractLockableDelegator() { + // NOOP + } + + public AbstractLockableDelegator(T initialDelegate) { + delegate = initialDelegate; + } + + @Override + public T getDelegate() { + try { + delegateReadLock.lock(); + return delegate; + } finally { + delegateReadLock.unlock(); + } + } + + public T retrieveDelegate() { + try { + delegateReadLock.lock(); + Preconditions.checkState(delegate != null,"Delegate is null"); + return delegate; + } finally { + delegateReadLock.unlock(); + } + } + + /** + * + * @param newDelegate + * @return oldDelegate + */ + public final T changeDelegate(T newDelegate) { + try { + delegateWriteLock.lock(); + T oldDelegate = delegate; + delegate = newDelegate; + onDelegateChanged(oldDelegate, newDelegate); + return oldDelegate; + } finally { + delegateWriteLock.unlock(); + } + } + + + protected void onDelegateChanged(T oldDelegate, T newDelegate) { + // NOOP in abstract calss; + } +} diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataStore.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataStore.java index 1062f5e535..87129d6863 100644 --- a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataStore.java +++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataStore.java @@ -8,5 +8,12 @@ import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; public interface DataStore extends // DataReader, DataCommitHandler { + + + Iterable getStoredConfigurationPaths(); + Iterable getStoredOperationalPaths(); + + boolean containsConfigurationPath(InstanceIdentifier path); + boolean containsOperationalPath(InstanceIdentifier path); } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomBrokerImplModule.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomBrokerImplModule.java index 9a4fc6ddc1..050966faa0 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomBrokerImplModule.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomBrokerImplModule.java @@ -13,6 +13,7 @@ import org.opendaylight.controller.sal.core.api.data.DataStore; import org.opendaylight.controller.sal.dom.broker.BrokerConfigActivator; import org.opendaylight.controller.sal.dom.broker.BrokerImpl; import org.osgi.framework.BundleContext; +import static com.google.common.base.Preconditions.*; /** * @@ -33,8 +34,10 @@ public final class DomBrokerImplModule extends org.opendaylight.controller.confi @Override public void validate(){ super.validate(); - // Add custom validation for module attributes here. + checkArgument(getDataStore() != null, "Data Store needs to be provided for DomBroker"); } + + @Override public java.lang.AutoCloseable createInstance() { diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerConfigActivator.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerConfigActivator.xtend index a6aa0ce32e..54c94dca9f 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerConfigActivator.xtend +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerConfigActivator.xtend @@ -12,6 +12,7 @@ import java.util.Hashtable import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier import org.opendaylight.controller.sal.core.api.data.DataStore +import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareDataStoreAdapter class BrokerConfigActivator implements AutoCloseable { @@ -27,6 +28,8 @@ class BrokerConfigActivator implements AutoCloseable { private var SchemaServiceImpl schemaService; private var DataBrokerImpl dataService; private var MountPointManagerImpl mountService; + + SchemaAwareDataStoreAdapter wrappedStore public def void start(BrokerImpl broker,DataStore store,BundleContext context) { val emptyProperties = new Hashtable(); @@ -45,9 +48,13 @@ class BrokerConfigActivator implements AutoCloseable { dataReg = context.registerService(DataBrokerService, dataService, emptyProperties); dataProviderReg = context.registerService(DataProviderService, dataService, emptyProperties); - dataService.registerConfigurationReader(ROOT, store); - dataService.registerCommitHandler(ROOT, store); - dataService.registerOperationalReader(ROOT, store); + wrappedStore = new SchemaAwareDataStoreAdapter(); + wrappedStore.changeDelegate(store); + wrappedStore.setValidationEnabled(false); + + dataService.registerConfigurationReader(ROOT, wrappedStore); + dataService.registerCommitHandler(ROOT, wrappedStore); + dataService.registerOperationalReader(ROOT, wrappedStore); mountService = new MountPointManagerImpl(); mountService.setDataBroker(dataService); diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerImpl.java index 1197ef34bd..ac5313a9ca 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerImpl.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerImpl.java @@ -2,6 +2,7 @@ package org.opendaylight.controller.sal.dom.broker; import java.util.concurrent.atomic.AtomicLong; +import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent; import org.opendaylight.controller.md.sal.common.api.data.DataReader; import org.opendaylight.controller.md.sal.common.impl.service.AbstractDataBroker; import org.opendaylight.controller.sal.common.DataStoreIdentifier; diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataStoreStatsWrapper.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataStoreStatsWrapper.java new file mode 100644 index 0000000000..9116d50d9c --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataStoreStatsWrapper.java @@ -0,0 +1,137 @@ +package org.opendaylight.controller.sal.dom.broker.impl; + +import java.util.concurrent.atomic.AtomicLong; + +import org.opendaylight.controller.md.sal.common.api.data.DataModification; +import org.opendaylight.controller.sal.core.api.data.DataStore; +import org.opendaylight.yangtools.concepts.Delegator; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; + +public class DataStoreStatsWrapper implements Delegator, DataStore { + + private final DataStore delegate; + + private AtomicLong cfgReadCount = new AtomicLong(); + private AtomicLong cfgReadTimeTotal = new AtomicLong(); + + private AtomicLong operReadCount = new AtomicLong(); + private AtomicLong operReadTimeTotal = new AtomicLong(); + + private AtomicLong requestCommitCount = new AtomicLong(); + private AtomicLong requestCommitTimeTotal = new AtomicLong(); + + public DataStoreStatsWrapper(DataStore store) { + delegate = store; + } + + @Override + public DataStore getDelegate() { + return delegate; + } + + @Override + public CompositeNode readConfigurationData(InstanceIdentifier path) { + cfgReadCount.incrementAndGet(); + final long startTime = System.nanoTime(); + try { + return delegate.readConfigurationData(path); + } finally { + final long endTime = System.nanoTime(); + final long runTime = endTime - startTime; + cfgReadTimeTotal.addAndGet(runTime); + } + } + + @Override + public CompositeNode readOperationalData(InstanceIdentifier path) { + operReadCount.incrementAndGet(); + final long startTime = System.nanoTime(); + try { + return delegate.readOperationalData(path); + } finally { + final long endTime = System.nanoTime(); + final long runTime = endTime - startTime; + cfgReadTimeTotal.addAndGet(runTime); + } + } + + public DataCommitTransaction requestCommit( + DataModification modification) { + requestCommitCount.incrementAndGet(); + final long startTime = System.nanoTime(); + try { + return delegate.requestCommit(modification); + } finally { + final long endTime = System.nanoTime(); + final long runTime = endTime - startTime; + requestCommitTimeTotal.addAndGet(runTime); + } + }; + + @Override + public boolean containsConfigurationPath(InstanceIdentifier path) { + return delegate.containsConfigurationPath(path); + } + + public Iterable getStoredConfigurationPaths() { + return delegate.getStoredConfigurationPaths(); + } + + public Iterable getStoredOperationalPaths() { + return delegate.getStoredOperationalPaths(); + } + + public boolean containsOperationalPath(InstanceIdentifier path) { + return delegate.containsOperationalPath(path); + } + + public final long getConfigurationReadCount() { + return cfgReadCount.get(); + } + + public final long getOperationalReadCount() { + return operReadCount.get(); + } + + public final long getRequestCommitCount() { + return requestCommitCount.get(); + } + + public final long getConfigurationReadTotalTime() { + return cfgReadTimeTotal.get(); + } + + public final long getOperationalReadTotalTime() { + return operReadTimeTotal.get(); + } + + public final long getRequestCommitTotalTime() { + return requestCommitTimeTotal.get(); + } + + public final long getConfigurationReadAverageTime() { + long readCount = cfgReadCount.get(); + if(readCount == 0) { + return 0; + } + return cfgReadTimeTotal.get() / readCount; + } + + public final long getOperationalReadAverageTime() { + long readCount = operReadCount.get(); + if(readCount == 0) { + return 0; + } + return operReadTimeTotal.get() / readCount; + } + + public final long getRequestCommitAverageTime() { + long count = requestCommitCount.get(); + if(count == 0) { + return 0; + } + return requestCommitTimeTotal.get() / count; + } + +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataUtils.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataUtils.xtend deleted file mode 100644 index 1a2f947270..0000000000 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataUtils.xtend +++ /dev/null @@ -1,50 +0,0 @@ -package org.opendaylight.controller.sal.dom.broker.impl - -import org.opendaylight.yangtools.yang.data.api.CompositeNode -import java.util.Map -import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier -import java.util.Map.Entry -import java.util.HashSet -import java.util.ArrayList -import org.opendaylight.yangtools.yang.data.api.Node -import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl - -class DataUtils { - - static def CompositeNode read(Map map, InstanceIdentifier path) { - val root = map.get(path); - val childs = map.getChilds(path); - if(root === null && childs.empty) { - return null; - } - - return merge(path, root, childs); - } - - static def CompositeNode merge(InstanceIdentifier path, CompositeNode node, - HashSet> entries) { - val it = new ArrayList>(); - val qname = path.path.last.nodeType; - if (node != null) { - addAll(node.children); - } - for (entry : entries) { - val nesting = entry.key.path.size - path.path.size; - if (nesting === 1) { - add(entry.value); - } - } - return new CompositeNodeTOImpl(qname, null, it); - } - - static def getChilds(Map map, InstanceIdentifier path) { - val it = new HashSet>(); - for (entry : map.entrySet) { - if (path.contains(entry.key)) { - add(entry); - } - } - return it; - } - -} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/HashMapDataStore.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/HashMapDataStore.xtend index e7445e6965..e9ed71a052 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/HashMapDataStore.xtend +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/HashMapDataStore.xtend @@ -9,23 +9,41 @@ import org.opendaylight.controller.sal.common.util.Rpcs import java.util.Collections import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier import org.opendaylight.yangtools.yang.data.api.CompositeNode -import static extension org.opendaylight.controller.sal.dom.broker.impl.DataUtils.*; import org.opendaylight.controller.sal.core.api.data.DataStore import java.util.HashSet class HashMapDataStore implements DataStore, AutoCloseable { + val Map configuration = new ConcurrentHashMap(); val Map operational = new ConcurrentHashMap(); + + + + override containsConfigurationPath(InstanceIdentifier path) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + + } + + override containsOperationalPath(InstanceIdentifier path) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + } + + override getStoredConfigurationPaths() { + configuration.keySet + } + + override getStoredOperationalPaths() { + operational.keySet + } override readConfigurationData(InstanceIdentifier path) { - configuration.read(path); + configuration.get(path); } override readOperationalData(InstanceIdentifier path) { - operational.read(path); + operational.get(path); } - diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareDataMerger.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareDataMerger.xtend new file mode 100644 index 0000000000..8cdbf9225d --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareDataMerger.xtend @@ -0,0 +1,13 @@ +package org.opendaylight.controller.sal.dom.broker.impl + +import org.opendaylight.yangtools.yang.model.api.SchemaContext +import org.opendaylight.yangtools.yang.data.api.CompositeNode + +class SchemaAwareDataMerger { + + private SchemaContext schema; + + + + +} \ No newline at end of file diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareDataStoreAdapter.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareDataStoreAdapter.java new file mode 100644 index 0000000000..1f908140b0 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareDataStoreAdapter.java @@ -0,0 +1,245 @@ +package org.opendaylight.controller.sal.dom.broker.impl; + +import java.awt.PageAttributes.OriginType; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.concurrent.atomic.AtomicLong; + +import org.opendaylight.controller.md.sal.common.api.data.DataModification; +import org.opendaylight.controller.md.sal.common.api.data.DataReader; +import org.opendaylight.controller.md.sal.common.impl.util.AbstractLockableDelegator; +import org.opendaylight.controller.sal.core.api.data.DataStore; +import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.Node; +import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Predicate; +import com.google.common.collect.FluentIterable; + +import static com.google.common.base.Preconditions.*; + +public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator implements // + DataStore, // + SchemaServiceListener, // + AutoCloseable { + + private final static Logger LOG = LoggerFactory.getLogger(SchemaAwareDataStoreAdapter.class); + + private SchemaContext schema = null; + private boolean validationEnabled = false; + private SchemaAwareDataMerger dataMerger = null; + private DataReader reader = new MergeFirstLevelReader(); + + @Override + public boolean containsConfigurationPath(InstanceIdentifier path) { + try { + getDelegateReadLock().lock(); + return getDelegate().containsConfigurationPath(path); + + } finally { + getDelegateReadLock().unlock(); + } + } + + @Override + public boolean containsOperationalPath(InstanceIdentifier path) { + try { + getDelegateReadLock().lock(); + return getDelegate().containsOperationalPath(path); + + } finally { + getDelegateReadLock().unlock(); + } + } + + @Override + public Iterable getStoredConfigurationPaths() { + try { + getDelegateReadLock().lock(); + return getDelegate().getStoredConfigurationPaths(); + + } finally { + getDelegateReadLock().unlock(); + } + } + + @Override + public Iterable getStoredOperationalPaths() { + try { + getDelegateReadLock().lock(); + return getDelegate().getStoredOperationalPaths(); + + } finally { + getDelegateReadLock().unlock(); + } + } + + @Override + public CompositeNode readConfigurationData(InstanceIdentifier path) { + return reader.readConfigurationData(path); + } + + @Override + public CompositeNode readOperationalData(InstanceIdentifier path) { + return reader.readOperationalData(path); + } + + @Override + public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction requestCommit( + DataModification modification) { + validateAgainstSchema(modification); + DataModification cleanedUp = prepareMergedTransaction(modification); + return retrieveDelegate().requestCommit(cleanedUp); + } + + public boolean isValidationEnabled() { + return validationEnabled; + } + + public void setValidationEnabled(boolean validationEnabled) { + this.validationEnabled = validationEnabled; + } + + private void validateAgainstSchema(DataModification modification) { + if (!validationEnabled) { + return; + } + + if (schema == null) { + LOG.info("Validation not performed for {}. Reason: YANG Schema not present.", modification.getIdentifier()); + return; + } + } + + @Override + protected void onDelegateChanged(DataStore oldDelegate, DataStore newDelegate) { + // NOOP + } + + @Override + public void onGlobalContextUpdated(SchemaContext context) { + this.schema = context; + } + + @Override + public void close() throws Exception { + this.schema = null; + } + + private DataModification prepareMergedTransaction( + DataModification original) { + // NOOP for now + return original; + } + + private final Comparator> preparationComparator = new Comparator>() { + @Override + public int compare(Entry o1, Entry o2) { + InstanceIdentifier o1Key = o1.getKey(); + InstanceIdentifier o2Key = o2.getKey(); + return Integer.compare(o1Key.getPath().size(), o2Key.getPath().size()); + } + }; + + private class MergeFirstLevelReader implements DataReader { + + @Override + public CompositeNode readConfigurationData(final InstanceIdentifier path) { + getDelegateReadLock().lock(); + try { + if (path.getPath().isEmpty()) { + return null; + } + QName qname = null; + CompositeNode original = getDelegate().readConfigurationData(path); + ArrayList> childNodes = new ArrayList>(); + if (original != null) { + childNodes.addAll(original.getChildren()); + qname = original.getNodeType(); + } else { + qname = path.getPath().get(path.getPath().size() - 1).getNodeType(); + } + + FluentIterable directChildren = FluentIterable.from(getStoredConfigurationPaths()) + .filter(new Predicate() { + @Override + public boolean apply(InstanceIdentifier input) { + if (path.contains(input)) { + int nesting = input.getPath().size() - path.getPath().size(); + if (nesting == 1) { + return true; + } + } + return false; + } + }); + for (InstanceIdentifier instanceIdentifier : directChildren) { + childNodes.add(getDelegate().readConfigurationData(instanceIdentifier)); + } + if (original == null && childNodes.isEmpty()) { + return null; + } + + return new CompositeNodeTOImpl(qname, null, childNodes); + } finally { + getDelegateReadLock().unlock(); + } + } + + @Override + public CompositeNode readOperationalData(final InstanceIdentifier path) { + getDelegateReadLock().lock(); + try { + if (path.getPath().isEmpty()) { + return null; + } + QName qname = null; + CompositeNode original = getDelegate().readOperationalData(path); + ArrayList> childNodes = new ArrayList>(); + if (original != null) { + childNodes.addAll(original.getChildren()); + qname = original.getNodeType(); + } else { + qname = path.getPath().get(path.getPath().size() - 1).getNodeType(); + } + + FluentIterable directChildren = FluentIterable.from(getStoredOperationalPaths()) + .filter(new Predicate() { + @Override + public boolean apply(InstanceIdentifier input) { + if (path.contains(input)) { + int nesting = input.getPath().size() - path.getPath().size(); + if (nesting == 1) { + return true; + } + } + return false; + } + }); + + for (InstanceIdentifier instanceIdentifier : directChildren) { + childNodes.add(getDelegate().readOperationalData(instanceIdentifier)); + } + if (original == null && childNodes.isEmpty()) { + return null; + } + + return new CompositeNodeTOImpl(qname, null, childNodes); + } finally { + getDelegateReadLock().unlock(); + } + } + } +}