<bundle>mvn:org.opendaylight.controller/sal-rest-connector/${project.version}</bundle>
<bundle>mvn:com.google.code.gson/gson/${gson.version}</bundle>
<bundle>mvn:org.opendaylight.yangtools/yang-data-codec-gson/${yangtools.version}</bundle>
+ <bundle>mvn:org.opendaylight.yangtools/yang-model-export/${yangtools.version}</bundle>
<bundle>mvn:com.sun.jersey/jersey-core/${jersey.version}</bundle>
<bundle>mvn:com.sun.jersey/jersey-server/${jersey.version}</bundle>
<bundle>mvn:com.sun.jersey/jersey-servlet/${jersey.version}</bundle>
-->
</feature>
+ <feature name="odl-nsf-service" description="OpenDaylight :: NSF :: Network Service Functions in Controller" version="${project.version}">
+ <feature version="${sal.version}">odl-adsal-all</feature>
+ <feature version="${project.version}">odl-nsf-controller-managers</feature>
+ <feature version="${project.version}">odl-adsal-controller-northbound</feature>
+ </feature>
+
<feature name="odl-nsf-managers" description="OpenDaylight :: AD-SAL :: Network Service Functions" version="${project.version}">
<feature version="${commons.opendaylight.version}">odl-base-all</feature>
<feature version="${sal.version}">odl-adsal-all</feature>
<bundle>mvn:org.opendaylight.controller/routing.dijkstra_implementation/${routing.dijkstra_implementation.version}</bundle>
</feature>
+ <feature name="odl-nsf-controller-managers" description="OpenDaylight :: AD-SAL :: Network Service Functions in Controller" version="${project.version}">
+ <feature version="${commons.opendaylight.version}">odl-base-all</feature>
+ <feature version="${sal.version}">odl-adsal-all</feature>
+ <bundle>mvn:org.opendaylight.controller/usermanager/${usermanager.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/usermanager.implementation/${usermanager.version}</bundle>
+
+ <bundle>mvn:org.opendaylight.controller/appauth/${appauth.version}</bundle>
+
+ <bundle>mvn:org.opendaylight.controller/connectionmanager/${connectionmanager.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/connectionmanager.implementation/${connectionmanager.version}</bundle>
+
+ <bundle>mvn:org.opendaylight.controller/containermanager/${containermanager.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/containermanager.implementation/${containermanager.version}</bundle>
+
+ <bundle>mvn:org.opendaylight.controller/statisticsmanager/${statisticsmanager.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/statisticsmanager.implementation/${statisticsmanager.implementation.version}</bundle>
+
+ <bundle>mvn:org.opendaylight.controller/switchmanager/${switchmanager.api.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/switchmanager.implementation/${switchmanager.implementation.version}</bundle>
+
+ <bundle>mvn:org.opendaylight.controller/forwardingrulesmanager/${forwardingrulesmanager.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/forwardingrulesmanager.implementation/${forwardingrulesmanager.implementation.version}</bundle>
+
+ <bundle>mvn:org.opendaylight.controller/topologymanager/${topologymanager.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/topologymanager.shell/${topologymanager.shell.version}</bundle>
+
+ <bundle>mvn:org.opendaylight.controller/hosttracker/${hosttracker.api.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/hosttracker.implementation/${hosttracker.implementation.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/hosttracker.shell/${hosttracker.shell.version}</bundle>
+
+ <bundle>mvn:org.opendaylight.controller/forwarding.staticrouting/${forwarding.staticrouting}</bundle>
+
+ <bundle>mvn:org.opendaylight.controller.thirdparty/net.sf.jung2/2.0.1</bundle>
+ <bundle>mvn:org.opendaylight.controller/routing.dijkstra_implementation/${routing.dijkstra_implementation.version}</bundle>
+ </feature>
+
<feature name="odl-adsal-northbound" description="OpenDaylight :: AD-SAL :: Northbound APIs" version="${project.version}">
<feature version="${commons.opendaylight.version}">odl-base-all</feature>
<feature version="${project.version}">odl-nsf-managers</feature>
<bundle>mvn:org.opendaylight.controller/topology.northbound/${topology.northbound.version}</bundle>
<bundle>mvn:org.opendaylight.controller/usermanager.northbound/${usermanager.northbound.version}</bundle>
</feature>
+
+ <feature name="odl-adsal-controller-northbound" description="OpenDaylight :: AD-SAL :: Northbound APIs in Controller" version="${project.version}">
+ <feature version="${commons.opendaylight.version}">odl-base-all</feature>
+ <feature version="${project.version}">odl-nsf-managers</feature>
+ <bundle>mvn:org.ow2.asm/asm-all/${asm.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/bundlescanner/${bundlescanner.api.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/bundlescanner.implementation/${bundlescanner.implementation.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/commons.northbound/${northbound.commons.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/connectionmanager.northbound/${connectionmanager.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/flowprogrammer.northbound/${flowprogrammer.northbound.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/hosttracker.northbound/${hosttracker.northbound.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/networkconfig.bridgedomain.northbound/${networkconfig.bridgedomain.northbound.version}</bundle>
+ <bundle>mvn:org.eclipse.persistence/org.eclipse.persistence.antlr/${eclipse.persistence.version}</bundle>
+ <bundle>mvn:org.eclipse.persistence/org.eclipse.persistence.core/${eclipse.persistence.version}</bundle>
+ <bundle>mvn:org.eclipse.persistence/org.eclipse.persistence.moxy/${eclipse.persistence.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/forwarding.staticrouting.northbound/${forwarding.staticrouting.northbound.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/statistics.northbound/${statistics.northbound.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/subnets.northbound/${subnets.northbound.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/switchmanager.northbound/${switchmanager.northbound.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/topology.northbound/${topology.northbound.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/usermanager.northbound/${usermanager.northbound.version}</bundle>
+ </feature>
</features>
<properties>
<mdsal.version>1.2.0-SNAPSHOT</mdsal.version>
<yangtools.version>0.7.0-SNAPSHOT</yangtools.version>
+ <configfile.directory>etc/opendaylight/karaf</configfile.directory>
</properties>
<dependencyManagement>
<dependencies>
<repository>mvn:org.opendaylight.yangtools/features-yangtools/${symbol_dollar}{yangtools.version}/xml/features</repository>
<repository>mvn:org.opendaylight.controller/features-mdsal/${symbol_dollar}{mdsal.version}/xml/features</repository>
<repository>mvn:org.opendaylight.controller/features-restconf/${symbol_dollar}{mdsal.version}/xml/features</repository>
- <feature name='odl-${artifactId}-api' version='${symbol_dollar}{project.version}' description='OpenDaylight :: ${artifactId} :: api '>
+ <feature name='odl-${artifactId}-api' version='${symbol_dollar}{project.version}' description='OpenDaylight :: ${artifactId} :: api'>
<feature version='${symbol_dollar}{yangtools.version}'>odl-yangtools-models</feature>
<bundle>mvn:${groupId}/${artifactId}-api/${symbol_dollar}{project.version}</bundle>
</feature>
- <feature name='odl-${artifactId}-impl' version='${symbol_dollar}{project.version}' description='OpenDaylight :: ${artifactId} :: impl '>
+ <feature name='odl-${artifactId}' version='${symbol_dollar}{project.version}' description='OpenDaylight :: ${artifactId}'>
<feature version='${symbol_dollar}{mdsal.version}'>odl-mdsal-broker</feature>
<feature version='${symbol_dollar}{project.version}'>odl-${artifactId}-api</feature>
<bundle>mvn:${groupId}/${artifactId}-impl/${symbol_dollar}{project.version}</bundle>
- <configfile finalname="${artifactId}-impl-default-config.xml">mvn:${groupId}/${artifactId}-impl/${symbol_dollar}{project.version}/xml/config</configfile>
+ <configfile finalname="${configfile.directory}/${artifactId}.xml">mvn:${groupId}/${artifactId}-impl/${symbol_dollar}{project.version}/xml/config</configfile>
</feature>
- <feature name='odl-${artifactId}-impl-rest' version='${symbol_dollar}{project.version}' description='OpenDaylight :: ${artifactId} :: impl :: REST '>
- <feature version="${symbol_dollar}{project.version}">odl-${artifactId}-impl</feature>
+ <feature name='odl-${artifactId}-rest' version='${symbol_dollar}{project.version}' description='OpenDaylight :: ${artifactId} :: REST'>
+ <feature version="${symbol_dollar}{project.version}">odl-${artifactId}</feature>
<feature version="${symbol_dollar}{mdsal.version}">odl-restconf</feature>
</feature>
- <feature name='odl-${artifactId}-impl-ui' version='${symbol_dollar}{project.version}' description='OpenDaylight :: ${artifactId} :: impl :: UI'>
- <feature version="${symbol_dollar}{project.version}">odl-${artifactId}-impl-rest</feature>
+ <feature name='odl-${artifactId}-ui' version='${symbol_dollar}{project.version}' description='OpenDaylight :: ${artifactId} :: UI'>
+ <feature version="${symbol_dollar}{project.version}">odl-${artifactId}-rest</feature>
<feature version="${symbol_dollar}{mdsal.version}">odl-mdsal-apidocs</feature>
<feature version="${symbol_dollar}{mdsal.version}">odl-mdsal-xsql</feature>
</feature>
* 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 ${package};
+package ${package}.impl;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
*/
package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${artifactId}.impl.rev141210;
-import ${package}.${classPrefix}Provider;
+import ${package}.impl.${classPrefix}Provider;
public class ${classPrefix}Module extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${artifactId}.impl.rev141210.Abstract${classPrefix}Module {
public ${classPrefix}Module(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
* 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 ${package};
+package ${package}.impl;
import org.junit.Test;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
import org.opendaylight.controller.config.api.JmxAttribute;
import org.opendaylight.controller.config.api.ModuleIdentifier;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
-import ${package}.${classPrefix}Provider;
+import ${package}.impl.${classPrefix}Provider;
import javax.management.ObjectName;
<maven>3.1.1</maven>
</prerequisites>
<properties>
- <karaf.localFeature>odl-${artifactId}-impl-ui</karaf.localFeature>
+ <karaf.localFeature>odl-${artifactId}-ui</karaf.localFeature>
</properties>
<dependencyManagement>
<dependencies>
<scope>runtime</scope>
</dependency>
</dependencies>
+ <!-- DO NOT install or deploy the karaf artifact -->
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-deploy-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-install-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
</project>
</plugin>
</plugins>
</build>
+
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/${artifactId}.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/${artifactId}.git</developerConnection>
+ <tag>HEAD</tag>
+ <url>https://wiki.opendaylight.org/view/${artifactId}:Main</url>
+ </scm>
</project>
Set<String> getAvailableModuleNames();
-
- /**
- * Find all runtime beans
- *
- * @return objectNames
- */
- Set<ObjectName> lookupRuntimeBeans();
-
- /**
- * Find all runtime of specified module
- *
- * @param moduleName
- * of bean
- * @param instanceName
- * of bean
- * @return objectNames
- */
- Set<ObjectName> lookupRuntimeBeans(String moduleName, String instanceName);
-
}
*/
Set<String> getAvailableModuleFactoryQNames();
+ /**
+ * Find all runtime beans
+ *
+ * @return objectNames
+ */
+ Set<ObjectName> lookupRuntimeBeans();
+
+ /**
+ * Find all runtime of specified module
+ *
+ * @param moduleName
+ * of bean
+ * @param instanceName
+ * of bean
+ * @return objectNames
+ */
+ Set<ObjectName> lookupRuntimeBeans(String moduleName, String instanceName);
}
public void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException {
txLookupRegistry.checkConfigBeanExists(objectName);
}
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Set<ObjectName> lookupRuntimeBeans() {
+ return txLookupRegistry.lookupRuntimeBeans();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Set<ObjectName> lookupRuntimeBeans(String moduleName,
+ String instanceName) {
+ return txLookupRegistry.lookupRuntimeBeans(moduleName, instanceName);
+ }
+
// --
/**
return ModuleQNameUtil.getQNames(allCurrentFactories);
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Set<ObjectName> lookupRuntimeBeans() {
+ return lookupRuntimeBeans("*", "*");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Set<ObjectName> lookupRuntimeBeans(String moduleName,
+ String instanceName) {
+ String finalModuleName = moduleName == null ? "*" : moduleName;
+ String finalInstanceName = instanceName == null ? "*" : instanceName;
+ ObjectName namePattern = ObjectNameUtil.createRuntimeBeanPattern(
+ finalModuleName, finalInstanceName);
+ return transactionJMXRegistrator.queryNames(namePattern, null);
+ }
@Override
public String toString() {
throw new UnsupportedOperationException();
}
+ @Override
+ public Set<ObjectName> lookupRuntimeBeans() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Set<ObjectName> lookupRuntimeBeans(final String moduleName, final String instanceName) {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public String toString() {
return "initial";
--- /dev/null
+package org.opendaylight.controller.config.util;
+
+import javax.management.ObjectName;
+
+/**
+ * Created by mmarsale on 20.2.2015.
+ */
+public interface BeanReader {
+ Object getAttributeCurrentValue(ObjectName on, String attributeName);
+}
import javax.management.ObjectName;
import org.opendaylight.controller.config.api.jmx.ConfigRegistryMXBean;
-public interface ConfigRegistryClient extends ConfigRegistryMXBean {
+public interface ConfigRegistryClient extends ConfigRegistryMXBean, BeanReader {
ConfigTransactionClient createTransaction();
Object invokeMethod(ObjectName on, String name, Object[] params,
String[] signature);
- Object getAttributeCurrentValue(ObjectName on, String attributeName);
-
}
} catch (AttributeNotFoundException | InstanceNotFoundException
| MBeanException | ReflectionException e) {
throw new RuntimeException("Unable to get attribute "
- + attributeName + " for " + on, e);
+ + attributeName + " for " + on + ". Available beans: " + lookupConfigBeans(), e);
}
}
import org.opendaylight.controller.config.api.jmx.ConfigTransactionControllerMXBean;
public interface ConfigTransactionClient extends
- ConfigTransactionControllerMXBean {
+ ConfigTransactionControllerMXBean, BeanReader {
CommitStatus commit() throws ConflictingVersionException,
ValidationException;
* @param on - ObjectName of the Object from which the attribute should be read
* @param jmxName - name of the attribute to be read
*
- * @return Attribute of Object on with attribute name jmxName
+ * @return Object of Object on with attribute name jmxName
*/
Attribute getAttribute(ObjectName on, String jmxName);
}
configTransactionControllerMXBeanProxy.checkServiceReferenceExists(objectName);
}
+ @Override
+ public Attribute getAttribute(ObjectName on, String attrName) {
+ if (ObjectNameUtil.getTransactionName(on) == null) {
+ throw new IllegalArgumentException("Not in transaction instance "
+ + on + ", no transaction name present");
+ }
+
+ try {
+ return new Attribute(attrName, configMBeanServer.getAttribute(on,attrName));
+ } catch (JMException e) {
+ throw new IllegalStateException("Unable to get attribute "
+ + attrName + " for " + on, e);
+ }
+ }
+
+ @Override
+ public Object getAttributeCurrentValue(ObjectName on, String attrName) {
+ return getAttribute(on, attrName).getValue();
+ }
+
@Override
public void validateBean(ObjectName configBeanON)
throws ValidationException {
}
@Override
- public Attribute getAttribute(ObjectName on, String attrName) {
- if (ObjectNameUtil.getTransactionName(on) == null) {
- throw new IllegalArgumentException("Not in transaction instance "
- + on + ", no transaction name present");
- }
+ public Set<String> getAvailableModuleFactoryQNames() {
+ return configTransactionControllerMXBeanProxy.getAvailableModuleFactoryQNames();
+ }
- try {
- return new Attribute(attrName, configMBeanServer.getAttribute(on,attrName));
- } catch (JMException e) {
- throw new IllegalStateException("Unable to get attribute "
- + attrName + " for " + on, e);
- }
+ @Override
+ public Set<ObjectName> lookupRuntimeBeans() {
+ return configTransactionControllerMXBeanProxy.lookupRuntimeBeans();
}
@Override
- public Set<String> getAvailableModuleFactoryQNames() {
- return configTransactionControllerMXBeanProxy.getAvailableModuleFactoryQNames();
+ public Set<ObjectName> lookupRuntimeBeans(final String moduleName, final String instanceName) {
+ return configTransactionControllerMXBeanProxy.lookupRuntimeBeans(moduleName, instanceName);
}
}
package org.opendaylight.controller.config.util;
import com.google.common.collect.Sets;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
return Sets.newHashSet("availableModuleFactoryQNames");
}
+ @Override
+ public Set<ObjectName> lookupRuntimeBeans() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Set<ObjectName> lookupRuntimeBeans(final String moduleName, final String instanceName) {
+ return Collections.emptySet();
+ }
+
@Override
public ObjectName getServiceReference(String serviceInterfaceQName, String refName) throws InstanceNotFoundException {
return conf3;
package org.opendaylight.controller.cluster.datastore;
import com.google.common.base.Preconditions;
-import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.AbstractFuture;
import com.google.common.util.concurrent.AbstractListeningExecutorService;
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
+import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
@Override
public CheckedFuture<Void, TransactionCommitFailedException> submit(DOMDataWriteTransaction transaction,
- Iterable<DOMStoreThreePhaseCommitCohort> cohorts) {
+ Collection<DOMStoreThreePhaseCommitCohort> cohorts) {
Preconditions.checkArgument(transaction != null, "Transaction must not be null.");
Preconditions.checkArgument(cohorts != null, "Cohorts must not be null.");
LOG.debug("Tx: {} is submitted for execution.", transaction.getIdentifier());
- final int cohortSize = Iterables.size(cohorts);
final AsyncNotifyingSettableFuture clientSubmitFuture =
new AsyncNotifyingSettableFuture(clientFutureCallbackExecutor);
- doCanCommit(clientSubmitFuture, transaction, cohorts, cohortSize);
+ doCanCommit(clientSubmitFuture, transaction, cohorts);
return MappingCheckedFuture.create(clientSubmitFuture,
TransactionCommitFailedExceptionMapper.COMMIT_ERROR_MAPPER);
private void doCanCommit(final AsyncNotifyingSettableFuture clientSubmitFuture,
final DOMDataWriteTransaction transaction,
- final Iterable<DOMStoreThreePhaseCommitCohort> cohorts, final int cohortSize) {
+ final Collection<DOMStoreThreePhaseCommitCohort> cohorts) {
final long startTime = System.nanoTime();
// Not using Futures.allAsList here to avoid its internal overhead.
- final AtomicInteger remaining = new AtomicInteger(cohortSize);
+ final AtomicInteger remaining = new AtomicInteger(cohorts.size());
FutureCallback<Boolean> futureCallback = new FutureCallback<Boolean>() {
@Override
public void onSuccess(Boolean result) {
if (result == null || !result) {
- handleException(clientSubmitFuture, transaction, cohorts, cohortSize,
+ handleException(clientSubmitFuture, transaction, cohorts,
CAN_COMMIT, TransactionCommitFailedExceptionMapper.CAN_COMMIT_ERROR_MAPPER,
new TransactionCommitFailedException(
"Can Commit failed, no detailed cause available."));
} else {
if(remaining.decrementAndGet() == 0) {
// All cohorts completed successfully - we can move on to the preCommit phase
- doPreCommit(startTime, clientSubmitFuture, transaction, cohorts, cohortSize);
+ doPreCommit(startTime, clientSubmitFuture, transaction, cohorts);
}
}
}
@Override
public void onFailure(Throwable t) {
- handleException(clientSubmitFuture, transaction, cohorts, cohortSize, CAN_COMMIT,
+ handleException(clientSubmitFuture, transaction, cohorts, CAN_COMMIT,
TransactionCommitFailedExceptionMapper.CAN_COMMIT_ERROR_MAPPER, t);
}
};
private void doPreCommit(final long startTime, final AsyncNotifyingSettableFuture clientSubmitFuture,
final DOMDataWriteTransaction transaction,
- final Iterable<DOMStoreThreePhaseCommitCohort> cohorts, final int cohortSize) {
+ final Collection<DOMStoreThreePhaseCommitCohort> cohorts) {
// Not using Futures.allAsList here to avoid its internal overhead.
- final AtomicInteger remaining = new AtomicInteger(cohortSize);
+ final AtomicInteger remaining = new AtomicInteger(cohorts.size());
FutureCallback<Void> futureCallback = new FutureCallback<Void>() {
@Override
public void onSuccess(Void notUsed) {
if(remaining.decrementAndGet() == 0) {
// All cohorts completed successfully - we can move on to the commit phase
- doCommit(startTime, clientSubmitFuture, transaction, cohorts, cohortSize);
+ doCommit(startTime, clientSubmitFuture, transaction, cohorts);
}
}
@Override
public void onFailure(Throwable t) {
- handleException(clientSubmitFuture, transaction, cohorts, cohortSize, PRE_COMMIT,
+ handleException(clientSubmitFuture, transaction, cohorts, PRE_COMMIT,
TransactionCommitFailedExceptionMapper.PRE_COMMIT_MAPPER, t);
}
};
private void doCommit(final long startTime, final AsyncNotifyingSettableFuture clientSubmitFuture,
final DOMDataWriteTransaction transaction,
- final Iterable<DOMStoreThreePhaseCommitCohort> cohorts, final int cohortSize) {
+ final Collection<DOMStoreThreePhaseCommitCohort> cohorts) {
// Not using Futures.allAsList here to avoid its internal overhead.
- final AtomicInteger remaining = new AtomicInteger(cohortSize);
+ final AtomicInteger remaining = new AtomicInteger(cohorts.size());
FutureCallback<Void> futureCallback = new FutureCallback<Void>() {
@Override
public void onSuccess(Void notUsed) {
@Override
public void onFailure(Throwable t) {
- handleException(clientSubmitFuture, transaction, cohorts, cohortSize, COMMIT,
+ handleException(clientSubmitFuture, transaction, cohorts, COMMIT,
TransactionCommitFailedExceptionMapper.COMMIT_ERROR_MAPPER, t);
}
};
private void handleException(final AsyncNotifyingSettableFuture clientSubmitFuture,
final DOMDataWriteTransaction transaction,
- final Iterable<DOMStoreThreePhaseCommitCohort> cohorts, int cohortSize,
+ final Collection<DOMStoreThreePhaseCommitCohort> cohorts,
final String phase, final TransactionCommitFailedExceptionMapper exMapper,
final Throwable t) {
// Transaction failed - tell all cohorts to abort.
@SuppressWarnings("unchecked")
- ListenableFuture<Void>[] canCommitFutures = new ListenableFuture[cohortSize];
+ ListenableFuture<Void>[] canCommitFutures = new ListenableFuture[cohorts.size()];
int i = 0;
for(DOMStoreThreePhaseCommitCohort cohort: cohorts) {
canCommitFutures[i++] = cohort.abort();
import com.google.common.base.Preconditions;
import java.io.Serializable;
+import java.util.Iterator;
import javax.annotation.Nonnull;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.yangtools.concepts.Immutable;
import org.opendaylight.yangtools.concepts.Path;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
/**
* A unique identifier for a particular subtree. It is composed of the logical
* data store type and the instance identifier of the root node.
*/
-public final class DOMDataTreeIdentifier implements Immutable, Path<DOMDataTreeIdentifier>, Serializable {
+public final class DOMDataTreeIdentifier implements Immutable, Path<DOMDataTreeIdentifier>, Serializable, Comparable<DOMDataTreeIdentifier> {
private static final long serialVersionUID = 1L;
private final YangInstanceIdentifier rootIdentifier;
private final LogicalDatastoreType datastoreType;
}
return rootIdentifier.equals(other.rootIdentifier);
}
+
+ @Override
+ public int compareTo(final DOMDataTreeIdentifier o) {
+ int i = datastoreType.compareTo(o.datastoreType);
+ if (i != 0) {
+ return i;
+ }
+
+ final Iterator<PathArgument> mi = rootIdentifier.getPathArguments().iterator();
+ final Iterator<PathArgument> oi = o.rootIdentifier.getPathArguments().iterator();
+
+ while (mi.hasNext()) {
+ if (!oi.hasNext()) {
+ return 1;
+ }
+
+ final PathArgument ma = mi.next();
+ final PathArgument oa = oi.next();
+ i = ma.compareTo(oa);
+ if (i != 0) {
+ return i;
+ }
+ }
+
+ return oi.hasNext() ? -1 : 0;
+ }
}
import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.CheckedFuture;
+import java.util.Collection;
import java.util.EnumMap;
import java.util.Map;
import java.util.Map.Entry;
* the Future fails with a {@link TransactionCommitFailedException}.
*/
protected abstract CheckedFuture<Void,TransactionCommitFailedException> submit(final DOMDataWriteTransaction transaction,
- final Iterable<DOMStoreThreePhaseCommitCohort> cohorts);
+ final Collection<DOMStoreThreePhaseCommitCohort> cohorts);
/**
* Creates a new composite read-only transaction
import com.google.common.base.Preconditions;
import com.google.common.base.Throwables;
-import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
+import java.util.Collection;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
};
private static final Logger LOG = LoggerFactory.getLogger(CommitCoordinationTask.class);
- private final Iterable<DOMStoreThreePhaseCommitCohort> cohorts;
+ private final Collection<DOMStoreThreePhaseCommitCohort> cohorts;
private final DurationStatisticsTracker commitStatTracker;
private final DOMDataWriteTransaction tx;
- private final int cohortSize;
public CommitCoordinationTask(final DOMDataWriteTransaction transaction,
- final Iterable<DOMStoreThreePhaseCommitCohort> cohorts,
+ final Collection<DOMStoreThreePhaseCommitCohort> cohorts,
final DurationStatisticsTracker commitStatTracker) {
this.tx = Preconditions.checkNotNull(transaction, "transaction must not be null");
this.cohorts = Preconditions.checkNotNull(cohorts, "cohorts must not be null");
this.commitStatTracker = commitStatTracker;
- this.cohortSize = Iterables.size(cohorts);
}
@Override
*
*/
private ListenableFuture<?>[] canCommitAll() {
- final ListenableFuture<?>[] ops = new ListenableFuture<?>[cohortSize];
+ final ListenableFuture<?>[] ops = new ListenableFuture<?>[cohorts.size()];
int i = 0;
for (DOMStoreThreePhaseCommitCohort cohort : cohorts) {
ops[i++] = cohort.canCommit();
*
*/
private ListenableFuture<?>[] preCommitAll() {
- final ListenableFuture<?>[] ops = new ListenableFuture<?>[cohortSize];
+ final ListenableFuture<?>[] ops = new ListenableFuture<?>[cohorts.size()];
int i = 0;
for (DOMStoreThreePhaseCommitCohort cohort : cohorts) {
ops[i++] = cohort.preCommit();
* @return List of all cohorts futures from can commit phase.
*/
private ListenableFuture<?>[] commitAll() {
- final ListenableFuture<?>[] ops = new ListenableFuture<?>[cohortSize];
+ final ListenableFuture<?>[] ops = new ListenableFuture<?>[cohorts.size()];
int i = 0;
for (DOMStoreThreePhaseCommitCohort cohort : cohorts) {
ops[i++] = cohort.commit();
*/
private ListenableFuture<Void> abortAsyncAll() {
- final ListenableFuture<?>[] ops = new ListenableFuture<?>[cohortSize];
+ final ListenableFuture<?>[] ops = new ListenableFuture<?>[cohorts.size()];
int i = 0;
for (DOMStoreThreePhaseCommitCohort cohort : cohorts) {
ops[i++] = cohort.abort();
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
+import java.util.Collection;
import java.util.Map;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import java.util.concurrent.atomic.AtomicLong;
@Override
public CheckedFuture<Void, TransactionCommitFailedException> submit(
- final DOMDataWriteTransaction transaction, final Iterable<DOMStoreThreePhaseCommitCohort> cohorts) {
+ final DOMDataWriteTransaction transaction, final Collection<DOMStoreThreePhaseCommitCohort> cohorts) {
checkNotFailed();
checkNotClosed();
/*
* This forces allocateTransaction() on a slow path, which has to happen after
- * this method has completed executing.
+ * this method has completed executing. Also inflightTx may be updated outside
+ * the lock, hence we need to re-check.
*/
@GuardedBy("this")
private void processIfReady() {
- final PingPongTransaction tx = READY_UPDATER.getAndSet(this, null);
- if (tx != null) {
- processTransaction(tx);
+ if (inflightTx == null) {
+ final PingPongTransaction tx = READY_UPDATER.getAndSet(this, null);
+ if (tx != null) {
+ processTransaction(tx);
+ }
}
}
}
@Override
- public void close() {
+ public synchronized void close() {
final PingPongTransaction notLocked = lockedTx;
Preconditions.checkState(notLocked == null, "Attempted to close chain with outstanding transaction %s", notLocked);
- synchronized (this) {
- processIfReady();
- delegate.close();
+ // Force allocations on slow path. We will complete the rest
+ final PingPongTransaction tx = READY_UPDATER.getAndSet(this, null);
+
+ // Make sure no transaction is outstanding. Otherwise sleep a bit and retry
+ while (inflightTx != null) {
+ LOG.debug("Busy-waiting for in-flight transaction {} to complete", inflightTx);
+ Thread.yield();
+ continue;
}
+
+ // If we have an outstanding transaction, send it down
+ if (tx != null) {
+ processTransaction(tx);
+ }
+
+ // All done, close the delegate. All new allocations should fail.
+ delegate.close();
}
@Override
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
+import java.util.Collection;
import java.util.Map;
import java.util.concurrent.RejectedExecutionException;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
@Override
protected CheckedFuture<Void,TransactionCommitFailedException> submit(final DOMDataWriteTransaction transaction,
- final Iterable<DOMStoreThreePhaseCommitCohort> cohorts) {
+ final Collection<DOMStoreThreePhaseCommitCohort> cohorts) {
Preconditions.checkArgument(transaction != null, "Transaction must not be null.");
Preconditions.checkArgument(cohorts != null, "Cohorts must not be null.");
LOG.debug("Tx: {} is submitted for execution.", transaction.getIdentifier());
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco 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.md.sal.dom.broker.impl;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeIdentifier;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeShard;
+import org.opendaylight.yangtools.concepts.AbstractListenerRegistration;
+
+final class ShardRegistration<T extends DOMDataTreeShard> extends AbstractListenerRegistration<T> {
+ private final DOMDataTreeIdentifier prefix;
+ private final ShardedDOMDataTree tree;
+
+ protected ShardRegistration(final ShardedDOMDataTree tree, final DOMDataTreeIdentifier prefix, final T shard) {
+ super(shard);
+ this.tree = Preconditions.checkNotNull(tree);
+ this.prefix = Preconditions.checkNotNull(prefix);
+ }
+
+ DOMDataTreeIdentifier getPrefix() {
+ return prefix;
+ }
+
+ @Override
+ protected void removeRegistration() {
+ tree.removeShard(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco 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.md.sal.dom.broker.impl;
+
+import com.google.common.base.Preconditions;
+import java.util.Collection;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.TreeMap;
+import javax.annotation.concurrent.GuardedBy;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeIdentifier;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeListener;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeProducer;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeService;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeShard;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeShardingConflictException;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeShardingService;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class ShardedDOMDataTree implements DOMDataTreeService, DOMDataTreeShardingService {
+ private static final Logger LOG = LoggerFactory.getLogger(ShardedDOMDataTree.class);
+ private final Map<LogicalDatastoreType, ShardingTableEntry> shardingTables = new EnumMap<>(LogicalDatastoreType.class);
+ @GuardedBy("this")
+ private final Map<DOMDataTreeIdentifier, DOMDataTreeProducer> idToProducer = new TreeMap<>();
+
+ @GuardedBy("this")
+ private ShardingTableEntry lookupShard(final DOMDataTreeIdentifier prefix) {
+ final ShardingTableEntry t = shardingTables.get(prefix.getDatastoreType());
+ if (t == null) {
+ return null;
+ }
+
+ return t.lookup(prefix.getRootIdentifier());
+ }
+
+ @GuardedBy("this")
+ private void storeShard(final DOMDataTreeIdentifier prefix, final ShardRegistration<?> reg) {
+ ShardingTableEntry t = shardingTables.get(prefix.getDatastoreType());
+ if (t == null) {
+ t = new ShardingTableEntry();
+ shardingTables.put(prefix.getDatastoreType(), t);
+ }
+
+ t.store(prefix.getRootIdentifier(), reg);
+ }
+
+ void removeShard(final ShardRegistration<?> reg) {
+ final DOMDataTreeIdentifier prefix = reg.getPrefix();
+ final ShardRegistration<?> parentReg;
+
+ synchronized (this) {
+ final ShardingTableEntry t = shardingTables.get(prefix.getDatastoreType());
+ if (t == null) {
+ LOG.warn("Shard registration {} points to non-existent table", reg);
+ return;
+ }
+
+ t.remove(prefix.getRootIdentifier());
+ parentReg = lookupShard(prefix).getRegistration();
+
+ /*
+ * FIXME: adjust all producers. This is tricky, as we need different locking strategy,
+ * simply because we risk AB/BA deadlock with a producer being split off from
+ * a producer.
+ *
+ */
+ }
+
+ if (parentReg != null) {
+ parentReg.getInstance().onChildDetached(prefix, reg.getInstance());
+ }
+ }
+
+ @Override
+ public <T extends DOMDataTreeShard> ListenerRegistration<T> registerDataTreeShard(final DOMDataTreeIdentifier prefix, final T shard) throws DOMDataTreeShardingConflictException {
+ final ShardRegistration<T> reg;
+ final ShardRegistration<?> parentReg;
+
+ synchronized (this) {
+ /*
+ * Lookup the parent shard (e.g. the one which currently matches the prefix),
+ * and if it exists, check if its registration prefix does not collide with
+ * this registration.
+ */
+ final ShardingTableEntry parent = lookupShard(prefix);
+ parentReg = parent.getRegistration();
+ if (parentReg != null && prefix.equals(parentReg.getPrefix())) {
+ throw new DOMDataTreeShardingConflictException(String.format("Prefix %s is already occupied by shard {}", prefix, parentReg.getInstance()));
+ }
+
+ // FIXME: wrap the shard in a proper adaptor based on implemented interface
+
+ reg = new ShardRegistration<T>(this, prefix, shard);
+
+ storeShard(prefix, reg);
+
+ // FIXME: update any producers/registrations
+ }
+
+ // Notify the parent shard
+ if (parentReg != null) {
+ parentReg.getInstance().onChildAttached(prefix, shard);
+ }
+
+ return reg;
+ }
+
+ @GuardedBy("this")
+ private DOMDataTreeProducer findProducer(final DOMDataTreeIdentifier subtree) {
+ for (Entry<DOMDataTreeIdentifier, DOMDataTreeProducer> e : idToProducer.entrySet()) {
+ if (e.getKey().contains(subtree)) {
+ return e.getValue();
+ }
+ }
+
+ return null;
+ }
+
+ synchronized void destroyProducer(final ShardedDOMDataTreeProducer producer) {
+ for (DOMDataTreeIdentifier s : producer.getSubtrees()) {
+ DOMDataTreeProducer r = idToProducer.remove(s);
+ if (!producer.equals(r)) {
+ LOG.error("Removed producer %s on subtree %s while removing %s", r, s, producer);
+ }
+ }
+ }
+
+ @GuardedBy("this")
+ private DOMDataTreeProducer createProducer(final Map<DOMDataTreeIdentifier, DOMDataTreeShard> shardMap) {
+ // Record the producer's attachment points
+ final DOMDataTreeProducer ret = ShardedDOMDataTreeProducer.create(this, shardMap);
+ for (DOMDataTreeIdentifier s : shardMap.keySet()) {
+ idToProducer.put(s, ret);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public synchronized DOMDataTreeProducer createProducer(final Collection<DOMDataTreeIdentifier> subtrees) {
+ Preconditions.checkArgument(!subtrees.isEmpty(), "Subtrees may not be empty");
+
+ final Map<DOMDataTreeIdentifier, DOMDataTreeShard> shardMap = new HashMap<>();
+ for (DOMDataTreeIdentifier s : subtrees) {
+ // Attempting to create a disconnected producer -- all subtrees have to be unclaimed
+ final DOMDataTreeProducer producer = findProducer(s);
+ Preconditions.checkArgument(producer == null, "Subtree %s is attached to producer %s", s, producer);
+
+ shardMap.put(s, lookupShard(s).getRegistration().getInstance());
+ }
+
+ return createProducer(shardMap);
+ }
+
+ synchronized DOMDataTreeProducer createProducer(final ShardedDOMDataTreeProducer parent, final Collection<DOMDataTreeIdentifier> subtrees) {
+ Preconditions.checkNotNull(parent);
+
+ final Map<DOMDataTreeIdentifier, DOMDataTreeShard> shardMap = new HashMap<>();
+ for (DOMDataTreeIdentifier s : subtrees) {
+ shardMap.put(s, lookupShard(s).getRegistration().getInstance());
+ }
+
+ return createProducer(shardMap);
+ }
+
+ @Override
+ public synchronized <T extends DOMDataTreeListener> ListenerRegistration<T> registerListener(final T listener, final Collection<DOMDataTreeIdentifier> subtrees, final boolean allowRxMerges, final Collection<DOMDataTreeProducer> producers) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco 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.md.sal.dom.broker.impl;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.BiMap;
+import com.google.common.collect.ImmutableBiMap;
+import com.google.common.collect.ImmutableBiMap.Builder;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Queue;
+import java.util.Set;
+import javax.annotation.concurrent.GuardedBy;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeIdentifier;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeProducer;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeProducerBusyException;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeProducerException;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeShard;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
+import org.opendaylight.controller.sal.core.spi.data.DOMStore;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class ShardedDOMDataTreeProducer implements DOMDataTreeProducer {
+ private static final Logger LOG = LoggerFactory.getLogger(ShardedDOMDataTreeProducer.class);
+ private final BiMap<DOMDataTreeShard, DOMStoreTransactionChain> shardToChain;
+ private final Map<DOMDataTreeIdentifier, DOMDataTreeShard> idToShard;
+ private final ShardedDOMDataTree dataTree;
+
+ @GuardedBy("this")
+ private Map<DOMDataTreeIdentifier, DOMDataTreeProducer> children = Collections.emptyMap();
+ @GuardedBy("this")
+ private DOMDataWriteTransaction openTx;
+ @GuardedBy("this")
+ private boolean closed;
+
+ ShardedDOMDataTreeProducer(final ShardedDOMDataTree dataTree, final Map<DOMDataTreeIdentifier, DOMDataTreeShard> shardMap, final Set<DOMDataTreeShard> shards) {
+ this.dataTree = Preconditions.checkNotNull(dataTree);
+
+ // Create shard -> chain map
+ final Builder<DOMDataTreeShard, DOMStoreTransactionChain> cb = ImmutableBiMap.builder();
+ final Queue<Exception> es = new LinkedList<>();
+
+ for (DOMDataTreeShard s : shards) {
+ if (s instanceof DOMStore) {
+ try {
+ final DOMStoreTransactionChain c = ((DOMStore)s).createTransactionChain();
+ LOG.trace("Using DOMStore chain {} to access shard {}", c, s);
+ cb.put(s, c);
+ } catch (Exception e) {
+ LOG.error("Failed to instantiate chain for shard {}", s, e);
+ es.add(e);
+ }
+ } else {
+ LOG.error("Unhandled shard instance type {}", s.getClass());
+ }
+ }
+ this.shardToChain = cb.build();
+
+ // An error was encountered, close chains and report the error
+ if (shardToChain.size() != shards.size()) {
+ for (DOMStoreTransactionChain c : shardToChain.values()) {
+ try {
+ c.close();
+ } catch (Exception e) {
+ LOG.warn("Exception raised while closing chain %s", c, e);
+ }
+ }
+
+ final IllegalStateException e = new IllegalStateException("Failed to completely allocate contexts", es.poll());
+ while (!es.isEmpty()) {
+ e.addSuppressed(es.poll());
+ }
+
+ throw e;
+ }
+
+ idToShard = ImmutableMap.copyOf(shardMap);
+ }
+
+ @Override
+ public synchronized DOMDataWriteTransaction createTransaction(final boolean isolated) {
+ Preconditions.checkState(!closed, "Producer is already closed");
+ Preconditions.checkState(openTx == null, "Transaction %s is still open", openTx);
+
+ // Allocate backing transactions
+ final Map<DOMDataTreeShard, DOMStoreWriteTransaction> shardToTx = new HashMap<>();
+ for (Entry<DOMDataTreeShard, DOMStoreTransactionChain> e : shardToChain.entrySet()) {
+ shardToTx.put(e.getKey(), e.getValue().newWriteOnlyTransaction());
+ }
+
+ // Create the ID->transaction map
+ final ImmutableMap.Builder<DOMDataTreeIdentifier, DOMStoreWriteTransaction> b = ImmutableMap.builder();
+ for (Entry<DOMDataTreeIdentifier, DOMDataTreeShard> e : idToShard.entrySet()) {
+ b.put(e.getKey(), shardToTx.get(e.getValue()));
+ }
+
+ final ShardedDOMDataWriteTransaction ret = new ShardedDOMDataWriteTransaction(this, b.build());
+ openTx = ret;
+ return ret;
+ }
+
+ @GuardedBy("this")
+ private boolean haveSubtree(final DOMDataTreeIdentifier subtree) {
+ for (DOMDataTreeIdentifier i : idToShard.keySet()) {
+ if (i.contains(subtree)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ @GuardedBy("this")
+ private DOMDataTreeProducer lookupChild(final DOMDataTreeIdentifier s) {
+ for (Entry<DOMDataTreeIdentifier, DOMDataTreeProducer> e : children.entrySet()) {
+ if (e.getKey().contains(s)) {
+ return e.getValue();
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public synchronized DOMDataTreeProducer createProducer(final Collection<DOMDataTreeIdentifier> subtrees) {
+ Preconditions.checkState(!closed, "Producer is already closed");
+ Preconditions.checkState(openTx == null, "Transaction %s is still open", openTx);
+
+ for (DOMDataTreeIdentifier s : subtrees) {
+ // Check if the subtree was visible at any time
+ if (!haveSubtree(s)) {
+ throw new IllegalArgumentException(String.format("Subtree %s was never available in producer %s", s, this));
+ }
+
+ // Check if the subtree has not been delegated to a child
+ final DOMDataTreeProducer child = lookupChild(s);
+ Preconditions.checkArgument(child == null, "Subtree %s is delegated to child producer %s", s, child);
+
+ // Check if part of the requested subtree is not delegated to a child.
+ for (DOMDataTreeIdentifier c : children.keySet()) {
+ if (s.contains(c)) {
+ throw new IllegalArgumentException(String.format("Subtree %s cannot be delegated as it is superset of already-delegated %s", s, c));
+ }
+ }
+ }
+
+ final DOMDataTreeProducer ret = dataTree.createProducer(this, subtrees);
+ final ImmutableMap.Builder<DOMDataTreeIdentifier, DOMDataTreeProducer> cb = ImmutableMap.builder();
+ cb.putAll(children);
+ for (DOMDataTreeIdentifier s : subtrees) {
+ cb.put(s, ret);
+ }
+
+ children = cb.build();
+ return ret;
+ }
+
+ @Override
+ public synchronized void close() throws DOMDataTreeProducerException {
+ if (!closed) {
+ if (openTx != null) {
+ throw new DOMDataTreeProducerBusyException(String.format("Transaction %s is still open", openTx));
+ }
+
+ closed = true;
+ dataTree.destroyProducer(this);
+ }
+ }
+
+ static DOMDataTreeProducer create(final ShardedDOMDataTree dataTree, final Map<DOMDataTreeIdentifier, DOMDataTreeShard> shardMap) {
+ /*
+ * FIXME: we do not allow multiple multiple shards in a producer because we do not implement the
+ * synchronization primitives yet
+ */
+ final Set<DOMDataTreeShard> shards = ImmutableSet.copyOf(shardMap.values());
+ if (shards.size() > 1) {
+ throw new UnsupportedOperationException("Cross-shard producers are not supported yet");
+ }
+
+ return new ShardedDOMDataTreeProducer(dataTree, shardMap, shards);
+ }
+
+ Set<DOMDataTreeIdentifier> getSubtrees() {
+ return idToShard.keySet();
+ }
+
+ synchronized void cancelTransaction(final ShardedDOMDataWriteTransaction transaction) {
+ if (!openTx.equals(transaction)) {
+ LOG.warn("Transaction {} is not open in producer {}", transaction, this);
+ return;
+ }
+
+ LOG.debug("Transaction {} cancelled", transaction);
+ openTx = null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco 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.md.sal.dom.broker.impl;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicLong;
+import javax.annotation.concurrent.GuardedBy;
+import javax.annotation.concurrent.NotThreadSafe;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.controller.md.sal.common.impl.service.AbstractDataTransaction;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeIdentifier;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@NotThreadSafe
+final class ShardedDOMDataWriteTransaction implements DOMDataWriteTransaction {
+ private static final Logger LOG = LoggerFactory.getLogger(ShardedDOMDataWriteTransaction.class);
+ private static final AtomicLong COUNTER = new AtomicLong();
+ private final Map<DOMDataTreeIdentifier, DOMStoreWriteTransaction> idToTransaction;
+ private final ShardedDOMDataTreeProducer producer;
+ private final String identifier;
+ @GuardedBy("this")
+ private boolean closed = false;
+
+ ShardedDOMDataWriteTransaction(final ShardedDOMDataTreeProducer producer, final Map<DOMDataTreeIdentifier, DOMStoreWriteTransaction> idToTransaction) {
+ this.producer = Preconditions.checkNotNull(producer);
+ this.idToTransaction = Preconditions.checkNotNull(idToTransaction);
+ this.identifier = "SHARDED-DOM-" + COUNTER.getAndIncrement();
+ }
+
+ // FIXME: use atomic operations
+ @GuardedBy("this")
+ private DOMStoreWriteTransaction lookup(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
+ final DOMDataTreeIdentifier id = new DOMDataTreeIdentifier(store, path);
+
+ for (Entry<DOMDataTreeIdentifier, DOMStoreWriteTransaction> e : idToTransaction.entrySet()) {
+ if (e.getKey().contains(id)) {
+ return e.getValue();
+ }
+ }
+
+ throw new IllegalArgumentException(String.format("Path %s is not acessible from transaction %s", id, this));
+ }
+
+ @Override
+ public String getIdentifier() {
+ return identifier;
+ }
+
+ @Override
+ public synchronized boolean cancel() {
+ if (closed) {
+ return false;
+ }
+
+ LOG.debug("Cancelling transaction {}", identifier);
+ for (DOMStoreWriteTransaction tx : ImmutableSet.copyOf(idToTransaction.values())) {
+ tx.close();
+ }
+
+ closed = true;
+ producer.cancelTransaction(this);
+ return true;
+ }
+
+ @Override
+ public synchronized CheckedFuture<Void, TransactionCommitFailedException> submit() {
+ Preconditions.checkState(!closed, "Transaction %s is already closed", identifier);
+
+ final Set<DOMStoreWriteTransaction> txns = ImmutableSet.copyOf(idToTransaction.values());
+ final List<DOMStoreThreePhaseCommitCohort> cohorts = new ArrayList<>(txns.size());
+ for (DOMStoreWriteTransaction tx : txns) {
+ cohorts.add(tx.ready());
+ }
+
+ try {
+ return Futures.immediateCheckedFuture(new CommitCoordinationTask(this, cohorts, null).call());
+ } catch (TransactionCommitFailedException e) {
+ return Futures.immediateFailedCheckedFuture(e);
+ }
+ }
+
+ @Override
+ @Deprecated
+ public ListenableFuture<RpcResult<TransactionStatus>> commit() {
+ return AbstractDataTransaction.convertToLegacyCommitFuture(submit());
+ }
+
+ @Override
+ public synchronized void delete(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
+ lookup(store, path).delete(path);
+ }
+
+ @Override
+ public synchronized void put(final LogicalDatastoreType store, final YangInstanceIdentifier path, final NormalizedNode<?, ?> data) {
+ lookup(store, path).write(path, data);
+ }
+
+ @Override
+ public synchronized void merge(final LogicalDatastoreType store, final YangInstanceIdentifier path, final NormalizedNode<?, ?> data) {
+ lookup(store, path).merge(path, data);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco 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.md.sal.dom.broker.impl;
+
+import com.google.common.base.Preconditions;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+import org.opendaylight.yangtools.concepts.Identifiable;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class ShardingTableEntry implements Identifiable<PathArgument> {
+ private static final Logger LOG = LoggerFactory.getLogger(ShardingTableEntry.class);
+ private final Map<PathArgument, ShardingTableEntry> children = Collections.emptyMap();
+ private final PathArgument identifier;
+ private ShardRegistration<?> registration;
+
+ ShardingTableEntry() {
+ identifier = null;
+ }
+
+ ShardingTableEntry(final PathArgument identifier) {
+ this.identifier = Preconditions.checkNotNull(identifier);
+ }
+
+ @Override
+ public PathArgument getIdentifier() {
+ return identifier;
+ }
+
+ public ShardRegistration<?> getRegistration() {
+ return registration;
+ }
+
+ ShardingTableEntry lookup(final YangInstanceIdentifier id) {
+ final Iterator<PathArgument> it = id.getPathArguments().iterator();
+ ShardingTableEntry entry = this;
+
+ while (it.hasNext()) {
+ final PathArgument a = it.next();
+ final ShardingTableEntry child = entry.children.get(a);
+ if (child == null) {
+ LOG.debug("Lookup of {} stopped at {}", id, a);
+ break;
+ }
+
+ entry = child;
+ }
+
+ return entry;
+ }
+
+ void store(final YangInstanceIdentifier id, final ShardRegistration<?> reg) {
+ final Iterator<PathArgument> it = id.getPathArguments().iterator();
+ ShardingTableEntry entry = this;
+
+ while (it.hasNext()) {
+ final PathArgument a = it.next();
+ ShardingTableEntry child = entry.children.get(a);
+ if (child == null) {
+ child = new ShardingTableEntry(a);
+ entry.children.put(a, child);
+ }
+ }
+
+ Preconditions.checkState(entry.registration == null);
+ entry.registration = reg;
+ }
+
+ private boolean remove(final Iterator<PathArgument> it) {
+ if (it.hasNext()) {
+ final PathArgument arg = it.next();
+ final ShardingTableEntry child = children.get(arg);
+ if (child != null) {
+ if (child.remove(it)) {
+ children.remove(arg);
+ }
+ } else {
+ LOG.warn("Cannot remove non-existent child {}", arg);
+ }
+ }
+
+ return registration == null && children.isEmpty();
+ }
+
+ void remove(final YangInstanceIdentifier id) {
+ this.remove(id.getPathArguments().iterator());
+ }
+}
request.future.set( RpcResultBuilder.<NetconfMessage>failed()
.withRpcError( NetconfMessageTransformUtil.toRpcError( e ) ).build() );
+
+ //recursively processing message to eventually find matching request
+ processMessage(message);
+
return;
}
return new NetconfMessage( doc );
}
+ //Test scenario verifying whether missing message is handled
+ @Test
+ public void testOnMissingResponseMessage() throws Exception {
+
+ setupSession();
+
+ String messageID1 = UUID.randomUUID().toString();
+ ListenableFuture<RpcResult<NetconfMessage>> resultFuture1 = sendRequest( messageID1 );
+
+ String messageID2 = UUID.randomUUID().toString();
+ ListenableFuture<RpcResult<NetconfMessage>> resultFuture2 = sendRequest( messageID2 );
+
+ String messageID3 = UUID.randomUUID().toString();
+ ListenableFuture<RpcResult<NetconfMessage>> resultFuture3 = sendRequest( messageID3 );
+
+ //response messages 1,2 are omitted
+ communicator.onMessage( mockSession, createSuccessResponseMessage( messageID3 ) );
+
+ verifyResponseMessage( resultFuture3.get(), messageID3 );
+ }
+
@Test
public void testOnSuccessfulResponseMessage() throws Exception {
setupSession();
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-data-codec-gson</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-model-export</artifactId>
+ <!-- FIXME: remove explicit version, once model export package is part of yangtools-artefacts -->
+ <version>0.7.0-SNAPSHOT</version>
+ </dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<Private-Package>org.opendaylight.controller.sal.rest.*,
org.opendaylight.controller.sal.restconf.rpc.*,
org.opendaylight.controller.sal.restconf.impl,
+ org.opendaylight.controller.md.sal.rest.common.*,
org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.rest.connector.rev140724.*,
</Private-Package>
<Import-Package>*,
--- /dev/null
+/**
+ * Copyright (c) 2015 Cisco 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.md.sal.rest.common;
+
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
+
+/**
+ * sal-rest-connector
+ * org.opendaylight.controller.md.sal.rest.common
+ *
+ * Utility class is centralizing all needed validation functionality for a Restconf osgi module.
+ * All methods have to throw {@link RestconfDocumentedException} only, which is a representation
+ * for all error situation followed by restconf-netconf specification.
+ * @see {@link https://tools.ietf.org/html/draft-bierman-netconf-restconf-02}
+ *
+ * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
+ *
+ * Created: Feb 24, 2015
+ */
+public class RestconfValidationUtils {
+
+ private RestconfValidationUtils () {
+ throw new UnsupportedOperationException("Utility class");
+ }
+
+ /**
+ * Method returns {@link RestconfDocumentedException} for a false condition.
+ *
+ * @param condition - condition for rise {@link RestconfDocumentedException}
+ * @param type - input {@link ErrorType} for create {@link RestconfDocumentedException}
+ * @param tag - input {@link ErrorTag} for create {@link RestconfDocumentedException}
+ * @param message - input error message for create {@link RestconfDocumentedException}
+ */
+ public static void checkDocumentedError(final boolean condition, final ErrorType type,
+ final ErrorTag tag, final String message) {
+ if(!condition) {
+ throw new RestconfDocumentedException(message, type, tag);
+ }
+ }
+
+ /**
+ * Method returns {@link RestconfDocumentedException} if value is NULL or same input value.
+ * {@link ErrorType} is relevant for server application layer
+ * {@link ErrorTag} is 404 data-missing
+ * @see {@link https://tools.ietf.org/html/draft-bierman-netconf-restconf-02}
+ *
+ * @param value - some value from {@link org.opendaylight.yangtools.yang.model.api.Module}
+ * @param moduleName - name of {@link org.opendaylight.yangtools.yang.model.api.Module}
+ * @return - T value (same input value)
+ */
+ public static <T> T checkNotNullDocumented(final T value, final String moduleName) {
+ if(value == null) {
+ final String errMsg = "Module " + moduleName + "was not found.";
+ throw new RestconfDocumentedException(errMsg, ErrorType.APPLICATION, ErrorTag.DATA_MISSING);
+ }
+ return value;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco 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.md.sal.rest.schema;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+@Provider
+@Produces(SchemaRetrievalService.YANG_MEDIA_TYPE)
+public class SchemaExportContentYangBodyWriter implements MessageBodyWriter<SchemaExportContext> {
+
+ @Override
+ public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return type.equals(SchemaExportContext.class);
+ }
+
+ @Override
+ public long getSize(final SchemaExportContext t, final Class<?> type, final Type genericType,
+ final Annotation[] annotations, final MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(final SchemaExportContext t, final Class<?> type, final Type genericType,
+ final Annotation[] annotations, final MediaType mediaType,
+ final MultivaluedMap<String, Object> httpHeaders, final OutputStream entityStream) throws IOException,
+ WebApplicationException {
+ final PrintWriter writer = new PrintWriter(entityStream);
+ writer.write(t.getModule().getSource());
+
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco 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.md.sal.rest.schema;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+import javax.xml.stream.XMLStreamException;
+import org.opendaylight.yangtools.yang.model.export.YinExportUtils;
+
+@Provider
+@Produces(SchemaRetrievalService.YIN_MEDIA_TYPE)
+public class SchemaExportContentYinBodyWriter implements MessageBodyWriter<SchemaExportContext> {
+
+ @Override
+ public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations,
+ final MediaType mediaType) {
+ return type.equals(SchemaExportContext.class);
+ }
+
+ @Override
+ public long getSize(final SchemaExportContext t, final Class<?> type, final Type genericType,
+ final Annotation[] annotations, final MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(final SchemaExportContext t, final Class<?> type, final Type genericType,
+ final Annotation[] annotations, final MediaType mediaType,
+ final MultivaluedMap<String, Object> httpHeaders, final OutputStream entityStream) throws IOException,
+ WebApplicationException {
+ try {
+ YinExportUtils.writeModuleToOutputStream(t.getSchemaContext(), t.getModule(), entityStream);
+ } catch (final XMLStreamException e) {
+ throw new IllegalStateException(e);
+ }
+
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco 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.md.sal.rest.schema;
+
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public class SchemaExportContext {
+
+ private final SchemaContext schemaContext;
+ private final Module module;
+
+ public SchemaExportContext(final SchemaContext ctx, final Module module) {
+ schemaContext = ctx;
+ this.module = module;
+ }
+
+ public SchemaContext getSchemaContext() {
+ return schemaContext;
+ }
+
+ public Module getModule() {
+ return module;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco 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.md.sal.rest.schema;
+
+import com.google.common.annotations.Beta;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+
+@Beta
+public interface SchemaRetrievalService {
+
+ public static final String YANG_MEDIA_TYPE = "application/yang";
+ public static final String YIN_MEDIA_TYPE = "application/yin+xml";
+
+ @GET
+ @Produces({YIN_MEDIA_TYPE,YANG_MEDIA_TYPE})
+ @Path("/modules/module/{identifier:.+}/schema")
+ SchemaExportContext getSchema(@PathParam("identifier") String mountAndModuleId);
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco 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.md.sal.rest.schema;
+
+import com.google.common.base.Splitter;
+import com.google.common.collect.Iterables;
+import java.text.ParseException;
+import java.util.Date;
+import java.util.Iterator;
+import org.opendaylight.controller.md.sal.rest.common.RestconfValidationUtils;
+import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
+import org.opendaylight.controller.sal.restconf.impl.InstanceIdentifierContext;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
+import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public class SchemaRetrievalServiceImpl implements SchemaRetrievalService {
+
+ private final ControllerContext salContext;
+
+ private static final Splitter SLASH_SPLITTER = Splitter.on("/");
+ private static final Splitter AT_SPLITTER = Splitter.on("@");
+ private static final String MOUNT_ARG = ControllerContext.MOUNT;
+
+ public SchemaRetrievalServiceImpl(final ControllerContext controllerContext) {
+ salContext = controllerContext;
+ }
+
+
+ @Override
+ public SchemaExportContext getSchema(final String mountAndModule) {
+ final SchemaContext schemaContext;
+ final Iterable<String> pathComponents = SLASH_SPLITTER.split(mountAndModule);
+ final Iterator<String> componentIter = pathComponents.iterator();
+ if(!Iterables.contains(pathComponents, MOUNT_ARG)) {
+ schemaContext = salContext.getGlobalSchema();
+ } else {
+ final StringBuilder pathBuilder = new StringBuilder();
+ while(componentIter.hasNext()) {
+ final String current = componentIter.next();
+ // It is argument, not last element.
+ if(pathBuilder.length() != 0) {
+ pathBuilder.append("/");
+ }
+ pathBuilder.append(current);
+ if(MOUNT_ARG.equals(current)) {
+ // We stop right at mountpoint, last two arguments should
+ // be module name and revision
+ break;
+ }
+ }
+ schemaContext = getMountSchemaContext(pathBuilder.toString());
+
+ }
+
+ RestconfValidationUtils.checkDocumentedError(componentIter.hasNext(),
+ ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE, "Module name must be supplied.");
+ final String moduleName = componentIter.next();
+ RestconfValidationUtils.checkDocumentedError(componentIter.hasNext(),
+ ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE, "Revision date must be supplied.");
+ final String revisionString = componentIter.next();
+ return getExportUsingNameAndRevision(schemaContext, moduleName, revisionString);
+ }
+
+ private SchemaExportContext getExportUsingNameAndRevision(final SchemaContext schemaContext, final String moduleName,
+ final String revisionStr) {
+ try {
+ final Date revision = SimpleDateFormatUtil.getRevisionFormat().parse(revisionStr);
+ final Module module = schemaContext.findModuleByName(moduleName, revision);
+ return new SchemaExportContext(schemaContext, RestconfValidationUtils.checkNotNullDocumented(module, moduleName));
+ } catch (final ParseException e) {
+ throw new RestconfDocumentedException("Supplied revision is not in expected date format YYYY-mm-dd", e);
+ }
+ }
+
+ private SchemaContext getMountSchemaContext(final String identifier) {
+ final InstanceIdentifierContext mountContext = salContext.toMountPointIdentifier(identifier);
+ return mountContext.getSchemaContext();
+ }
+
+
+
+}
+
import java.io.IOException;
/**
+ * @deprecated class will be removed in Lithium release
+ *
* This class parses JSON elements from a gson JsonReader. It disallows multiple elements of the same name unlike the
* default gson JsonParser."
*/
+@Deprecated
public class JsonParser {
- public JsonElement parse(JsonReader reader) throws JsonIOException, JsonSyntaxException {
+ public JsonElement parse(final JsonReader reader) throws JsonIOException, JsonSyntaxException {
// code copied from gson's JsonParser and Stream classes
- boolean lenient = reader.isLenient();
+ final boolean lenient = reader.isLenient();
reader.setLenient(true);
boolean isEmpty = true;
try {
reader.peek();
isEmpty = false;
return read(reader);
- } catch (EOFException e) {
+ } catch (final EOFException e) {
if (isEmpty) {
return JsonNull.INSTANCE;
}
// The stream ended prematurely so it is likely a syntax error.
throw new JsonSyntaxException(e);
- } catch (MalformedJsonException e) {
+ } catch (final MalformedJsonException e) {
throw new JsonSyntaxException(e);
- } catch (IOException e) {
+ } catch (final IOException e) {
throw new JsonIOException(e);
- } catch (NumberFormatException e) {
+ } catch (final NumberFormatException e) {
throw new JsonSyntaxException(e);
} catch (StackOverflowError | OutOfMemoryError e) {
throw new JsonParseException("Failed parsing JSON source: " + reader + " to Json", e);
}
}
- public JsonElement read(JsonReader in) throws IOException {
+ public JsonElement read(final JsonReader in) throws IOException {
switch (in.peek()) {
case STRING:
return new JsonPrimitive(in.nextString());
case NUMBER:
- String number = in.nextString();
+ final String number = in.nextString();
return new JsonPrimitive(new LazilyParsedNumber(number));
case BOOLEAN:
return new JsonPrimitive(in.nextBoolean());
in.nextNull();
return JsonNull.INSTANCE;
case BEGIN_ARRAY:
- JsonArray array = new JsonArray();
+ final JsonArray array = new JsonArray();
in.beginArray();
while (in.hasNext()) {
array.add(read(in));
in.endArray();
return array;
case BEGIN_OBJECT:
- JsonObject object = new JsonObject();
+ final JsonObject object = new JsonObject();
in.beginObject();
while (in.hasNext()) {
final String childName = in.nextName();
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+/**
+ * @deprecated class will be removed in Lithium release
+ */
@Provider
@Consumes({ Draft02.MediaTypes.DATA + RestconfService.JSON, Draft02.MediaTypes.OPERATION + RestconfService.JSON,
MediaType.APPLICATION_JSON })
WebApplicationException {
try {
return JsonToCompositeNodeReader.read(entityStream);
- } catch (Exception e) {
+ } catch (final Exception e) {
LOG.debug("Error parsing json input", e);
throw new RestconfDocumentedException("Error parsing input: " + e.getMessage(), ErrorType.PROTOCOL,
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+/**
+ * @deprecated class will be removed in Lithium release
+ */
+@Deprecated
class JsonToCompositeNodeReader {
private static final Logger LOG = LoggerFactory.getLogger(JsonToCompositeNodeReader.class);
private static final Splitter COLON_SPLITTER = Splitter.on(':');
}
public static CompositeNodeWrapper read(final InputStream entityStream) throws UnsupportedFormatException {
- JsonParser parser = new JsonParser();
+ final JsonParser parser = new JsonParser();
- JsonElement rootElement = parser.parse(new JsonReader(new InputStreamReader(entityStream)));
+ final JsonElement rootElement = parser.parse(new JsonReader(new InputStreamReader(entityStream)));
if (rootElement.isJsonNull()) {
// no content, so return null to indicate no input
return null;
throw new UnsupportedFormatException("Root element of Json has to be Object");
}
- Set<Entry<String, JsonElement>> entrySetsOfRootJsonObject = rootElement.getAsJsonObject().entrySet();
+ final Set<Entry<String, JsonElement>> entrySetsOfRootJsonObject = rootElement.getAsJsonObject().entrySet();
if (entrySetsOfRootJsonObject.size() != 1) {
throw new UnsupportedFormatException("Json Object should contain one element");
}
- Entry<String, JsonElement> childEntry = entrySetsOfRootJsonObject.iterator().next();
- String firstElementName = childEntry.getKey();
- JsonElement firstElementType = childEntry.getValue();
+ final Entry<String, JsonElement> childEntry = entrySetsOfRootJsonObject.iterator().next();
+ final String firstElementName = childEntry.getKey();
+ final JsonElement firstElementType = childEntry.getValue();
if (firstElementType.isJsonObject()) {
// container in yang
return createStructureWithRoot(firstElementName, firstElementType.getAsJsonObject());
if (firstElementType.isJsonArray()) {
// list in yang
if (firstElementType.getAsJsonArray().size() == 1) {
- JsonElement firstElementInArray = firstElementType.getAsJsonArray().get(0);
+ final JsonElement firstElementInArray = firstElementType.getAsJsonArray().get(0);
if (firstElementInArray.isJsonObject()) {
return createStructureWithRoot(firstElementName, firstElementInArray.getAsJsonObject());
}
}
private static CompositeNodeWrapper createStructureWithRoot(final String rootObjectName, final JsonObject rootObject) {
- CompositeNodeWrapper firstNode = new CompositeNodeWrapper(getNamespaceFor(rootObjectName),
+ final CompositeNodeWrapper firstNode = new CompositeNodeWrapper(getNamespaceFor(rootObjectName),
getLocalNameFor(rootObjectName));
- for (Entry<String, JsonElement> childOfFirstNode : rootObject.entrySet()) {
+ for (final Entry<String, JsonElement> childOfFirstNode : rootObject.entrySet()) {
addChildToParent(childOfFirstNode.getKey(), childOfFirstNode.getValue(), firstNode);
}
return firstNode;
private static void addChildToParent(final String childName, final JsonElement childType,
final CompositeNodeWrapper parent) {
if (childType.isJsonObject()) {
- CompositeNodeWrapper child = new CompositeNodeWrapper(getNamespaceFor(childName),
+ final CompositeNodeWrapper child = new CompositeNodeWrapper(getNamespaceFor(childName),
getLocalNameFor(childName));
parent.addValue(child);
- for (Entry<String, JsonElement> childOfChild : childType.getAsJsonObject().entrySet()) {
+ for (final Entry<String, JsonElement> childOfChild : childType.getAsJsonObject().entrySet()) {
addChildToParent(childOfChild.getKey(), childOfChild.getValue(), child);
}
} else if (childType.isJsonArray()) {
parent.addValue(new EmptyNodeWrapper(getNamespaceFor(childName), getLocalNameFor(childName)));
} else {
- for (JsonElement childOfChildType : childType.getAsJsonArray()) {
+ for (final JsonElement childOfChildType : childType.getAsJsonArray()) {
addChildToParent(childName, childOfChildType, parent);
}
}
} else if (childType.isJsonPrimitive()) {
- JsonPrimitive childPrimitive = childType.getAsJsonPrimitive();
- String value = childPrimitive.getAsString().trim();
+ final JsonPrimitive childPrimitive = childType.getAsJsonPrimitive();
+ final String value = childPrimitive.getAsString().trim();
parent.addValue(new SimpleNodeWrapper(getNamespaceFor(childName), getLocalNameFor(childName),
resolveValueOfElement(value)));
} else {
if (Iterators.size(it) == 1) {
try {
return URI.create(maybeURI);
- } catch (IllegalArgumentException e) {
+ } catch (final IllegalArgumentException e) {
LOG.debug("Value {} couldn't be interpreted as URI.", maybeURI);
}
}
private static Object resolveValueOfElement(final String value) {
// it could be instance-identifier Built-In Type
if (!value.isEmpty() && value.charAt(0) == '/') {
- IdentityValuesDTO resolvedValue = RestUtil.asInstanceIdentifier(value, new PrefixMapingFromJson());
+ final IdentityValuesDTO resolvedValue = RestUtil.asInstanceIdentifier(value, new PrefixMapingFromJson());
if (resolvedValue != null) {
return resolvedValue;
}
}
// it could be identityref Built-In Type therefore it is necessary to look at value as module_name:local_name
- URI namespace = getNamespaceFor(value);
+ final URI namespace = getNamespaceFor(value);
if (namespace != null) {
return new IdentityValuesDTO(namespace.toString(), getLocalNameFor(value), null, value);
}
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;
+import org.opendaylight.controller.md.sal.rest.schema.SchemaExportContentYangBodyWriter;
+import org.opendaylight.controller.md.sal.rest.schema.SchemaExportContentYinBodyWriter;
+import org.opendaylight.controller.md.sal.rest.schema.SchemaRetrievalServiceImpl;
import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
.add(JsonNormalizedNodeBodyReader.class)
.add(NormalizedNodeJsonBodyWriter.class)
.add(NormalizedNodeXmlBodyWriter.class)
+ .add(SchemaExportContentYinBodyWriter.class)
+ .add(SchemaExportContentYangBodyWriter.class)
.build();
}
@Override
public Set<Object> getSingletons() {
- Set<Object> singletons = new HashSet<>();
- ControllerContext controllerContext = ControllerContext.getInstance();
- BrokerFacade brokerFacade = BrokerFacade.getInstance();
- RestconfImpl restconfImpl = RestconfImpl.getInstance();
+ final Set<Object> singletons = new HashSet<>();
+ final ControllerContext controllerContext = ControllerContext.getInstance();
+ final BrokerFacade brokerFacade = BrokerFacade.getInstance();
+ final RestconfImpl restconfImpl = RestconfImpl.getInstance();
+ final SchemaRetrievalServiceImpl schemaRetrieval = new SchemaRetrievalServiceImpl(controllerContext);
restconfImpl.setBroker(brokerFacade);
restconfImpl.setControllerContext(controllerContext);
singletons.add(controllerContext);
singletons.add(brokerFacade);
- singletons.add(StatisticsRestconfServiceWrapper.getInstance());
+ singletons.add(schemaRetrieval);
+ singletons.add(new RestconfCompositeWrapper(StatisticsRestconfServiceWrapper.getInstance(), schemaRetrieval));
singletons.add(StructuredDataToXmlProvider.INSTANCE);
singletons.add(StructuredDataToJsonProvider.INSTANCE);
singletons.add(JsonToCompositeNodeProvider.INSTANCE);
--- /dev/null
+package org.opendaylight.controller.sal.rest.impl;
+
+import com.google.common.base.Preconditions;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import org.opendaylight.controller.md.sal.rest.schema.SchemaExportContext;
+import org.opendaylight.controller.md.sal.rest.schema.SchemaRetrievalService;
+import org.opendaylight.controller.sal.rest.api.RestconfService;
+import org.opendaylight.controller.sal.restconf.impl.NormalizedNodeContext;
+import org.opendaylight.controller.sal.restconf.impl.StructuredData;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+
+public class RestconfCompositeWrapper implements RestconfService, SchemaRetrievalService {
+
+ private final RestconfService restconf;
+ private final SchemaRetrievalService schema;
+
+ public RestconfCompositeWrapper(final RestconfService restconf, final SchemaRetrievalService schema) {
+ this.restconf = Preconditions.checkNotNull(restconf);
+ this.schema = Preconditions.checkNotNull(schema);
+ }
+
+ @Override
+ public Object getRoot() {
+ return restconf.getRoot();
+ }
+
+ @Override
+ public StructuredData getModules(final UriInfo uriInfo) {
+ return restconf.getModules(uriInfo);
+ }
+
+ @Override
+ public StructuredData getModules(final String identifier, final UriInfo uriInfo) {
+ return restconf.getModules(identifier, uriInfo);
+ }
+
+ @Override
+ public StructuredData getModule(final String identifier, final UriInfo uriInfo) {
+ return restconf.getModule(identifier, uriInfo);
+ }
+
+ @Override
+ public StructuredData getOperations(final UriInfo uriInfo) {
+ return restconf.getOperations(uriInfo);
+ }
+
+ @Override
+ public StructuredData getOperations(final String identifier, final UriInfo uriInfo) {
+ return restconf.getOperations(identifier, uriInfo);
+ }
+
+ @Override
+ public StructuredData invokeRpc(final String identifier, final CompositeNode payload, final UriInfo uriInfo) {
+ return restconf.invokeRpc(identifier, payload, uriInfo);
+ }
+
+ @Override
+ public StructuredData invokeRpc(final String identifier, final String noPayload, final UriInfo uriInfo) {
+ return restconf.invokeRpc(identifier, noPayload, uriInfo);
+ }
+
+ @Override
+ public NormalizedNodeContext readConfigurationData(final String identifier, final UriInfo uriInfo) {
+ return restconf.readConfigurationData(identifier, uriInfo);
+ }
+
+ @Override
+ public NormalizedNodeContext readOperationalData(final String identifier, final UriInfo uriInfo) {
+ return restconf.readOperationalData(identifier, uriInfo);
+ }
+
+ @Override
+ public Response updateConfigurationData(final String identifier, final Node<?> payload) {
+ return restconf.updateConfigurationData(identifier, payload);
+ }
+
+ @Override
+ public Response createConfigurationData(final String identifier, final Node<?> payload) {
+ return restconf.createConfigurationData(identifier, payload);
+ }
+
+ @Override
+ public Response createConfigurationData(final Node<?> payload) {
+ return restconf.createConfigurationData(payload);
+ }
+
+ @Override
+ public Response deleteConfigurationData(final String identifier) {
+ return restconf.deleteConfigurationData(identifier);
+ }
+
+ @Override
+ public Response subscribeToStream(final String identifier, final UriInfo uriInfo) {
+ return restconf.subscribeToStream(identifier, uriInfo);
+ }
+
+ @Override
+ public StructuredData getAvailableStreams(final UriInfo uriInfo) {
+ return restconf.getAvailableStreams(uriInfo);
+ }
+
+ @Override
+ public SchemaExportContext getSchema(final String mountId) {
+ return schema.getSchema(mountId);
+ }
+}
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+/**
+ * @deprecated class will be removed in Lithium release
+ */
@Provider
@Produces({ Draft02.MediaTypes.API + RestconfService.JSON, Draft02.MediaTypes.DATA + RestconfService.JSON,
Draft02.MediaTypes.OPERATION + RestconfService.JSON, MediaType.APPLICATION_JSON })
public void writeTo(final StructuredData t, final Class<?> type, final Type genericType, final Annotation[] annotations,
final MediaType mediaType, final MultivaluedMap<String, Object> httpHeaders, final OutputStream entityStream)
throws IOException, WebApplicationException {
- CompositeNode data = t.getData();
+ final CompositeNode data = t.getData();
if (data == null) {
throw new RestconfDocumentedException(Response.Status.NOT_FOUND);
}
- JsonWriter writer = new JsonWriter(new OutputStreamWriter(entityStream, Charsets.UTF_8));
+ final JsonWriter writer = new JsonWriter(new OutputStreamWriter(entityStream, Charsets.UTF_8));
if (t.isPrettyPrintMode()) {
writer.setIndent(" ");
} else {
writer.setIndent("");
}
- JsonMapper jsonMapper = new JsonMapper(t.getMountPoint());
+ final JsonMapper jsonMapper = new JsonMapper(t.getMountPoint());
jsonMapper.write(writer, data, (DataNodeContainer) t.getSchema());
writer.flush();
}
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
+/**
+ * @deprecated class will be removed in Lithium release
+ */
@Provider
@Produces({ Draft02.MediaTypes.API + RestconfService.XML, Draft02.MediaTypes.DATA + RestconfService.XML,
Draft02.MediaTypes.OPERATION + RestconfService.XML, MediaType.APPLICATION_XML, MediaType.TEXT_XML })
final Transformer ret;
try {
ret = FACTORY.newTransformer();
- } catch (TransformerConfigurationException e) {
+ } catch (final TransformerConfigurationException e) {
LOG.error("Failed to instantiate XML transformer", e);
throw new IllegalStateException("XML encoding currently unavailable", e);
}
final Annotation[] annotations, final MediaType mediaType,
final MultivaluedMap<String, Object> httpHeaders, final OutputStream entityStream) throws IOException,
WebApplicationException {
- CompositeNode data = t.getData();
+ final CompositeNode data = t.getData();
if (data == null) {
throw new RestconfDocumentedException(Response.Status.NOT_FOUND);
}
} else {
trans.setOutputProperty(OutputKeys.INDENT, "no");
}
- } catch (RuntimeException e) {
+ } catch (final RuntimeException e) {
throw new RestconfDocumentedException(e.getMessage(), ErrorType.TRANSPORT, ErrorTag.OPERATION_FAILED);
}
final Document domTree = new XmlMapper().write(data, (DataNodeContainer) t.getSchema());
try {
trans.transform(new DOMSource(domTree), new StreamResult(entityStream));
- } catch (TransformerException e) {
+ } catch (final TransformerException e) {
LOG.error("Error during translation of Document to OutputStream", e);
throw new RestconfDocumentedException(e.getMessage(), ErrorType.TRANSPORT, ErrorTag.OPERATION_FAILED);
}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+/**
+ * @deprecated class will be removed in Lithium release
+ */
@Provider
@Consumes({ Draft02.MediaTypes.DATA + RestconfService.XML, Draft02.MediaTypes.OPERATION + RestconfService.XML,
MediaType.APPLICATION_XML, MediaType.TEXT_XML })
@Override
public Node<?> readFrom(final Class<Node<?>> type, final Type genericType, final Annotation[] annotations,
- MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
+ final MediaType mediaType, final MultivaluedMap<String, String> httpHeaders, final InputStream entityStream)
throws IOException, WebApplicationException {
- XmlToCompositeNodeReader xmlReader = new XmlToCompositeNodeReader();
+ final XmlToCompositeNodeReader xmlReader = new XmlToCompositeNodeReader();
try {
return xmlReader.read(entityStream);
} catch (XMLStreamException | UnsupportedFormatException e) {
package org.opendaylight.controller.sal.rest.impl;
import static com.google.common.base.Preconditions.checkArgument;
-
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
import org.opendaylight.yangtools.yang.data.api.Node;
+/**
+ * @deprecated class will be removed in Lithium release
+ */
@Deprecated
public class XmlToCompositeNodeReader {
eventReader = xmlInputFactory.createXMLEventReader(entityStream);
if (eventReader.hasNext()) {
- XMLEvent element = eventReader.peek();
+ final XMLEvent element = eventReader.peek();
if (element.isStartDocument()) {
eventReader.nextEvent();
}
private boolean isSimpleNodeEvent(final XMLEvent event) throws XMLStreamException {
checkArgument(event != null, "XML Event cannot be NULL!");
if (event.isStartElement()) {
- XMLEvent innerEvent = skipCommentsAndWhitespace();
+ final XMLEvent innerEvent = skipCommentsAndWhitespace();
if (innerEvent != null && (innerEvent.isCharacters() || innerEvent.isEndElement())) {
return true;
}
private boolean isCompositeNodeEvent(final XMLEvent event) throws XMLStreamException {
checkArgument(event != null, "XML Event cannot be NULL!");
if (event.isStartElement()) {
- XMLEvent innerEvent = skipCommentsAndWhitespace();
+ final XMLEvent innerEvent = skipCommentsAndWhitespace();
if (innerEvent != null) {
if (innerEvent.isStartElement()) {
return true;
private XMLEvent skipCommentsAndWhitespace() throws XMLStreamException {
while (eventReader.hasNext()) {
- XMLEvent event = eventReader.peek();
+ final XMLEvent event = eventReader.peek();
if (event.getEventType() == XMLStreamConstants.COMMENT) {
eventReader.nextEvent();
continue;
}
if (event.isCharacters()) {
- Characters chars = event.asCharacters();
+ final Characters chars = event.asCharacters();
if (chars.isWhiteSpace()) {
eventReader.nextEvent();
continue;
private NodeWrapper<? extends Node<?>> resolveSimpleNodeFromStartElement(final StartElement startElement)
throws XMLStreamException {
checkArgument(startElement != null, "Start Element cannot be NULL!");
- String data = getValueOf(startElement);
+ final String data = getValueOf(startElement);
if (data == null) {
return new EmptyNodeWrapper(getNamespaceFor(startElement), getLocalNameFor(startElement));
}
}
private URI getNamespaceFor(final StartElement startElement) {
- String namespaceURI = startElement.getName().getNamespaceURI();
+ final String namespaceURI = startElement.getName().getNamespaceURI();
return namespaceURI.isEmpty() ? null : URI.create(namespaceURI);
}
private Object resolveValueOfElement(final String value, final StartElement startElement) {
// it could be instance-identifier Built-In Type
if (value.startsWith("/")) {
- IdentityValuesDTO iiValue = RestUtil.asInstanceIdentifier(value, new RestUtil.PrefixMapingFromXml(
+ final IdentityValuesDTO iiValue = RestUtil.asInstanceIdentifier(value, new RestUtil.PrefixMapingFromXml(
startElement));
if (iiValue != null) {
return iiValue;
}
}
// it could be identityref Built-In Type
- String[] namespaceAndValue = value.split(":");
+ final String[] namespaceAndValue = value.split(":");
if (namespaceAndValue.length == 2) {
- String namespace = startElement.getNamespaceContext().getNamespaceURI(namespaceAndValue[0]);
+ final String namespace = startElement.getNamespaceContext().getNamespaceURI(namespaceAndValue[0]);
if (namespace != null && !namespace.isEmpty()) {
return new IdentityValuesDTO(namespace, namespaceAndValue[1], namespaceAndValue[0], value);
}
import org.opendaylight.yangtools.yang.data.api.SimpleNode;
import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
+/**
+ * @deprecated class will be removed in Lithium release
+ */
+@Deprecated
public final class CompositeNodeWrapper implements NodeWrapper<CompositeNode>, CompositeNode {
private MutableCompositeNode compositeNode;
name = new QName(namespace, localName);
}
- List<Node<?>> nodeValues = new ArrayList<>(values.size());
- for (NodeWrapper<?> nodeWrapper : values) {
+ final List<Node<?>> nodeValues = new ArrayList<>(values.size());
+ for (final NodeWrapper<?> nodeWrapper : values) {
nodeValues.add(nodeWrapper.unwrap());
}
compositeNode = NodeFactory.createMutableCompositeNode(name, null, nodeValues, null, null);
import org.opendaylight.yangtools.yang.data.api.Node;
import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
+/**
+ * @deprecated class will be removed in Lithium release
+ */
+@Deprecated
public final class EmptyNodeWrapper implements NodeWrapper<Node<?>>, Node<Void> {
private Node<?> unwrapped;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.Node;
+/**
+ * @deprecated class will be removed in Lithium release
+ */
+@Deprecated
public interface NodeWrapper<T extends Node<?>> {
void setQname(QName name);
import org.opendaylight.yangtools.yang.data.api.SimpleNode;
import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
+/**
+ * @deprecated class will be removed in Lithium release
+ */
+@Deprecated
public final class SimpleNodeWrapper implements NodeWrapper<SimpleNode<?>>, SimpleNode<Object> {
private SimpleNode<Object> simpleNode;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+/**
+ * @deprecated class will be removed in Lithium release
+ */
+@Deprecated
public class StructuredData {
private final CompositeNode data;
this.data = data;
this.schema = schema;
this.mountPoint = mountPoint;
- this.prettyPrintMode = preattyPrintMode;
+ prettyPrintMode = preattyPrintMode;
}
public CompositeNode getData() {
import java.util.Map.Entry;
import javax.management.ObjectName;
import javax.management.openmbean.OpenType;
-import org.opendaylight.controller.config.util.ConfigRegistryClient;
+import org.opendaylight.controller.config.util.BeanReader;
import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry;
import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
private final Map<String, AttributeIfc> yangToAttrConfig;
private final String nullableDummyContainerName;
private final Map<String, AttributeIfc> jmxToAttrConfig;
- private final ConfigRegistryClient configRegistryClient;
+ private final BeanReader configRegistryClient;
- public InstanceConfig(ConfigRegistryClient configRegistryClient, Map<String, AttributeIfc> yangNamesToAttributes,
+ public InstanceConfig(BeanReader configRegistryClient, Map<String, AttributeIfc> yangNamesToAttributes,
String nullableDummyContainerName) {
this.yangToAttrConfig = yangNamesToAttributes;
TransactionProvider transactionProvider) {
switch (source) {
case running:
- return new RunningDatastoreQueryStrategy();
+ return new RunningDatastoreQueryStrategy(transactionProvider);
case candidate:
return new CandidateDatastoreQueryStrategy(transactionProvider);
default:
protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException {
fromXml(xml);
try {
- this.transactionProvider.abortTransaction();
- } catch (final IllegalStateException e) {
+ if (transactionProvider.getTransaction().isPresent()) {
+ this.transactionProvider.abortTransaction();
+ }
+ } catch (final RuntimeException e) {
LOG.warn("Abort failed: ", e);
final Map<String, String> errorInfo = new HashMap<>();
errorInfo
.put(ErrorTag.operation_failed.name(),
- "Operation failed. Use 'get-config' or 'edit-config' before triggering 'discard-changes' operation");
+ "Abort failed.");
throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.application, ErrorTag.operation_failed,
ErrorSeverity.error, errorInfo);
}
import javax.management.InstanceNotFoundException;
import javax.management.ObjectName;
import org.opendaylight.controller.config.api.ValidationException;
+import org.opendaylight.controller.config.util.BeanReader;
import org.opendaylight.controller.config.util.ConfigRegistryClient;
import org.opendaylight.controller.config.util.ConfigTransactionClient;
import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
public static Map<String/* Namespace from yang file */,
Map<String /* Name of module entry from yang file */, ModuleConfig>> transformMbeToModuleConfigs
- (final ConfigRegistryClient configRegistryClient, Map<String/* Namespace from yang file */,
+ (final BeanReader configRegistryClient, Map<String/* Namespace from yang file */,
Map<String /* Name of module entry from yang file */, ModuleMXBeanEntry>> mBeanEntries) {
Map<String, Map<String, ModuleConfig>> namespaceToModuleNameToModuleConfig = Maps.newHashMap();
@Override
protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException {
-
EditConfigXmlParser.EditConfigExecution editConfigExecution;
Config cfg = getConfigMapping(getConfigRegistryClient(), yangStoreSnapshot);
editConfigExecution = editConfigXmlParser.fromXml(xml, cfg);
import java.util.Set;
import javax.management.ObjectName;
import org.opendaylight.controller.config.util.ConfigRegistryClient;
+import org.opendaylight.controller.config.util.ConfigTransactionClient;
import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.Datastore;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreContext;
+import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException;
import org.opendaylight.controller.netconf.util.exception.UnexpectedElementException;
import org.opendaylight.controller.netconf.util.exception.UnexpectedNamespaceException;
public class Get extends AbstractConfigNetconfOperation {
+ private final TransactionProvider transactionProvider;
private final YangStoreContext yangStoreSnapshot;
private static final Logger LOG = LoggerFactory.getLogger(Get.class);
- public Get(YangStoreContext yangStoreSnapshot, ConfigRegistryClient configRegistryClient,
+ public Get(final TransactionProvider transactionProvider, YangStoreContext yangStoreSnapshot, ConfigRegistryClient configRegistryClient,
String netconfSessionIdForReporting) {
super(configRegistryClient, netconfSessionIdForReporting);
+ this.transactionProvider = transactionProvider;
this.yangStoreSnapshot = yangStoreSnapshot;
}
protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException {
checkXml(xml);
- final Set<ObjectName> runtimeBeans = getConfigRegistryClient().lookupRuntimeBeans();
+ final ObjectName testTransaction = transactionProvider.getOrCreateReadTransaction();
+ final ConfigTransactionClient registryClient = getConfigRegistryClient().getConfigTransactionClient(testTransaction);
- //Transaction provider required only for candidate datastore
- final Set<ObjectName> configBeans = Datastore.getInstanceQueryStrategy(Datastore.running, null)
- .queryInstances(getConfigRegistryClient());
+ try {
+ // Runtime beans are not parts of transactions and have to be queried against the central registry
+ final Set<ObjectName> runtimeBeans = getConfigRegistryClient().lookupRuntimeBeans();
- final Map<String, Map<String, ModuleRuntime>> moduleRuntimes = createModuleRuntimes(getConfigRegistryClient(),
- yangStoreSnapshot.getModuleMXBeanEntryMap());
- final Map<String, Map<String, ModuleConfig>> moduleConfigs = EditConfig.transformMbeToModuleConfigs(
- getConfigRegistryClient(), yangStoreSnapshot.getModuleMXBeanEntryMap());
+ final Set<ObjectName> configBeans = Datastore.getInstanceQueryStrategy(Datastore.running, transactionProvider)
+ .queryInstances(getConfigRegistryClient());
- final Runtime runtime = new Runtime(moduleRuntimes, moduleConfigs);
+ final Map<String, Map<String, ModuleRuntime>> moduleRuntimes = createModuleRuntimes(getConfigRegistryClient(),
+ yangStoreSnapshot.getModuleMXBeanEntryMap());
+ final Map<String, Map<String, ModuleConfig>> moduleConfigs = EditConfig.transformMbeToModuleConfigs(
+ registryClient, yangStoreSnapshot.getModuleMXBeanEntryMap());
- final Element element = runtime.toXml(runtimeBeans, configBeans, document);
+ final Runtime runtime = new Runtime(moduleRuntimes, moduleConfigs);
- LOG.trace("{} operation successful", XmlNetconfConstants.GET);
+ final Element element = runtime.toXml(runtimeBeans, configBeans, document);
- return element;
+ LOG.trace("{} operation successful", XmlNetconfConstants.GET);
+
+ return element;
+ } finally {
+ transactionProvider.closeReadTransaction();
+ }
}
}
private Element getResponseInternal(final Document document, final ConfigRegistryClient configRegistryClient,
final Datastore source) {
- Element dataElement = XmlUtil.createElement(document, XmlNetconfConstants.DATA_KEY, Optional.<String>absent());
- final Set<ObjectName> instances = Datastore.getInstanceQueryStrategy(source, this.transactionProvider)
- .queryInstances(configRegistryClient);
- final Config configMapping = new Config(EditConfig.transformMbeToModuleConfigs(configRegistryClient,
- yangStoreSnapshot.getModuleMXBeanEntryMap()));
-
-
- ObjectName on = transactionProvider.getOrCreateTransaction();
- ConfigTransactionClient ta = configRegistryClient.getConfigTransactionClient(on);
-
- ServiceRegistryWrapper serviceTracker = new ServiceRegistryWrapper(ta);
- dataElement = configMapping.toXml(instances, this.maybeNamespace, document, dataElement, serviceTracker);
-
- LOG.trace("{} operation successful", GET_CONFIG);
-
- return dataElement;
+ final ConfigTransactionClient registryClient;
+ // Read current state from a transaction, if running is source, then start new transaction just for reading
+ // in case of candidate, get current transaction representing candidate
+ if(source == Datastore.running) {
+ final ObjectName readTx = transactionProvider.getOrCreateReadTransaction();
+ registryClient = getConfigRegistryClient().getConfigTransactionClient(readTx);
+ } else {
+ registryClient = getConfigRegistryClient().getConfigTransactionClient(transactionProvider.getOrCreateTransaction());
+ }
+
+ try {
+ Element dataElement = XmlUtil.createElement(document, XmlNetconfConstants.DATA_KEY, Optional.<String>absent());
+ final Set<ObjectName> instances = Datastore.getInstanceQueryStrategy(source, this.transactionProvider)
+ .queryInstances(configRegistryClient);
+
+ final Config configMapping = new Config(EditConfig.transformMbeToModuleConfigs(registryClient,
+ yangStoreSnapshot.getModuleMXBeanEntryMap()));
+
+ ServiceRegistryWrapper serviceTracker = new ServiceRegistryWrapper(registryClient);
+ dataElement = configMapping.toXml(instances, this.maybeNamespace, document, dataElement, serviceTracker);
+
+ LOG.trace("{} operation successful", GET_CONFIG);
+
+ return dataElement;
+ } finally {
+ if(source == Datastore.running) {
+ transactionProvider.closeReadTransaction();
+ }
+ }
}
@Override
import java.util.Set;
import javax.management.ObjectName;
import org.opendaylight.controller.config.util.ConfigRegistryClient;
+import org.opendaylight.controller.config.util.ConfigTransactionClient;
+import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
public class RunningDatastoreQueryStrategy implements DatastoreQueryStrategy {
+ private final TransactionProvider transactionProvider;
+
+ public RunningDatastoreQueryStrategy(TransactionProvider transactionProvider) {
+ this.transactionProvider = transactionProvider;
+ }
+
@Override
public Set<ObjectName> queryInstances(ConfigRegistryClient configRegistryClient) {
- return configRegistryClient.lookupConfigBeans();
+ ObjectName on = transactionProvider.getOrCreateReadTransaction();
+ ConfigTransactionClient proxy = configRegistryClient.getConfigTransactionClient(on);
+ return proxy.lookupConfigBeans();
}
}
ops.add(new Commit(transactionProvider, configRegistryClient, netconfSessionIdForReporting));
ops.add(new Lock(netconfSessionIdForReporting));
ops.add(new UnLock(netconfSessionIdForReporting));
- ops.add(new Get(yangStoreSnapshot, configRegistryClient, netconfSessionIdForReporting));
+ ops.add(new Get(transactionProvider, yangStoreSnapshot, configRegistryClient, netconfSessionIdForReporting));
ops.add(new DiscardChanges(transactionProvider, configRegistryClient, netconfSessionIdForReporting));
ops.add(new Validate(transactionProvider, configRegistryClient, netconfSessionIdForReporting));
ops.add(new RuntimeRpc(yangStoreSnapshot, configRegistryClient, netconfSessionIdForReporting));
private final ConfigRegistryClient configRegistryClient;
private final String netconfSessionIdForReporting;
- private ObjectName transaction;
+ private ObjectName candidateTx;
+ private ObjectName readTx;
private final List<ObjectName> allOpenedTransactions = new ArrayList<>();
private static final String NO_TRANSACTION_FOUND_FOR_SESSION = "No transaction found for session ";
public synchronized Optional<ObjectName> getTransaction() {
- if (transaction == null){
+ if (candidateTx == null){
return Optional.absent();
}
// Transaction was already closed somehow
- if (!isStillOpenTransaction(transaction)) {
- LOG.warn("Fixing illegal state: transaction {} was closed in {}", transaction,
+ if (!isStillOpenTransaction(candidateTx)) {
+ LOG.warn("Fixing illegal state: transaction {} was closed in {}", candidateTx,
netconfSessionIdForReporting);
- transaction = null;
+ candidateTx = null;
return Optional.absent();
}
- return Optional.of(transaction);
+ return Optional.of(candidateTx);
+ }
+
+ public synchronized Optional<ObjectName> getReadTransaction() {
+
+ if (readTx == null){
+ return Optional.absent();
+ }
+
+ // Transaction was already closed somehow
+ if (!isStillOpenTransaction(readTx)) {
+ LOG.warn("Fixing illegal state: transaction {} was closed in {}", readTx,
+ netconfSessionIdForReporting);
+ readTx = null;
+ return Optional.absent();
+ }
+ return Optional.of(readTx);
}
private boolean isStillOpenTransaction(ObjectName transaction) {
if (ta.isPresent()) {
return ta.get();
}
- transaction = configRegistryClient.beginConfig();
- allOpenedTransactions.add(transaction);
- return transaction;
+ candidateTx = configRegistryClient.beginConfig();
+ allOpenedTransactions.add(candidateTx);
+ return candidateTx;
+ }
+
+ public synchronized ObjectName getOrCreateReadTransaction() {
+ Optional<ObjectName> ta = getReadTransaction();
+
+ if (ta.isPresent()) {
+ return ta.get();
+ }
+ readTx = configRegistryClient.beginConfig();
+ allOpenedTransactions.add(readTx);
+ return readTx;
}
/**
try {
CommitStatus status = configRegistryClient.commitConfig(taON);
// clean up
- allOpenedTransactions.remove(transaction);
- transaction = null;
+ allOpenedTransactions.remove(candidateTx);
+ candidateTx = null;
return status;
} catch (ValidationException validationException) {
// no clean up: user can reconfigure and recover this transaction
ConfigTransactionClient transactionClient = configRegistryClient.getConfigTransactionClient(taON.get());
transactionClient.abortConfig();
- allOpenedTransactions.remove(transaction);
- transaction = null;
+ allOpenedTransactions.remove(candidateTx);
+ candidateTx = null;
+ }
+
+ public synchronized void closeReadTransaction() {
+ LOG.debug("Closing read transaction");
+ Optional<ObjectName> taON = getReadTransaction();
+ Preconditions.checkState(taON.isPresent(), NO_TRANSACTION_FOUND_FOR_SESSION + netconfSessionIdForReporting);
+
+ ConfigTransactionClient transactionClient = configRegistryClient.getConfigTransactionClient(taON.get());
+ transactionClient.abortConfig();
+ allOpenedTransactions.remove(readTx);
+ readTx = null;
}
public synchronized void abortTestTransaction(ObjectName testTx) {
commit();
}
- @Test(expected = NetconfDocumentedException.class)
+ @Test
public void testEx2() throws Exception {
- discard();
+ assertContainsElement(discard(), readXmlToElement("<ok xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"/>"));
}
- private void discard() throws ParserConfigurationException, SAXException, IOException, NetconfDocumentedException {
+ private Document discard() throws ParserConfigurationException, SAXException, IOException, NetconfDocumentedException {
DiscardChanges discardOp = new DiscardChanges(transactionProvider, configRegistryClient, NETCONF_SESSION_ID);
- executeOp(discardOp, "netconfMessages/discardChanges.xml");
+ return executeOp(discardOp, "netconfMessages/discardChanges.xml");
}
private void checkBinaryLeafEdited(final Document response) throws NodeTestException, SAXException, IOException {
}
private Document get() throws NetconfDocumentedException, ParserConfigurationException, SAXException, IOException {
- Get getOp = new Get(yangStoreSnapshot, configRegistryClient, NETCONF_SESSION_ID);
+ Get getOp = new Get(transactionProvider, yangStoreSnapshot, configRegistryClient, NETCONF_SESSION_ID);
return executeOp(getOp, "netconfMessages/get.xml");
}
import java.util.List;
+/**
+ * This interface defines the methods for Neutron Requests
+ *
+ * @deprecated Replaced by {@link org.opendaylight.neutron.northbound.api.INeutronRequest}
+ */
+@Deprecated
public interface INeutronRequest<T extends INeutronObject> {
public T getSingleton();
public boolean isSingleton();
/**
* This interface defines the methods a service that wishes to be aware of Firewall Rules needs to implement
*
+ * @deprecated Replaced by {@link org.opendaylight.neutron.neutron.spi.INeutronFirewallAware}
*/
+@Deprecated
public interface INeutronFirewallAware {
/**
/**
* This interface defines the methods for CRUD of NB OpenStack Firewall objects
*
+ * @deprecated Replaced by {@link org.opendaylight.neutron.neutron.spi.INeutronFirewallCRUD}
*/
+@Deprecated
public interface INeutronFirewallCRUD {
/**
* Applications call this interface method to determine if a particular
/**
* This interface defines the methods a service that wishes to be aware of Firewall Policys needs to implement
*
+ * @deprecated Replaced by {@link org.opendaylight.neutron.neutron.spi.INeutronFirewallPolicyAware}
*/
+@Deprecated
public interface INeutronFirewallPolicyAware {
/**
/**
* This interface defines the methods for CRUD of NB OpenStack Firewall Policy objects
*
+ * @deprecated Replaced by {@link org.opendaylight.neutron.neutron.spi.INeutronFirewallPolicyCRUD}
*/
+@Deprecated
public interface INeutronFirewallPolicyCRUD {
/**
* Applications call this interface method to determine if a particular
/**
* This interface defines the methods a service that wishes to be aware of Firewall Rules needs to implement
*
+ * @deprecated Replaced by {@link org.opendaylight.neutron.neutron.spi.INeutronFirewallRuleAware}
*/
+@Deprecated
public interface INeutronFirewallRuleAware {
/**
/**
* This interface defines the methods for CRUD of NB OpenStack Firewall Rule objects
*
+ * @deprecated Replaced by {@link org.opendaylight.neutron.neutron.spi.INeutronFirewallRuleCRUD}
*/
+@Deprecated
public interface INeutronFirewallRuleCRUD {
/**
* Applications call this interface method to determine if a particular
/**
* This interface defines the methods a service that wishes to be aware of Neutron FloatingIPs needs to implement
*
+ * @deprecated Replaced by {@link org.opendaylight.neutron.neutron.spi.INeutronFloatingIPAware}
*/
+@Deprecated
public interface INeutronFloatingIPAware {
/**
/**
* This interface defines the methods for CRUD of NB FloatingIP objects
*
+ * @deprecated Replaced by {@link org.opendaylight.neutron.neutron.spi.INeutronFloatingIPCRUD}
*/
+@Deprecated
public interface INeutronFloatingIPCRUD {
/**
* Applications call this interface method to determine if a particular
/**
* This interface defines the methods a service that wishes to be aware of LoadBalancer Rules needs to implement
*
+ * @deprecated Replaced by {@link org.opendaylight.neutron.neutron.spi.INeutronLoadBalancerAware}
*/
+@Deprecated
public interface INeutronLoadBalancerAware {
/**
/**
* This interface defines the methods for CRUD of NB OpenStack LoadBalancer objects
*
+ * @deprecated Replaced by {@link org.opendaylight.neutron.neutron.spi.INeutronLoadBalancerCRUD}
*/
+@Deprecated
public interface INeutronLoadBalancerCRUD {
/**
* Applications call this interface method to determine if a particular
/**
* This interface defines the methods a service that wishes to be aware of LoadBalancerHealthMonitor Rules needs to implement
*
+ * @deprecated Replaced by {@link org.opendaylight.neutron.neutron.spi.INeutronLoadBalancerHealthMonitorAware}
*/
+@Deprecated
public interface INeutronLoadBalancerHealthMonitorAware {
/**
/**
* This interface defines the methods for CRUD of NB OpenStack LoadBalancerHealthMonitor objects
*
+ * @deprecated Replaced by {@link org.opendaylight.neutron.neutron.spi.INeutronLoadBalancerHealthMonitorCRUD}
*/
+@Deprecated
public interface INeutronLoadBalancerHealthMonitorCRUD {
/**
* Applications call this interface method to determine if a particular
/**
* This interface defines the methods a service that wishes to be aware of LoadBalancerListener Rules needs to implement
*
+ * @deprecated Replaced by {@link org.opendaylight.neutron.neutron.spi.INeutronLoadBalancerListenerAware}
*/
+@Deprecated
public interface INeutronLoadBalancerListenerAware {
/**
/**
* This interface defines the methods for CRUD of NB OpenStack LoadBalancerListener objects
*
+ * @deprecated Replaced by {@link org.opendaylight.neutron.neutron.spi.INeutronLoadBalancerListenerCRUD}
*/
+@Deprecated
public interface INeutronLoadBalancerListenerCRUD {
/**
* Applications call this interface method to determine if a particular
/**
* This interface defines the methods a service that wishes to be aware of LoadBalancerPool Rules needs to implement
*
+ * @deprecated Replaced by {@link org.opendaylight.neutron.neutron.spi.INeutronLoadBalancerPoolAware}
*/
+@Deprecated
public interface INeutronLoadBalancerPoolAware {
/**
/**
* This interface defines the methods for CRUD of NB OpenStack LoadBalancerPool objects
*
+ * @deprecated Replaced by {@link org.opendaylight.neutron.neutron.spi.INeutronLoadBalancerPoolCRUD}
*/
+@Deprecated
public interface INeutronLoadBalancerPoolCRUD {
/**
* Applications call this interface method to determine if a particular
*/
package org.opendaylight.controller.networkconfig.neutron;
+/**
+ * This interface defines the methods for CRUD of NB OpenStack INeutronLoadBalancerPoolMemberAware objects
+ *
+ * @deprecated Replaced by {@link org.opendaylight.neutron.neutron.spi.INeutronLoadBalancerPoolMemberAware}
+ */
+
+@Deprecated
public interface INeutronLoadBalancerPoolMemberAware {
import java.util.List;
+/**
+ * This interface defines the methods for CRUD of NB OpenStack INeutronLoadBalancerPoolMemberCRUD objects
+ *
+ * @deprecated Replaced by {@link org.opendaylight.neutron.neutron.spi.INeutronLoadBalancerPoolMemberCRUD}
+ */
+
+@Deprecated
public interface INeutronLoadBalancerPoolMemberCRUD {
/**
/**
* This interface defines the methods a service that wishes to be aware of Neutron Networks needs to implement
*
+ * @deprecated Replaced by {@link org.opendaylight.neutron.neutron.spi.INeutronNetworkAware}
*/
+@Deprecated
public interface INeutronNetworkAware {
/**
/**
* This interface defines the methods for CRUD of NB network objects
*
+ * @deprecated Replaced by {@link org.opendaylight.neutron.neutron.spi.INeutronNetworkCRUD}
*/
+@Deprecated
public interface INeutronNetworkCRUD {
/**
* Applications call this interface method to determine if a particular
/**
* This class contains behaviour common to Neutron configuration objects
+ *
+ * @deprecated Replaced by {@link org.opendaylight.neutron.neutron.spi.INeutronObject}
*/
+@Deprecated
public interface INeutronObject {
public String getID();
public void setID(String id);
/**
* This interface defines the methods a service that wishes to be aware of Neutron Ports needs to implement
*
+ * @deprecated Replaced by {@link org.opendaylight.neutron.neutron.spi.INeutronPortAware}
*/
+@Deprecated
public interface INeutronPortAware {
/**
/**
* This interface defines the methods for CRUD of NB Port objects
*
+ * @deprecated Replaced by {@link org.opendaylight.neutron.neutron.spi.INeutronPortCRUD}
*/
+@Deprecated
public interface INeutronPortCRUD {
/**
* Applications call this interface method to determine if a particular
/**
* This interface defines the methods a service that wishes to be aware of Neutron Routers needs to implement
*
+ * @deprecated Replaced by {@link org.opendaylight.neutron.neutron.spi.INeutronRouterAware}
*/
+@Deprecated
public interface INeutronRouterAware {
/**
/**
* This interface defines the methods for CRUD of NB Router objects
*
+ * @deprecated Replaced by {@link org.opendaylight.neutron.neutron.spi.INeutronRouterCRUD}
*/
+@Deprecated
public interface INeutronRouterCRUD {
/**
* Applications call this interface method to determine if a particular
/**
* This interface defines the methods a service that wishes to be aware of Neutron Security Groups needs to implement
+ *
+ * @deprecated Replaced by {@link org.opendaylight.neutron.neutron.spi.INeutronSecurityGroupAware}
*/
+@Deprecated
public interface INeutronSecurityGroupAware {
/**
/**
* This interface defines the methods for CRUD of NB OpenStack Security Group objects
+ *
+ * @deprecated Replaced by {@link org.opendaylight.neutron.neutron.spi.INeutronSecurityGroupCRUD}
*/
+@Deprecated
public interface INeutronSecurityGroupCRUD {
/**
* Applications call this interface method to determine if a particular
/**
* This interface defines the methods required to be aware of Neutron Security Rules
+ *
+ * @deprecated Replaced by {@link org.opendaylight.neutron.neutron.spi.INeutronSecurityRuleAware}
*/
+@Deprecated
public interface INeutronSecurityRuleAware {
/**
/**
* This interface defines the methods for CRUD of NB OpenStack Security Rule objects
+ *
+ * @deprecated Replaced by {@link org.opendaylight.neutron.neutron.spi.INeutronSecurityRuleCRUD}
*/
+@Deprecated
public interface INeutronSecurityRuleCRUD {
/**
* Applications call this interface method to determine if a particular
/**
* This interface defines the methods a service that wishes to be aware of Neutron Subnets needs to implement
*
+ * @deprecated Replaced by {@link org.opendaylight.neutron.neutron.spi.INeutronSubnetAware}
*/
+@Deprecated
public interface INeutronSubnetAware {
/**
/**
* This interface defines the methods for CRUD of NB Subnet objects
*
+ * @deprecated Replaced by {@link org.opendaylight.neutron.neutron.spi.INeutronSubnetCRUD}
*/
+@Deprecated
public interface INeutronSubnetCRUD {
/**
* Applications call this interface method to determine if a particular