using the config subystem.
patch 5 changes:
md-sal/pom.xml correction
patch 4 changes:
Moved data tree api and impl to yang-tools based on earlier comment
Patch 3 changes:
1. Included sal-inmemory-datastore dependency in TestHelper.java for PaxExam
integration test cases [Weird that it was working earlier and my local controller full build were passing]
Patch 2 changes:
1. Keeping schema service as part of opendaylight-dom-broker-impl for backward comptability scenario
2. Initializing InMemoryDOMDataStore by default if config-dom-datastore and
operation-dom-datastore are not found
3. Updated 01-md-sal.xml based on 1.
4. Regarding the comment of moving data tree in yangtools. It shall be done in
separate patch.
This is done to replace InMemoryDOMDatastore with distributed-datastore
The changes done are:
1. Created a new sal-inmemory-datastore bundle and moved the
store/impl source files from sal-dom-broker and the corresponding
InMemoryDOMDatastore test cases.
2. Created two yang config models in sal-dom-spi that represent
the configurable config-dom-datastore and operational-dom-datastore, that
are of service type DOMStore
3. In opendaylight-dom-broker-impl.yang of sal-dom-broker, in the augment of dom-inmemory-data-broker added two container config-data-store and operational-data-store that refer the service implementations of service defined in sal-dom-spi
4.In sal-inmemory-datastore bundle, created a yang model opendaylight-inmemory-datastore that provide the implementation of the sal-dom-spi service definitions mentioned in 2 -- The implementaions are augmented to have schema-service container required by InMemoryDOMDatastore for registering itself for scheam changes
5. Updated the 01-md-sal.xml with the above changes
6. Update the distribution pom.xml to include sal-inmemory-datastore.
Change-Id: Ib2f0f0556869981e7e60b3eeae9b1e5e6cc96a0f
Signed-off-by: Basheeruddin Ahmed <syedbahm@cisco.com>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-core-spi</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-inmemory-datastore</artifactId>
+ <version>1.1-SNAPSHOT</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-netconf-connector</artifactId>
<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:schema-service-singleton</type>
<name>yang-schema-service</name>
</module>
+
<module>
<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:runtime-generated-mapping</type>
<name>runtime-mapping-singleton</name>
</data-broker>
</module>
+
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:inmemory-datastore-provider">prefix:inmemory-config-datastore-provider</type>
+ <name>config-store-service</name>
+ <schema-service>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
+ <name>yang-schema-service</name>
+ </schema-service>
+ </module>
+
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:inmemory-datastore-provider">prefix:inmemory-operational-datastore-provider</type>
+ <name>operational-store-service</name>
+ <schema-service>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
+ <name>yang-schema-service</name>
+ </schema-service>
+ </module>
+
<!--
Tree-based in-memory data store. This is the data store which is currently
recommended for single-node deployments.
<module>
<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-inmemory-data-broker</type>
<name>inmemory-data-broker</name>
+
<schema-service>
<type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
<name>yang-schema-service</name>
</schema-service>
+
+ <config-data-store>
+ <type xmlns:config-dom-store-spi="urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:config-dom-store">config-dom-store-spi:config-dom-datastore</type>
+ <name>config-store-service</name>
+ </config-data-store>
+
+ <operational-data-store>
+ <type xmlns:operational-dom-store-spi="urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:operational-dom-store">operational-dom-store-spi:operational-dom-datastore</type>
+ <name>operational-store-service</name>
+ </operational-data-store>
</module>
<module>
<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-broker-impl</type>
<provider>/modules/module[type='schema-service-singleton'][name='yang-schema-service']</provider>
</instance>
</service>
+ <service>
+ <type xmlns:config-dom-store-spi="urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:config-dom-store">config-dom-store-spi:config-dom-datastore</type>
+ <instance>
+ <name>config-store-service</name>
+ <provider>/modules/module[type='inmemory-config-datastore-provider'][name='config-store-service']</provider>
+ </instance>
+ </service>
+ <service>
+ <type xmlns:operational-dom-store-spi="urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:operational-dom-store">operational-dom-store-spi:operational-dom-datastore</type>
+ <instance>
+ <name>operational-store-service</name>
+ <provider>/modules/module[type='inmemory-operational-datastore-provider'][name='operational-store-service']</provider>
+ </instance>
+ </service>
<service>
<type xmlns:binding-impl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding-impl:binding-dom-mapping-service</type>
<instance>
<capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl?module=opendaylight-sal-binding-broker-impl&revision=2013-10-28</capability>
<capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&revision=2013-10-28</capability>
<capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:common?module=opendaylight-md-sal-common&revision=2013-10-28</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:config-dom-store?module=opendaylight-config-dom-datastore&revision=2014-06-17</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:operational-dom-store?module=opendaylight-operational-dom-datastore&revision=2014-06-17</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:inmemory-datastore-provider?module=opendaylight-inmemory-datastore-provider&revision=2014-06-17</capability>
+
</required-capabilities>
</snapshot>
<!-- Clustering -->
<module>remoterpc-routingtable/implementation</module>
<module>sal-remoterpc-connector/implementation</module>
-
<!-- Documentation -->
<module>sal-rest-docgen</module>
+ <!--InMemory DOM DataStore-->
+ <module>sal-inmemory-datastore</module>
+
<!--sal-protocolbuffer-encoding-->
<module>sal-protocolbuffer-encoding</module>
mavenBundle(CONTROLLER, "sal-common-util").versionAsInProject(), // //
-
+ mavenBundle(CONTROLLER, "sal-inmemory-datastore").versionAsInProject(), // /
mavenBundle(CONTROLLER, "sal-broker-impl").versionAsInProject(), // //
mavenBundle(CONTROLLER, "sal-core-spi").versionAsInProject().update(), //
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-core-spi</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-inmemory-datastore</artifactId>
+ <version>1.1-SNAPSHOT</version>
+
+ </dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>util</artifactId>
org.opendaylight.controller.config.yang.md.sal.dom.statistics,
org.opendaylight.controller.md.sal.dom.broker.impl,
org.opendaylight.controller.md.sal.dom.broker.impl.*,
- org.opendaylight.controller.md.sal.dom.store.impl,
- org.opendaylight.controller.md.sal.dom.store.impl.*,
org.opendaylight.yangtools.yang.util,
org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.dom.impl.rev131028.*</Private-Package>
<Import-Package>*</Import-Package>
*/
package org.opendaylight.controller.config.yang.md.sal.dom.impl;
-import java.util.Hashtable;
-import java.util.concurrent.Executors;
-
+import com.google.common.collect.ImmutableMap;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
import org.opendaylight.controller.md.sal.dom.broker.impl.DOMDataBrokerImpl;
import org.opendaylight.controller.sal.core.spi.data.DOMStore;
import org.osgi.framework.BundleContext;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
+import java.util.Hashtable;
+import java.util.concurrent.Executors;
/**
*
@Override
public java.lang.AutoCloseable createInstance() {
ListeningExecutorService storeExecutor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(2));
- InMemoryDOMDataStore operStore = new InMemoryDOMDataStore("DOM-OPER", storeExecutor);
- InMemoryDOMDataStore configStore = new InMemoryDOMDataStore("DOM-CFG", storeExecutor);
+ //Initializing Operational DOM DataStore defaulting to InMemoryDOMDataStore if one is not configured
+ DOMStore operStore = getOperationalDataStoreDependency();
+ if(operStore == null){
+ //we will default to InMemoryDOMDataStore creation
+ operStore = new InMemoryDOMDataStore("DOM-OPER", storeExecutor);
+ //here we will register the SchemaContext listener
+ getSchemaServiceDependency().registerSchemaServiceListener((InMemoryDOMDataStore)operStore);
+ }
+
+ DOMStore configStore = getConfigDataStoreDependency();
+ if(configStore == null){
+ //we will default to InMemoryDOMDataStore creation
+ configStore = new InMemoryDOMDataStore("DOM-CFG", storeExecutor);
+ //here we will register the SchemaContext listener
+ getSchemaServiceDependency().registerSchemaServiceListener((InMemoryDOMDataStore)configStore);
+ }
ImmutableMap<LogicalDatastoreType, DOMStore> datastores = ImmutableMap
.<LogicalDatastoreType, DOMStore> builder().put(LogicalDatastoreType.OPERATIONAL, operStore)
.put(LogicalDatastoreType.CONFIGURATION, configStore).build();
getBundleContext().registerService(DOMDataBroker.class, newDataBroker, new Hashtable<String, String>());
- getSchemaServiceDependency().registerSchemaServiceListener(operStore);
- getSchemaServiceDependency().registerSchemaServiceListener(configStore);
return newDataBroker;
}
+++ /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.dom.store.impl.tree;
-
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-
-/**
- * Exception thrown when a proposed change fails validation before being
- * applied into the Data Tree because the Data Tree has been modified
- * in way that a conflicting
- * node is present.
- */
-public class ConflictingModificationAppliedException extends DataValidationFailedException {
-
- /**
- *
- */
- private static final long serialVersionUID = 1L;
-
- public ConflictingModificationAppliedException(final InstanceIdentifier path, final String message, final Throwable cause) {
- super(path, message, cause);
- }
-
- public ConflictingModificationAppliedException(final InstanceIdentifier path, final String message) {
- super(path, message);
- }
-
-}
+++ /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.dom.store.impl.tree;
-
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-
-/**
- * Interface representing a data tree which can be modified in an MVCC fashion.
- */
-public interface DataTree {
- /**
- * Take a read-only point-in-time snapshot of the tree.
- *
- * @return Data tree snapshot.
- */
- DataTreeSnapshot takeSnapshot();
-
- /**
- * Make the data tree use a new schema context. The context will be used
- * only by subsequent operations.
- *
- * @param newSchemaContext new SchemaContext
- * @throws IllegalArgumentException if the new context is incompatible
- */
- void setSchemaContext(SchemaContext newSchemaContext);
-
- /**
- * Validate whether a particular modification can be applied to the data tree.
- */
- void validate(DataTreeModification modification) throws DataValidationFailedException;
-
- /**
- * Prepare a modification for commit.
- *
- * @param modification
- * @return candidate data tree
- */
- DataTreeCandidate prepare(DataTreeModification modification);
-
- /**
- * Commit a data tree candidate.
- *
- * @param candidate data tree candidate
- */
- void commit(DataTreeCandidate candidate);
-}
+++ /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.dom.store.impl.tree;
-
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-
-/**
- * An encapsulation of a validated data tree modification. This candidate
- * is ready for atomic commit to the datastore. It allows access to before-
- * and after-state as it will be seen in to subsequent commit. This capture
- * can be accessed for reference, but cannot be modified and the content
- * is limited to nodes which were affected by the modification from which
- * this instance originated.
- */
-public interface DataTreeCandidate {
- /**
- * Get the candidate tree root node.
- *
- * @return Candidate tree root node
- */
- DataTreeCandidateNode getRootNode();
-
- /**
- * Get the candidate tree root path. This is the path of the root node
- * relative to the root of InstanceIdentifier namespace.
- *
- * @return Relative path of the root node
- */
- InstanceIdentifier getRootPath();
-}
+++ /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.dom.store.impl.tree;
-
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-
-import com.google.common.base.Optional;
-
-/**
- * A single node within a {@link DataTreeCandidate}. The nodes are organized
- * in tree hierarchy, reflecting the modification from which this candidate
- * was created. The node itself exposes the before- and after-image of the
- * tree restricted to the modified nodes.
- */
-public interface DataTreeCandidateNode {
- /**
- * Get the node identifier.
- *
- * @return The node identifier.
- */
- PathArgument getIdentifier();
-
- /**
- * Get an unmodifiable iterable of modified child nodes.
- *
- * @return Unmodifiable iterable of modified child nodes.
- */
- Iterable<DataTreeCandidateNode> getChildNodes();
-
- /**
- * Return the type of modification this node is undergoing.
- *
- * @return Node modification type.
- */
- ModificationType getModificationType();
-
- /**
- * Return the before-image of data corresponding to the node.
- *
- * @return Node data as they were present in the tree before
- * the modification was applied.
- */
- Optional<NormalizedNode<?, ?>> getDataAfter();
-
- /**
- * Return the after-image of data corresponding to the node.
- *
- * @return Node data as they will be present in the tree after
- * the modification is applied.
- */
- Optional<NormalizedNode<?, ?>> getDataBefore();
-}
+++ /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.dom.store.impl.tree;
-
-/**
- * Factory interface for creating data trees.
- */
-public interface DataTreeFactory {
- /**
- * Create a new data tree.
- *
- * @return A data tree instance.
- */
- DataTree create();
-}
+++ /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.dom.store.impl.tree;
-
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-
-/**
- * Class encapsulation of set of modifications to a base tree. This tree is backed
- * by a read-only snapshot and tracks modifications on top of that. The modification
- * has the ability to rebase itself to a new snapshot.
- */
-public interface DataTreeModification extends DataTreeSnapshot {
- /**
- * Delete the node at specified path.
- *
- * @param path Node path
- */
- void delete(InstanceIdentifier path);
-
- /**
- * Merge the specified data with the currently-present data
- * at specified path.
- *
- * @param path Node path
- * @param data Data to be merged
- */
- void merge(InstanceIdentifier path, NormalizedNode<?, ?> data);
-
- /**
- * Replace the data at specified path with supplied data.
- *
- * @param path Node path
- * @param data New node data
- */
- void write(InstanceIdentifier path, NormalizedNode<?, ?> data);
-
- /**
- * Finish creation of a modification, making it ready for application
- * to the data tree. Any calls to this object's methods will result
- * in undefined behavior, possibly with an
- * {@link IllegalStateException} being thrown.
- */
- void ready();
-}
+++ /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.dom.store.impl.tree;
-
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-
-import com.google.common.base.Optional;
-
-/**
- * Read-only snapshot of a {@link DataTree}. The snapshot is stable and isolated,
- * e.g. data tree changes occurring after the snapshot has been taken are not
- * visible through the snapshot.
- */
-public interface DataTreeSnapshot {
- /**
- * Read a particular node from the snapshot.
- *
- * @param path Path of the node
- * @return Optional result encapsulating the presence and value of the node
- */
- Optional<NormalizedNode<?, ?>> readNode(InstanceIdentifier path);
-
- /**
- * Create a new data tree modification based on this snapshot, using the
- * specified data application strategy.
- *
- * @param strategy data modification strategy
- * @return A new data tree modification
- */
- DataTreeModification newModification();
-}
+++ /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.dom.store.impl.tree;
-
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-
-import com.google.common.base.Preconditions;
-
-/**
- * Exception thrown when a proposed change fails validation before being
- * applied into the datastore. This can have multiple reasons, for example
- * the datastore has been concurrently modified such that a conflicting
- * node is present, or the modification is structurally incorrect.
- */
-public class DataValidationFailedException extends Exception {
- private static final long serialVersionUID = 1L;
- private final InstanceIdentifier path;
-
- /**
- * Create a new instance.
- *
- * @param path Object path which caused this exception
- * @param message Specific message describing the failure
- */
- public DataValidationFailedException(final InstanceIdentifier path, final String message) {
- this(path, message, null);
- }
- /**
- * Create a new instance, initializing
- *
- * @param path Object path which caused this exception
- * @param message Specific message describing the failure
- * @param cause Exception which triggered this failure, may be null
- */
- public DataValidationFailedException(final InstanceIdentifier path, final String message, final Throwable cause) {
- super(message, cause);
- this.path = Preconditions.checkNotNull(path);
- }
-
- /**
- * Returns the offending object path.
- *
- * @return Path of the offending object
- */
- public InstanceIdentifier getPath() {
- return path;
- }
-}
+++ /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.dom.store.impl.tree;
-
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-
-/**
- * Exception thrown when a proposed change fails validation before being
- * applied into the datastore because of incorrect structure of user supplied
- * data.
- *
- */
-public class IncorrectDataStructureException extends DataValidationFailedException {
-
- /**
- *
- */
- private static final long serialVersionUID = 1L;
-
- public IncorrectDataStructureException(final InstanceIdentifier path, final String message, final Throwable cause) {
- super(path, message, cause);
- }
-
- public IncorrectDataStructureException(final InstanceIdentifier path, final String message) {
- super(path, message);
- }
-
-}
+++ /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.dom.store.impl.tree;
-
-/**
- * Enumeration of all possible node modification states. These are used in
- * data tree modification context to quickly assess what sort of modification
- * the node is undergoing.
- */
-public enum ModificationType {
- /**
- * Node is currently unmodified.
- */
- UNMODIFIED,
-
- /**
- * A child node, either direct or indirect, has been modified. This means
- * that the data representation of this node has potentially changed.
- */
- SUBTREE_MODIFIED,
-
- /**
- * This node has been placed into the tree, potentially completely replacing
- * pre-existing contents.
- */
- WRITE,
-
- /**
- * This node has been deleted along with any of its child nodes.
- */
- DELETE,
-
- /**
- * Node has been written into the tree, but instead of replacing pre-existing
- * contents, it has been merged. This means that any incoming nodes which
- * were present in the tree have been replaced, but their child nodes have
- * been retained.
- */
- MERGE,
-}
+++ /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.dom.store.impl.tree;
-
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
-
-import com.google.common.base.Optional;
-
-/**
- * A tree node which has references to its child leaves. This are typically
- * internal non-data leaves, such as containers, lists, etc.
- *
- * @param <C> Final node type
- */
-public interface StoreTreeNode<C extends StoreTreeNode<C>> {
-
- /**
- * Returns a direct child of the node
- *
- * @param child Identifier of child
- * @return Optional with node if the child is existing, {@link Optional#absent()} otherwise.
- */
- Optional<C> getChild(PathArgument child);
-}
+++ /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.dom.store.impl.tree;
-
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
-
-import com.google.common.base.Strings;
-
-/**
- * Data store tree manipulation utilities.
- */
-public final class StoreUtils {
- private static final int STRINGTREE_INDENT = 4;
-
- private StoreUtils() {
- throw new UnsupportedOperationException("Utility class should not be instantiated");
- }
-
- /**
- * Convert a data subtree under a node into a human-readable string format.
- *
- * @param node Data subtree root
- * @return String containing a human-readable form of the subtree.
- */
- public static String toStringTree(final NormalizedNode<?, ?> node) {
- final StringBuilder builder = new StringBuilder();
- toStringTree(builder, node, 0);
- return builder.toString();
- }
-
- private static void toStringTree(final StringBuilder builder, final NormalizedNode<?, ?> node, final int offset) {
- final String prefix = Strings.repeat(" ", offset);
-
- builder.append(prefix).append(toStringTree(node.getIdentifier()));
- if (node instanceof NormalizedNodeContainer<?, ?, ?>) {
- final NormalizedNodeContainer<?, ?, ?> container = (NormalizedNodeContainer<?, ?, ?>) node;
-
- builder.append(" {\n");
- for (NormalizedNode<?, ?> child : container.getValue()) {
- toStringTree(builder, child, offset + STRINGTREE_INDENT);
- }
-
- builder.append(prefix).append('}');
- } else {
- builder.append(' ').append(node.getValue());
- }
- builder.append('\n');
- }
-
- private static String toStringTree(final PathArgument identifier) {
- if (identifier instanceof NodeIdentifierWithPredicates) {
- StringBuilder builder = new StringBuilder();
- builder.append(identifier.getNodeType().getLocalName());
- builder.append(((NodeIdentifierWithPredicates) identifier).getKeyValues().values());
- return builder.toString();
- } else if (identifier instanceof AugmentationIdentifier) {
- return "augmentation";
- }
- return identifier.getNodeType().getLocalName();
- }
-}
+++ /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.dom.store.impl.tree;
-
-import java.util.AbstractMap.SimpleEntry;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-
-/**
- * A set of utility methods for interacting with {@link org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode} objects.
- */
-public final class TreeNodeUtils {
- private TreeNodeUtils() {
- throw new UnsupportedOperationException("Utility class should not be instantiated");
- }
-
- /**
- * Finds a node in tree
- *
- * @param tree Data Tree
- * @param path Path to the node
- * @return Optional with node if the node is present in tree, {@link Optional#absent()} otherwise.
- */
- public static <T extends StoreTreeNode<T>> Optional<T> findNode(final T tree, final InstanceIdentifier path) {
- Optional<T> current = Optional.<T> of(tree);
- Iterator<PathArgument> pathIter = path.getPath().iterator();
- while (current.isPresent() && pathIter.hasNext()) {
- current = current.get().getChild(pathIter.next());
- }
- return current;
- }
-
- public static <T extends StoreTreeNode<T>> T findNodeChecked(final T tree, final InstanceIdentifier path) {
- T current = tree;
- List<PathArgument> nested = new ArrayList<>(path.getPath().size());
- for(PathArgument pathArg : path.getPath()) {
- Optional<T> potential = current.getChild(pathArg);
- nested.add(pathArg);
- Preconditions.checkArgument(potential.isPresent(),"Child %s is not present in tree.",nested);
- current = potential.get();
- }
- return current;
- }
-
- /**
- * Finds a node or closest parent in the tree
- *
- * @param tree Data Tree
- * @param path Path to the node
- * @return Map.Entry Entry with key which is path to closest parent and value is parent node.
- *
- */
- public static <T extends StoreTreeNode<T>> Map.Entry<InstanceIdentifier, T> findClosest(final T tree, final InstanceIdentifier path) {
- return findClosestsOrFirstMatch(tree, path, Predicates.<T>alwaysFalse());
- }
-
- public static <T extends StoreTreeNode<T>> Map.Entry<InstanceIdentifier, T> findClosestsOrFirstMatch(final T tree, final InstanceIdentifier path, final Predicate<T> predicate) {
- Optional<T> parent = Optional.<T>of(tree);
- Optional<T> current = Optional.<T> of(tree);
-
- int nesting = 0;
- Iterator<PathArgument> pathIter = path.getPath().iterator();
- while (current.isPresent() && pathIter.hasNext() && !predicate.apply(current.get())) {
- parent = current;
- current = current.get().getChild(pathIter.next());
- nesting++;
- }
- if(current.isPresent()) {
- final InstanceIdentifier currentPath = new InstanceIdentifier(path.getPath().subList(0, nesting));
- return new SimpleEntry<InstanceIdentifier,T>(currentPath,current.get());
- }
-
- /*
- * Subtracting 1 from nesting level at this point is safe, because we
- * cannot reach here with nesting == 0: that would mean the above check
- * for current.isPresent() failed, which it cannot, as current is always
- * present. At any rate we check state just to be on the safe side.
- */
- Preconditions.checkState(nesting > 0);
- final InstanceIdentifier parentPath = new InstanceIdentifier(path.getPath().subList(0, nesting - 1));
-
- return new SimpleEntry<InstanceIdentifier,T>(parentPath,parent.get());
- }
-
- public static <T extends StoreTreeNode<T>> Optional<T> getChild(final Optional<T> parent,final PathArgument child) {
- if(parent.isPresent()) {
- return parent.get().getChild(child);
- }
- return Optional.absent();
- }
-
-}
+++ /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.dom.store.impl.tree.data;
-
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidate;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-
-import com.google.common.base.Preconditions;
-
-abstract class AbstractDataTreeCandidate implements DataTreeCandidate {
- private final InstanceIdentifier rootPath;
-
- protected AbstractDataTreeCandidate(final InstanceIdentifier rootPath) {
- this.rootPath = Preconditions.checkNotNull(rootPath);
- }
-
- @Override
- public final InstanceIdentifier getRootPath() {
- return rootPath;
- }
-
-}
+++ /dev/null
-package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
-
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
-
-import com.google.common.base.Optional;
-
-/**
- * An implementation of apply operation which fails to do anything,
- * consistently. An instance of this class is used by the data tree
- * if it does not have a SchemaContext attached and hence cannot
- * perform anything meaningful.
- */
-final class AlwaysFailOperation implements ModificationApplyOperation {
- @Override
- public Optional<TreeNode> apply(final ModifiedNode modification,
- final Optional<TreeNode> storeMeta, final Version version) {
- throw new IllegalStateException("Schema Context is not available.");
- }
-
- @Override
- public void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<TreeNode> storeMetadata) {
- throw new IllegalStateException("Schema Context is not available.");
- }
-
- @Override
- public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
- throw new IllegalStateException("Schema Context is not available.");
- }
-
- @Override
- public void verifyStructure(final ModifiedNode modification) {
- throw new IllegalStateException("Schema Context is not available.");
- }
-}
\ No newline at end of file
+++ /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.dom.store.impl.tree.data;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-import java.util.HashSet;
-import java.util.Set;
-import java.util.concurrent.ExecutionException;
-
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAugmentationNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableUnkeyedListEntryNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.AugmentationSchemaProxy;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
-import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-
-/**
- * Base strategy for applying changes to a ContainerNode, irrespective of its
- * actual type.
- *
- * @param <T> Type of the container node
- */
-abstract class DataNodeContainerModificationStrategy<T extends DataNodeContainer> extends NormalizedNodeContainerModificationStrategy {
-
- private final T schema;
- private final LoadingCache<PathArgument, ModificationApplyOperation> childCache = CacheBuilder.newBuilder()
- .build(CacheLoader.from(new Function<PathArgument, ModificationApplyOperation>() {
-
- @Override
- public ModificationApplyOperation apply(final PathArgument identifier) {
- if (identifier instanceof AugmentationIdentifier && schema instanceof AugmentationTarget) {
- return from(schema, (AugmentationTarget) schema, (AugmentationIdentifier) identifier);
- }
-
- DataSchemaNode child = schema.getDataChildByName(identifier.getNodeType());
- if (child == null) {
- return null;
- }
- return from(child);
- }
- }));
-
- protected DataNodeContainerModificationStrategy(final T schema,
- final Class<? extends NormalizedNode<?, ?>> nodeClass) {
- super(nodeClass);
- this.schema = schema;
- }
-
- protected T getSchema() {
- return schema;
- }
-
- @Override
- public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
- try {
- return Optional.<ModificationApplyOperation> fromNullable(childCache.get(identifier));
- } catch (ExecutionException e) {
- return Optional.absent();
- }
- }
-
- @Override
- @SuppressWarnings("rawtypes")
- protected abstract DataContainerNodeBuilder createBuilder(NormalizedNode<?, ?> original);
-
- @Override
- public String toString() {
- return getClass().getSimpleName() + " [" + schema + "]";
- }
-
- public static class AugmentationModificationStrategy extends DataNodeContainerModificationStrategy<AugmentationSchema> {
-
- protected AugmentationModificationStrategy(final AugmentationSchema schema, final DataNodeContainer resolved) {
- super(createAugmentProxy(schema,resolved), AugmentationNode.class);
- }
-
- @Override
- @SuppressWarnings("rawtypes")
- protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
- checkArgument(original instanceof AugmentationNode);
- return ImmutableAugmentationNodeBuilder.create((AugmentationNode) original);
- }
-
-
- private static AugmentationSchema createAugmentProxy(final AugmentationSchema schema, final DataNodeContainer resolved) {
- Set<DataSchemaNode> realChildSchemas = new HashSet<>();
- for(DataSchemaNode augChild : schema.getChildNodes()) {
- realChildSchemas.add(resolved.getDataChildByName(augChild.getQName()));
- }
- return new AugmentationSchemaProxy(schema, realChildSchemas);
- }
- }
-
- public static class ContainerModificationStrategy extends DataNodeContainerModificationStrategy<ContainerSchemaNode> {
-
- public ContainerModificationStrategy(final ContainerSchemaNode schemaNode) {
- super(schemaNode, ContainerNode.class);
- }
-
- @Override
- @SuppressWarnings("rawtypes")
- protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
- checkArgument(original instanceof ContainerNode);
- return ImmutableContainerNodeBuilder.create((ContainerNode) original);
- }
- }
-
- public static class ListEntryModificationStrategy extends DataNodeContainerModificationStrategy<ListSchemaNode> {
-
- protected ListEntryModificationStrategy(final ListSchemaNode schema) {
- super(schema, MapEntryNode.class);
- }
-
- @Override
- @SuppressWarnings("rawtypes")
- protected final DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
- checkArgument(original instanceof MapEntryNode);
- return ImmutableMapEntryNodeBuilder.create((MapEntryNode) original);
- }
- }
-
- public static class UnkeyedListItemModificationStrategy extends DataNodeContainerModificationStrategy<ListSchemaNode> {
-
- public UnkeyedListItemModificationStrategy(final ListSchemaNode schemaNode) {
- super(schemaNode, UnkeyedListEntryNode.class);
- }
-
- @Override
- @SuppressWarnings("rawtypes")
- protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
- checkArgument(original instanceof UnkeyedListEntryNode);
- return ImmutableUnkeyedListEntryNodeBuilder.create((UnkeyedListEntryNode) original);
- }
- }
-}
\ No newline at end of file
+++ /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.dom.store.impl.tree.data;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTree;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidate;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeModification;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataValidationFailedException;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreUtils;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
-/**
- * Read-only snapshot of the data tree.
- */
-final class InMemoryDataTree implements DataTree {
- private static final Logger LOG = LoggerFactory.getLogger(InMemoryDataTree.class);
- private static final InstanceIdentifier PUBLIC_ROOT_PATH = InstanceIdentifier.builder().build();
-
- private final ReadWriteLock rwLock = new ReentrantReadWriteLock(true);
- private ModificationApplyOperation applyOper = new AlwaysFailOperation();
- private SchemaContext currentSchemaContext;
- private TreeNode rootNode;
-
- public InMemoryDataTree(final TreeNode rootNode, final SchemaContext schemaContext) {
- this.rootNode = Preconditions.checkNotNull(rootNode);
-
- if (schemaContext != null) {
- // Also sets applyOper
- setSchemaContext(schemaContext);
- }
- }
-
- @Override
- public synchronized void setSchemaContext(final SchemaContext newSchemaContext) {
- Preconditions.checkNotNull(newSchemaContext);
-
- LOG.info("Attepting to install schema context {}", newSchemaContext);
-
- /*
- * FIXME: we should walk the schema contexts, both current and new and see
- * whether they are compatible here. Reject incompatible changes.
- */
-
- // Instantiate new apply operation, this still may fail
- final ModificationApplyOperation newApplyOper = SchemaAwareApplyOperation.from(newSchemaContext);
-
- // Ready to change the context now, make sure no operations are running
- rwLock.writeLock().lock();
- try {
- this.applyOper = newApplyOper;
- this.currentSchemaContext = newSchemaContext;
- } finally {
- rwLock.writeLock().unlock();
- }
- }
-
- @Override
- public InMemoryDataTreeSnapshot takeSnapshot() {
- rwLock.readLock().lock();
- try {
- return new InMemoryDataTreeSnapshot(currentSchemaContext, rootNode, applyOper);
- } finally {
- rwLock.readLock().unlock();
- }
- }
-
- @Override
- public void validate(final DataTreeModification modification) throws DataValidationFailedException {
- Preconditions.checkArgument(modification instanceof InMemoryDataTreeModification, "Invalid modification class %s", modification.getClass());
-
- final InMemoryDataTreeModification m = (InMemoryDataTreeModification)modification;
- m.getStrategy().checkApplicable(PUBLIC_ROOT_PATH, m.getRootModification(), Optional.<TreeNode>of(rootNode));
- }
-
- @Override
- public synchronized DataTreeCandidate prepare(final DataTreeModification modification) {
- Preconditions.checkArgument(modification instanceof InMemoryDataTreeModification, "Invalid modification class %s", modification.getClass());
-
- final InMemoryDataTreeModification m = (InMemoryDataTreeModification)modification;
- final ModifiedNode root = m.getRootModification();
-
- if (root.getType() == ModificationType.UNMODIFIED) {
- return new NoopDataTreeCandidate(PUBLIC_ROOT_PATH, root);
- }
-
- rwLock.writeLock().lock();
- try {
- final Optional<TreeNode> newRoot = m.getStrategy().apply(m.getRootModification(),
- Optional.<TreeNode>of(rootNode), rootNode.getSubtreeVersion().next());
- Preconditions.checkState(newRoot.isPresent(), "Apply strategy failed to produce root node");
- return new InMemoryDataTreeCandidate(PUBLIC_ROOT_PATH, root, rootNode, newRoot.get());
- } finally {
- rwLock.writeLock().unlock();
- }
- }
-
- @Override
- public synchronized void commit(final DataTreeCandidate candidate) {
- if (candidate instanceof NoopDataTreeCandidate) {
- return;
- }
-
- Preconditions.checkArgument(candidate instanceof InMemoryDataTreeCandidate, "Invalid candidate class %s", candidate.getClass());
- final InMemoryDataTreeCandidate c = (InMemoryDataTreeCandidate)candidate;
-
- LOG.debug("Updating datastore from {} to {}", rootNode, c.getAfterRoot());
-
- if (LOG.isTraceEnabled()) {
- LOG.trace("Data Tree is {}", StoreUtils.toStringTree(c.getAfterRoot().getData()));
- }
-
- // Ready to change the context now, make sure no operations are running
- rwLock.writeLock().lock();
- try {
- Preconditions.checkState(c.getBeforeRoot() == rootNode,
- String.format("Store tree %s and candidate base %s differ.", rootNode, c.getBeforeRoot()));
- this.rootNode = c.getAfterRoot();
- } finally {
- rwLock.writeLock().unlock();
- }
- }
-}
+++ /dev/null
-package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
-
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidateNode;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Iterables;
-
-final class InMemoryDataTreeCandidate extends AbstractDataTreeCandidate {
- private static abstract class AbstractNode implements DataTreeCandidateNode {
- private final ModifiedNode mod;
- private final TreeNode newMeta;
- private final TreeNode oldMeta;
-
- protected AbstractNode(final ModifiedNode mod,
- final TreeNode oldMeta, final TreeNode newMeta) {
- this.newMeta = newMeta;
- this.oldMeta = oldMeta;
- this.mod = Preconditions.checkNotNull(mod);
- }
-
- protected final ModifiedNode getMod() {
- return mod;
- }
-
- protected final TreeNode getNewMeta() {
- return newMeta;
- }
-
- protected final TreeNode getOldMeta() {
- return oldMeta;
- }
-
- private static final TreeNode childMeta(final TreeNode parent, final PathArgument id) {
- if (parent != null) {
- return parent.getChild(id).orNull();
- } else {
- return null;
- }
- }
-
- @Override
- public Iterable<DataTreeCandidateNode> getChildNodes() {
- return Iterables.transform(mod.getChildren(), new Function<ModifiedNode, DataTreeCandidateNode>() {
- @Override
- public DataTreeCandidateNode apply(final ModifiedNode input) {
- final PathArgument id = input.getIdentifier();
- return new ChildNode(input, childMeta(oldMeta, id), childMeta(newMeta, id));
- }
- });
- }
-
- @Override
- public ModificationType getModificationType() {
- return mod.getType();
- }
-
- private Optional<NormalizedNode<?, ?>> optionalData(final TreeNode meta) {
- if (meta != null) {
- return Optional.<NormalizedNode<?,?>>of(meta.getData());
- } else {
- return Optional.absent();
- }
- }
-
- @Override
- public Optional<NormalizedNode<?, ?>> getDataAfter() {
- return optionalData(newMeta);
- }
-
- @Override
- public Optional<NormalizedNode<?, ?>> getDataBefore() {
- return optionalData(oldMeta);
- }
- }
-
- private static final class ChildNode extends AbstractNode {
- public ChildNode(final ModifiedNode mod, final TreeNode oldMeta, final TreeNode newMeta) {
- super(mod, oldMeta, newMeta);
- }
-
- @Override
- public PathArgument getIdentifier() {
- return getMod().getIdentifier();
- }
- }
-
- private static final class RootNode extends AbstractNode {
- public RootNode(final ModifiedNode mod, final TreeNode oldMeta, final TreeNode newMeta) {
- super(mod, oldMeta, newMeta);
- }
-
- @Override
- public PathArgument getIdentifier() {
- throw new IllegalStateException("Attempted to get identifier of the root node");
- }
- }
-
- private final RootNode root;
-
- InMemoryDataTreeCandidate(final InstanceIdentifier rootPath, final ModifiedNode modificationRoot,
- final TreeNode beforeRoot, final TreeNode afterRoot) {
- super(rootPath);
- this.root = new RootNode(modificationRoot, beforeRoot, afterRoot);
- }
-
- TreeNode getAfterRoot() {
- return root.getNewMeta();
- }
-
- TreeNode getBeforeRoot() {
- return root.getOldMeta();
- }
-
- @Override
- public DataTreeCandidateNode getRootNode() {
- return root;
- }
-}
+++ /dev/null
-package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
-
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeFactory;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNodeFactory;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-
-/**
- * A factory for creating in-memory data trees.
- */
-public final class InMemoryDataTreeFactory implements DataTreeFactory {
- private static final InMemoryDataTreeFactory INSTANCE = new InMemoryDataTreeFactory();
-
- private InMemoryDataTreeFactory() {
- // Never instantiated externally
- }
-
- @Override
- public InMemoryDataTree create() {
- final NodeIdentifier root = new NodeIdentifier(SchemaContext.NAME);
- final NormalizedNode<?, ?> data = Builders.containerBuilder().withNodeIdentifier(root).build();
-
- return new InMemoryDataTree(TreeNodeFactory.createTreeNode(data, Version.initial()), null);
- }
-
- /**
- * Get an instance of this factory. This method cannot fail.
- *
- * @return Data tree factory instance.
- */
- public static final InMemoryDataTreeFactory getInstance() {
- return INSTANCE;
- }
-}
+++ /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.dom.store.impl.tree.data;
-
-import java.util.Map.Entry;
-
-import javax.annotation.concurrent.GuardedBy;
-
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeModification;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.TreeNodeUtils;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
-import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-
-final class InMemoryDataTreeModification implements DataTreeModification {
- private static final Logger LOG = LoggerFactory.getLogger(InMemoryDataTreeModification.class);
- private final ModificationApplyOperation strategyTree;
- private final InMemoryDataTreeSnapshot snapshot;
- private final ModifiedNode rootNode;
-
- @GuardedBy("this")
- private boolean sealed = false;
-
- InMemoryDataTreeModification(final InMemoryDataTreeSnapshot snapshot, final ModificationApplyOperation resolver) {
- this.snapshot = Preconditions.checkNotNull(snapshot);
- this.strategyTree = Preconditions.checkNotNull(resolver);
- this.rootNode = ModifiedNode.createUnmodified(snapshot.getRootNode());
- }
-
- ModifiedNode getRootModification() {
- return rootNode;
- }
-
- ModificationApplyOperation getStrategy() {
- return strategyTree;
- }
-
- @Override
- public synchronized void write(final InstanceIdentifier path, final NormalizedNode<?, ?> value) {
- checkSealed();
- resolveModificationFor(path).write(value);
- }
-
- @Override
- public synchronized void merge(final InstanceIdentifier path, final NormalizedNode<?, ?> data) {
- checkSealed();
- mergeImpl(resolveModificationFor(path),data);
- }
-
- private void mergeImpl(final OperationWithModification op,final NormalizedNode<?,?> data) {
-
- if(data instanceof NormalizedNodeContainer<?,?,?>) {
- @SuppressWarnings({ "rawtypes", "unchecked" })
- NormalizedNodeContainer<?,?,NormalizedNode<PathArgument, ?>> dataContainer = (NormalizedNodeContainer) data;
- for(NormalizedNode<PathArgument, ?> child : dataContainer.getValue()) {
- PathArgument childId = child.getIdentifier();
- mergeImpl(op.forChild(childId), child);
- }
- }
- op.merge(data);
- }
-
- @Override
- public synchronized void delete(final InstanceIdentifier path) {
- checkSealed();
- resolveModificationFor(path).delete();
- }
-
- @Override
- public synchronized Optional<NormalizedNode<?, ?>> readNode(final InstanceIdentifier path) {
- /*
- * Walk the tree from the top, looking for the first node between root and
- * the requested path which has been modified. If no such node exists,
- * we use the node itself.
- */
- final Entry<InstanceIdentifier, ModifiedNode> entry = TreeNodeUtils.findClosestsOrFirstMatch(rootNode, path, ModifiedNode.IS_TERMINAL_PREDICATE);
- final InstanceIdentifier key = entry.getKey();
- final ModifiedNode mod = entry.getValue();
-
- final Optional<TreeNode> result = resolveSnapshot(key, mod);
- if (result.isPresent()) {
- NormalizedNode<?, ?> data = result.get().getData();
- return NormalizedNodeUtils.findNode(key, data, path);
- } else {
- return Optional.absent();
- }
- }
-
- private Optional<TreeNode> resolveSnapshot(final InstanceIdentifier path,
- final ModifiedNode modification) {
- final Optional<Optional<TreeNode>> potentialSnapshot = modification.getSnapshotCache();
- if(potentialSnapshot.isPresent()) {
- return potentialSnapshot.get();
- }
-
- try {
- return resolveModificationStrategy(path).apply(modification, modification.getOriginal(),
- snapshot.getRootNode().getSubtreeVersion().next());
- } catch (Exception e) {
- LOG.error("Could not create snapshot for {}:{}", path,modification,e);
- throw e;
- }
- }
-
- private ModificationApplyOperation resolveModificationStrategy(final InstanceIdentifier path) {
- LOG.trace("Resolving modification apply strategy for {}", path);
- return TreeNodeUtils.findNodeChecked(strategyTree, path);
- }
-
- private OperationWithModification resolveModificationFor(final InstanceIdentifier path) {
- ModifiedNode modification = rootNode;
- // We ensure strategy is present.
- ModificationApplyOperation operation = resolveModificationStrategy(path);
- for (PathArgument pathArg : path.getPath()) {
- modification = modification.modifyChild(pathArg);
- }
- return OperationWithModification.from(operation, modification);
- }
-
- @Override
- public synchronized void ready() {
- Preconditions.checkState(!sealed, "Attempted to seal an already-sealed Data Tree.");
- sealed = true;
- rootNode.seal();
- }
-
- @GuardedBy("this")
- private void checkSealed() {
- Preconditions.checkState(!sealed, "Data Tree is sealed. No further modifications allowed.");
- }
-
- @Override
- public String toString() {
- return "MutableDataTree [modification=" + rootNode + "]";
- }
-
- @Override
- public synchronized DataTreeModification newModification() {
- Preconditions.checkState(sealed, "Attempted to chain on an unsealed modification");
-
- if(rootNode.getType() == ModificationType.UNMODIFIED) {
- return snapshot.newModification();
- }
-
- /*
- * FIXME: Add advanced transaction chaining for modification of not rebased
- * modification.
- *
- * Current computation of tempRoot may yeld incorrect subtree versions
- * if there are multiple concurrent transactions, which may break
- * versioning preconditions for modification of previously occured write,
- * directly nested under parent node, since node version is derived from
- * subtree version.
- *
- * For deeper nodes subtree version is derived from their respective metadata
- * nodes, so this incorrect root subtree version is not affecting us.
- */
- TreeNode originalSnapshotRoot = snapshot.getRootNode();
- Optional<TreeNode> tempRoot = strategyTree.apply(rootNode, Optional.of(originalSnapshotRoot), originalSnapshotRoot.getSubtreeVersion().next());
-
- InMemoryDataTreeSnapshot tempTree = new InMemoryDataTreeSnapshot(snapshot.getSchemaContext(), tempRoot.get(), strategyTree);
- return tempTree.newModification();
- }
-}
+++ /dev/null
-package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
-
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeSnapshot;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeUtils;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-
-final class InMemoryDataTreeSnapshot implements DataTreeSnapshot {
- private final ModificationApplyOperation applyOper;
- private final SchemaContext schemaContext;
- private final TreeNode rootNode;
-
- InMemoryDataTreeSnapshot(final SchemaContext schemaContext, final TreeNode rootNode,
- final ModificationApplyOperation applyOper) {
- this.schemaContext = Preconditions.checkNotNull(schemaContext);
- this.rootNode = Preconditions.checkNotNull(rootNode);
- this.applyOper = Preconditions.checkNotNull(applyOper);
- }
-
- TreeNode getRootNode() {
- return rootNode;
- }
-
- SchemaContext getSchemaContext() {
- return schemaContext;
- }
-
- @Override
- public Optional<NormalizedNode<?, ?>> readNode(final InstanceIdentifier path) {
- return NormalizedNodeUtils.findNode(rootNode.getData(), path);
- }
-
- @Override
- public InMemoryDataTreeModification newModification() {
- return new InMemoryDataTreeModification(this, applyOper);
- }
-
- @Override
- public String toString() {
- return rootNode.getSubtreeVersion().toString();
- }
-
-}
\ No newline at end of file
+++ /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.dom.store.impl.tree.data;
-
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataValidationFailedException;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreTreeNode;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
-
-import com.google.common.base.Optional;
-
-/**
- *
- * Operation responsible for applying {@link ModifiedNode} on tree.
- *
- * Operation is composite - operation on top level node consists of
- * suboperations on child nodes. This allows to walk operation hierarchy and
- * invoke suboperations independently.
- *
- * <b>Implementation notes</b>
- * <ul>
- * <li>
- * Implementations MUST expose all nested suboperations which operates on child
- * nodes expose via {@link #getChild(PathArgument)} method.
- * <li>Same suboperations SHOULD be used when invoked via
- * {@link #apply(ModifiedNode, Optional)} if applicable.
- *
- *
- * Hierarchical composite operation which is responsible for applying
- * modification on particular subtree and creating updated subtree
- *
- *
- */
-interface ModificationApplyOperation extends StoreTreeNode<ModificationApplyOperation> {
-
- /**
- *
- * Implementation of this operation must be stateless and must not change
- * state of this object.
- *
- * @param modification
- * NodeModification to be applied
- * @param storeMeta
- * Store Metadata Node on which NodeModification should be
- * applied
- * @param version New subtree version of parent node
- * @throws IllegalArgumentException
- * If it is not possible to apply Operation on provided Metadata
- * node
- * @return new {@link StoreMetadataNode} if operation resulted in updating
- * node, {@link Optional#absent()} if {@link ModifiedNode}
- * resulted in deletion of this node.
- */
- Optional<TreeNode> apply(ModifiedNode modification, Optional<TreeNode> storeMeta, Version version);
-
- /**
- *
- * Performs structural verification of NodeModification, such as writen values / types
- * uses right structural elements.
- *
- * @param modification to be verified.
- * @throws IllegalArgumentException If provided NodeModification does not adhere to the structure.
- */
- void verifyStructure(ModifiedNode modification) throws IllegalArgumentException;
-
- /**
- * Returns a suboperation for specified tree node
- *
- * @return Reference to suboperation for specified tree node, {@link Optional#absent()}
- * if suboperation is not supported for specified tree node.
- */
- @Override
- Optional<ModificationApplyOperation> getChild(PathArgument child);
-
- /**
- *
- * Checks if provided node modification could be applied to current metadata node.
- *
- * @param modification Modification
- * @param current Metadata Node to which modification should be applied
- * @return true if modification is applicable
- * false if modification is no applicable
- * @throws DataValidationFailedException
- */
- void checkApplicable(InstanceIdentifier path, NodeModification modification, Optional<TreeNode> current) throws DataValidationFailedException;
-}
+++ /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.dom.store.impl.tree.data;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-import javax.annotation.concurrent.GuardedBy;
-
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreTreeNode;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
-import org.opendaylight.yangtools.concepts.Identifiable;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Predicate;
-
-/**
- * Node Modification Node and Tree
- *
- * Tree which structurally resembles data tree and captures client modifications
- * to the data store tree.
- *
- * This tree is lazily created and populated via {@link #modifyChild(PathArgument)}
- * and {@link StoreMetadataNode} which represents original state {@link #getOriginal()}.
- */
-final class ModifiedNode implements StoreTreeNode<ModifiedNode>, Identifiable<PathArgument>, NodeModification {
-
- public static final Predicate<ModifiedNode> IS_TERMINAL_PREDICATE = new Predicate<ModifiedNode>() {
- @Override
- public boolean apply(final ModifiedNode input) {
- switch (input.getType()) {
- case DELETE:
- case MERGE:
- case WRITE:
- return true;
- case SUBTREE_MODIFIED:
- case UNMODIFIED:
- return false;
- }
-
- throw new IllegalArgumentException(String.format("Unhandled modification type %s", input.getType()));
- }
- };
-
- private final Map<PathArgument, ModifiedNode> children = new LinkedHashMap<>();
- private final Optional<TreeNode> original;
- private final PathArgument identifier;
- private ModificationType modificationType = ModificationType.UNMODIFIED;
- private Optional<TreeNode> snapshotCache;
- private NormalizedNode<?, ?> value;
-
- private ModifiedNode(final PathArgument identifier, final Optional<TreeNode> original) {
- this.identifier = identifier;
- this.original = original;
- }
-
- /**
- *
- *
- * @return
- */
- public NormalizedNode<?, ?> getWrittenValue() {
- return value;
- }
-
- @Override
- public PathArgument getIdentifier() {
- return identifier;
- }
-
- /**
- *
- * Returns original store metadata
- * @return original store metadata
- */
- @Override
- public Optional<TreeNode> getOriginal() {
- return original;
- }
-
- /**
- * Returns modification type
- *
- * @return modification type
- */
- @Override
- public ModificationType getType() {
- return modificationType;
- }
-
- /**
- *
- * Returns child modification if child was modified
- *
- * @return Child modification if direct child or it's subtree
- * was modified.
- *
- */
- @Override
- public Optional<ModifiedNode> getChild(final PathArgument child) {
- return Optional.<ModifiedNode> fromNullable(children.get(child));
- }
-
- /**
- *
- * Returns child modification if child was modified, creates {@link ModifiedNode}
- * for child otherwise.
- *
- * If this node's {@link ModificationType} is {@link ModificationType#UNMODIFIED}
- * changes modification type to {@link ModificationType#SUBTREE_MODIFIED}
- *
- * @param child
- * @return {@link ModifiedNode} for specified child, with {@link #getOriginal()}
- * containing child metadata if child was present in original data.
- */
- public ModifiedNode modifyChild(final PathArgument child) {
- clearSnapshot();
- if (modificationType == ModificationType.UNMODIFIED) {
- updateModificationType(ModificationType.SUBTREE_MODIFIED);
- }
- final ModifiedNode potential = children.get(child);
- if (potential != null) {
- return potential;
- }
-
- final Optional<TreeNode> currentMetadata;
- if (original.isPresent()) {
- final TreeNode orig = original.get();
- currentMetadata = orig.getChild(child);
- } else {
- currentMetadata = Optional.absent();
- }
-
- ModifiedNode newlyCreated = new ModifiedNode(child, currentMetadata);
- children.put(child, newlyCreated);
- return newlyCreated;
- }
-
- /**
- *
- * Returns all recorded direct child modification
- *
- * @return all recorded direct child modifications
- */
- @Override
- public Iterable<ModifiedNode> getChildren() {
- return children.values();
- }
-
- /**
- *
- * Records a delete for associated node.
- *
- */
- public void delete() {
- clearSnapshot();
- updateModificationType(ModificationType.DELETE);
- children.clear();
- this.value = null;
- }
-
- /**
- *
- * Records a write for associated node.
- *
- * @param value
- */
- public void write(final NormalizedNode<?, ?> value) {
- clearSnapshot();
- updateModificationType(ModificationType.WRITE);
- children.clear();
- this.value = value;
- }
-
- public void merge(final NormalizedNode<?, ?> data) {
- clearSnapshot();
- updateModificationType(ModificationType.MERGE);
- // FIXME: Probably merge with previous value.
- this.value = data;
- }
-
- void seal() {
- clearSnapshot();
- for (ModifiedNode child : children.values()) {
- child.seal();
- }
- }
-
- private void clearSnapshot() {
- snapshotCache = null;
- }
-
- public Optional<TreeNode> storeSnapshot(final Optional<TreeNode> snapshot) {
- snapshotCache = snapshot;
- return snapshot;
- }
-
- public Optional<Optional<TreeNode>> getSnapshotCache() {
- return Optional.fromNullable(snapshotCache);
- }
-
- @GuardedBy("this")
- private void updateModificationType(final ModificationType type) {
- modificationType = type;
- clearSnapshot();
- }
-
- @Override
- public String toString() {
- return "NodeModification [identifier=" + identifier + ", modificationType="
- + modificationType + ", childModification=" + children + "]";
- }
-
- public static ModifiedNode createUnmodified(final TreeNode metadataTree) {
- return new ModifiedNode(metadataTree.getIdentifier(), Optional.of(metadataTree));
- }
-}
+++ /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.dom.store.impl.tree.data;
-
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
-import org.opendaylight.yangtools.concepts.Identifiable;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
-
-import com.google.common.base.Optional;
-
-/**
- * Internal interface representing a modification action of a particular node.
- * It is used by the validation code to allow for a read-only view of the
- * modification tree as we should never modify that during validation.
- */
-interface NodeModification extends Identifiable<PathArgument> {
- /**
- * Get the type of modification.
- *
- * @return Modification type.
- */
- ModificationType getType();
-
- /**
- * Get the original tree node to which the modification is to be applied.
- *
- * @return The original node, or {@link Optional#absent()} if the node is
- * a new node.
- */
- Optional<TreeNode> getOriginal();
-
- /**
- * Get a read-only view of children nodes.
- *
- * @return Iterable of all children nodes.
- */
- Iterable<? extends NodeModification> getChildren();
-}
+++ /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.dom.store.impl.tree.data;
-
-import java.util.Collections;
-
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidateNode;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-
-/**
- * Internal utility class for an empty candidate. We instantiate this class
- * for empty modifications, saving memory and processing speed. Instances
- * of this class are explicitly recognized and processing of them is skipped.
- */
-final class NoopDataTreeCandidate extends AbstractDataTreeCandidate {
- private static final DataTreeCandidateNode ROOT = new DataTreeCandidateNode() {
- @Override
- public ModificationType getModificationType() {
- return ModificationType.UNMODIFIED;
- }
-
- @Override
- public Iterable<DataTreeCandidateNode> getChildNodes() {
- return Collections.emptyList();
- }
-
- @Override
- public PathArgument getIdentifier() {
- throw new IllegalStateException("Attempted to read identifier of the no-operation change");
- }
-
- @Override
- public Optional<NormalizedNode<?, ?>> getDataAfter() {
- return Optional.absent();
- }
-
- @Override
- public Optional<NormalizedNode<?, ?>> getDataBefore() {
- return Optional.absent();
- }
- };
-
- protected NoopDataTreeCandidate(final InstanceIdentifier rootPath, final ModifiedNode modificationRoot) {
- super(rootPath);
- Preconditions.checkArgument(modificationRoot.getType() == ModificationType.UNMODIFIED);
- }
-
- @Override
- public DataTreeCandidateNode getRootNode() {
- return ROOT;
- }
-}
+++ /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.dom.store.impl.tree.data;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-import java.util.Map;
-
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataValidationFailedException;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.DataNodeContainerModificationStrategy.ListEntryModificationStrategy;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.ValueNodeModificationStrategy.LeafSetEntryModificationStrategy;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.MutableTreeNode;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNodeFactory;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeWithValue;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
-import org.opendaylight.yangtools.yang.data.api.schema.OrderedLeafSetNode;
-import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableChoiceNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedLeafSetNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedMapNodeBuilder;
-import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
-import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-
-import com.google.common.base.Optional;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
-
-abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareApplyOperation {
-
- private final Class<? extends NormalizedNode<?, ?>> nodeClass;
-
- protected NormalizedNodeContainerModificationStrategy(final Class<? extends NormalizedNode<?, ?>> nodeClass) {
- this.nodeClass = nodeClass;
- }
-
- @Override
- public void verifyStructure(final ModifiedNode modification) throws IllegalArgumentException {
- if (modification.getType() == ModificationType.WRITE) {
-
- }
- for (ModifiedNode childModification : modification.getChildren()) {
- resolveChildOperation(childModification.getIdentifier()).verifyStructure(childModification);
- }
- }
-
- @Override
- protected void checkWriteApplicable(final InstanceIdentifier path, final NodeModification modification,
- final Optional<TreeNode> current) throws DataValidationFailedException {
- // FIXME: Implement proper write check for replacement of node container
- // prerequisite is to have transaction chain available for clients
- // otherwise this will break chained writes to same node.
- }
-
- @SuppressWarnings("rawtypes")
- @Override
- protected void verifyWrittenStructure(final NormalizedNode<?, ?> writtenValue) {
- checkArgument(nodeClass.isInstance(writtenValue), "Node should must be of type %s", nodeClass);
- checkArgument(writtenValue instanceof NormalizedNodeContainer);
-
- NormalizedNodeContainer container = (NormalizedNodeContainer) writtenValue;
- for (Object child : container.getValue()) {
- checkArgument(child instanceof NormalizedNode);
-
- /*
- * FIXME: fail-fast semantics:
- *
- * We can validate the data structure here, aborting the commit
- * before it ever progresses to being committed.
- */
- }
- }
-
- @Override
- protected TreeNode applyWrite(final ModifiedNode modification,
- final Optional<TreeNode> currentMeta, final Version version) {
- final NormalizedNode<?, ?> newValue = modification.getWrittenValue();
- final TreeNode newValueMeta = TreeNodeFactory.createTreeNode(newValue, version);
-
- if (Iterables.isEmpty(modification.getChildren())) {
- return newValueMeta;
- }
-
- /*
- * This is where things get interesting. The user has performed a write and
- * then she applied some more modifications to it. So we need to make sense
- * of that an apply the operations on top of the written value. We could have
- * done it during the write, but this operation is potentially expensive, so
- * we have left it out of the fast path.
- *
- * As it turns out, once we materialize the written data, we can share the
- * code path with the subtree change. So let's create an unsealed TreeNode
- * and run the common parts on it -- which end with the node being sealed.
- */
- final MutableTreeNode mutable = newValueMeta.mutable();
- mutable.setSubtreeVersion(version);
-
- @SuppressWarnings("rawtypes")
- final NormalizedNodeContainerBuilder dataBuilder = createBuilder(newValue);
-
- return mutateChildren(mutable, dataBuilder, version, modification.getChildren());
- }
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- private TreeNode mutateChildren(final MutableTreeNode meta, final NormalizedNodeContainerBuilder data,
- final Version nodeVersion, final Iterable<ModifiedNode> modifications) {
-
- for (ModifiedNode mod : modifications) {
- final PathArgument id = mod.getIdentifier();
- final Optional<TreeNode> cm = meta.getChild(id);
-
- Optional<TreeNode> result = resolveChildOperation(id).apply(mod, cm, nodeVersion);
- if (result.isPresent()) {
- final TreeNode tn = result.get();
- meta.addChild(tn);
- data.addChild(tn.getData());
- } else {
- meta.removeChild(id);
- data.removeChild(id);
- }
- }
-
- meta.setData(data.build());
- return meta.seal();
- }
-
- @Override
- protected TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta,
- final Version version) {
- // For Node Containers - merge is same as subtree change - we only replace children.
- return applySubtreeChange(modification, currentMeta, version);
- }
-
- @Override
- public TreeNode applySubtreeChange(final ModifiedNode modification,
- final TreeNode currentMeta, final Version version) {
- final MutableTreeNode newMeta = currentMeta.mutable();
- newMeta.setSubtreeVersion(version);
-
- @SuppressWarnings("rawtypes")
- NormalizedNodeContainerBuilder dataBuilder = createBuilder(currentMeta.getData());
-
- return mutateChildren(newMeta, dataBuilder, version, modification.getChildren());
- }
-
- @Override
- protected void checkSubtreeModificationApplicable(final InstanceIdentifier path, final NodeModification modification,
- final Optional<TreeNode> current) throws DataValidationFailedException {
- checkConflicting(path, current.isPresent(), "Node was deleted by other transaction.");
- checkChildPreconditions(path, modification, current);
- }
-
- private void checkChildPreconditions(final InstanceIdentifier path, final NodeModification modification, final Optional<TreeNode> current) throws DataValidationFailedException {
- final TreeNode currentMeta = current.get();
- for (NodeModification childMod : modification.getChildren()) {
- final PathArgument childId = childMod.getIdentifier();
- final Optional<TreeNode> childMeta = currentMeta.getChild(childId);
-
- InstanceIdentifier childPath = path.node(childId);
- resolveChildOperation(childId).checkApplicable(childPath, childMod, childMeta);
- }
- }
-
- @Override
- protected void checkMergeApplicable(final InstanceIdentifier path, final NodeModification modification,
- final Optional<TreeNode> current) throws DataValidationFailedException {
- if(current.isPresent()) {
- checkChildPreconditions(path, modification,current);
- }
- }
-
- @SuppressWarnings("rawtypes")
- protected abstract NormalizedNodeContainerBuilder createBuilder(NormalizedNode<?, ?> original);
-
- public static class ChoiceModificationStrategy extends NormalizedNodeContainerModificationStrategy {
-
- private final Map<PathArgument, ModificationApplyOperation> childNodes;
-
- public ChoiceModificationStrategy(final ChoiceNode schemaNode) {
- super(org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode.class);
- ImmutableMap.Builder<PathArgument, ModificationApplyOperation> child = ImmutableMap.builder();
-
- for (ChoiceCaseNode caze : schemaNode.getCases()) {
- for (DataSchemaNode cazeChild : caze.getChildNodes()) {
- SchemaAwareApplyOperation childNode = from(cazeChild);
- child.put(new NodeIdentifier(cazeChild.getQName()), childNode);
- }
- }
- childNodes = child.build();
- }
-
- @Override
- public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
- return Optional.fromNullable(childNodes.get(child));
- }
-
- @Override
- @SuppressWarnings("rawtypes")
- protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
- checkArgument(original instanceof org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode);
- return ImmutableChoiceNodeBuilder.create((org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode) original);
- }
- }
-
- public static class OrderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy {
-
- private final Optional<ModificationApplyOperation> entryStrategy;
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- protected OrderedLeafSetModificationStrategy(final LeafListSchemaNode schema) {
- super((Class) LeafSetNode.class);
- entryStrategy = Optional.<ModificationApplyOperation> of(new LeafSetEntryModificationStrategy(schema));
- }
-
- @SuppressWarnings("rawtypes")
- @Override
- protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
- checkArgument(original instanceof OrderedLeafSetNode<?>);
- return ImmutableOrderedLeafSetNodeBuilder.create((OrderedLeafSetNode<?>) original);
- }
-
- @Override
- public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
- if (identifier instanceof NodeWithValue) {
- return entryStrategy;
- }
- return Optional.absent();
- }
- }
-
- public static class OrderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy {
-
- private final Optional<ModificationApplyOperation> entryStrategy;
-
- protected OrderedMapModificationStrategy(final ListSchemaNode schema) {
- super(OrderedMapNode.class);
- entryStrategy = Optional.<ModificationApplyOperation> of(new ListEntryModificationStrategy(schema));
- }
-
- @SuppressWarnings("rawtypes")
- @Override
- protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
- checkArgument(original instanceof OrderedMapNode);
- return ImmutableOrderedMapNodeBuilder.create((OrderedMapNode) original);
- }
-
- @Override
- public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
- if (identifier instanceof NodeIdentifierWithPredicates) {
- return entryStrategy;
- }
- return Optional.absent();
- }
-
- @Override
- public String toString() {
- return "OrderedMapModificationStrategy [entry=" + entryStrategy + "]";
- }
- }
-
- public static class UnorderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy {
-
- private final Optional<ModificationApplyOperation> entryStrategy;
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- protected UnorderedLeafSetModificationStrategy(final LeafListSchemaNode schema) {
- super((Class) LeafSetNode.class);
- entryStrategy = Optional.<ModificationApplyOperation> of(new LeafSetEntryModificationStrategy(schema));
- }
-
- @SuppressWarnings("rawtypes")
- @Override
- protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
- checkArgument(original instanceof LeafSetNode<?>);
- return ImmutableLeafSetNodeBuilder.create((LeafSetNode<?>) original);
- }
-
- @Override
- public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
- if (identifier instanceof NodeWithValue) {
- return entryStrategy;
- }
- return Optional.absent();
- }
- }
-
- public static class UnorderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy {
-
- private final Optional<ModificationApplyOperation> entryStrategy;
-
- protected UnorderedMapModificationStrategy(final ListSchemaNode schema) {
- super(MapNode.class);
- entryStrategy = Optional.<ModificationApplyOperation> of(new ListEntryModificationStrategy(schema));
- }
-
- @SuppressWarnings("rawtypes")
- @Override
- protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
- checkArgument(original instanceof MapNode);
- return ImmutableMapNodeBuilder.create((MapNode) original);
- }
-
- @Override
- public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
- if (identifier instanceof NodeIdentifierWithPredicates) {
- return entryStrategy;
- }
- return Optional.absent();
- }
-
- @Override
- public String toString() {
- return "UnorderedMapModificationStrategy [entry=" + entryStrategy + "]";
- }
- }
-}
+++ /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.dom.store.impl.tree.data;
-
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-
-import com.google.common.base.Optional;
-
-final class OperationWithModification {
-
- private final ModifiedNode modification;
-
- private final ModificationApplyOperation applyOperation;
-
- private OperationWithModification(final ModificationApplyOperation op, final ModifiedNode mod) {
- this.modification = mod;
- this.applyOperation = op;
- }
-
- public OperationWithModification write(final NormalizedNode<?, ?> value) {
- modification.write(value);
- applyOperation.verifyStructure(modification);
- return this;
- }
-
- public OperationWithModification delete() {
- modification.delete();
- return this;
- }
-
- public ModifiedNode getModification() {
- return modification;
- }
-
- public ModificationApplyOperation getApplyOperation() {
- return applyOperation;
- }
-
- public Optional<TreeNode> apply(final Optional<TreeNode> data, final Version version) {
- return applyOperation.apply(modification, data, version);
- }
-
- public static OperationWithModification from(final ModificationApplyOperation operation,
- final ModifiedNode modification) {
- return new OperationWithModification(operation, modification);
-
- }
-
- public void merge(final NormalizedNode<?, ?> data) {
- modification.merge(data);
- applyOperation.verifyStructure(modification);
-
- }
-
- public OperationWithModification forChild(final PathArgument childId) {
- ModifiedNode childMod = modification.modifyChild(childId);
- Optional<ModificationApplyOperation> childOp = applyOperation.getChild(childId);
- return from(childOp.get(),childMod);
- }
-}
+++ /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.dom.store.impl.tree.data;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-import java.util.List;
-
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.ConflictingModificationAppliedException;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataValidationFailedException;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.IncorrectDataStructureException;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.DataNodeContainerModificationStrategy.ContainerModificationStrategy;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.DataNodeContainerModificationStrategy.UnkeyedListItemModificationStrategy;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.NormalizedNodeContainerModificationStrategy.ChoiceModificationStrategy;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.NormalizedNodeContainerModificationStrategy.OrderedLeafSetModificationStrategy;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.NormalizedNodeContainerModificationStrategy.OrderedMapModificationStrategy;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.NormalizedNodeContainerModificationStrategy.UnorderedLeafSetModificationStrategy;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.ValueNodeModificationStrategy.LeafModificationStrategy;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNodeFactory;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
-import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
-import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-
-abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
- private static final Logger LOG = LoggerFactory.getLogger(SchemaAwareApplyOperation.class);
-
- public static SchemaAwareApplyOperation from(final DataSchemaNode schemaNode) {
- if (schemaNode instanceof ContainerSchemaNode) {
- return new ContainerModificationStrategy((ContainerSchemaNode) schemaNode);
- } else if (schemaNode instanceof ListSchemaNode) {
- return fromListSchemaNode((ListSchemaNode) schemaNode);
- } else if (schemaNode instanceof ChoiceNode) {
- return new ChoiceModificationStrategy((ChoiceNode) schemaNode);
- } else if (schemaNode instanceof LeafListSchemaNode) {
- return fromLeafListSchemaNode((LeafListSchemaNode) schemaNode);
- } else if (schemaNode instanceof LeafSchemaNode) {
- return new LeafModificationStrategy((LeafSchemaNode) schemaNode);
- }
- throw new IllegalArgumentException("Not supported schema node type for " + schemaNode.getClass());
- }
-
- public static SchemaAwareApplyOperation from(final DataNodeContainer resolvedTree,
- final AugmentationTarget augSchemas, final AugmentationIdentifier identifier) {
- AugmentationSchema augSchema = null;
-
- allAugments:
- for (AugmentationSchema potential : augSchemas.getAvailableAugmentations()) {
- for (DataSchemaNode child : potential.getChildNodes()) {
- if (identifier.getPossibleChildNames().contains(child.getQName())) {
- augSchema = potential;
- break allAugments;
- }
- }
- }
-
- if (augSchema != null) {
- return new DataNodeContainerModificationStrategy.AugmentationModificationStrategy(augSchema, resolvedTree);
- }
- return null;
- }
-
- public static boolean checkConflicting(final InstanceIdentifier path, final boolean condition, final String message) throws ConflictingModificationAppliedException {
- if(!condition) {
- throw new ConflictingModificationAppliedException(path, message);
- }
- return condition;
- }
-
- private static SchemaAwareApplyOperation fromListSchemaNode(final ListSchemaNode schemaNode) {
- List<QName> keyDefinition = schemaNode.getKeyDefinition();
- if (keyDefinition == null || keyDefinition.isEmpty()) {
- return new UnkeyedListModificationStrategy(schemaNode);
- }
- if (schemaNode.isUserOrdered()) {
- return new OrderedMapModificationStrategy(schemaNode);
- }
-
- return new NormalizedNodeContainerModificationStrategy.UnorderedMapModificationStrategy(schemaNode);
- }
-
- private static SchemaAwareApplyOperation fromLeafListSchemaNode(final LeafListSchemaNode schemaNode) {
- if(schemaNode.isUserOrdered()) {
- return new OrderedLeafSetModificationStrategy(schemaNode);
- } else {
- return new UnorderedLeafSetModificationStrategy(schemaNode);
- }
- }
-
- private static final void checkNotConflicting(final InstanceIdentifier path, final TreeNode original, final TreeNode current) throws ConflictingModificationAppliedException {
- checkConflicting(path, original.getVersion().equals(current.getVersion()),
- "Node was replaced by other transaction.");
- checkConflicting(path, original.getSubtreeVersion().equals(current.getSubtreeVersion()),
- "Node children was modified by other transaction");
- }
-
- protected final ModificationApplyOperation resolveChildOperation(final PathArgument child) {
- Optional<ModificationApplyOperation> potential = getChild(child);
- checkArgument(potential.isPresent(), "Operation for child %s is not defined.", child);
- return potential.get();
- }
-
- @Override
- public void verifyStructure(final ModifiedNode modification) throws IllegalArgumentException {
- if (modification.getType() == ModificationType.WRITE) {
- verifyWrittenStructure(modification.getWrittenValue());
- }
- }
-
- @Override
- public final void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<TreeNode> current) throws DataValidationFailedException {
- switch (modification.getType()) {
- case DELETE:
- checkDeleteApplicable(modification, current);
- case SUBTREE_MODIFIED:
- checkSubtreeModificationApplicable(path, modification, current);
- return;
- case WRITE:
- checkWriteApplicable(path, modification, current);
- return;
- case MERGE:
- checkMergeApplicable(path, modification, current);
- return;
- case UNMODIFIED:
- return;
- default:
- throw new UnsupportedOperationException("Suplied modification type "+ modification.getType()+ "is not supported.");
- }
-
- }
-
- protected void checkMergeApplicable(final InstanceIdentifier path, final NodeModification modification, final Optional<TreeNode> current) throws DataValidationFailedException {
- Optional<TreeNode> original = modification.getOriginal();
- if (original.isPresent() && current.isPresent()) {
- /*
- * We need to do conflict detection only and only if the value of leaf changed
- * before two transactions. If value of leaf is unchanged between two transactions
- * it should not cause transaction to fail, since result of this merge
- * leads to same data.
- */
- if(!original.get().getData().equals(current.get().getData())) {
- checkNotConflicting(path, original.get(), current.get());
- }
- }
- }
-
- protected void checkWriteApplicable(final InstanceIdentifier path, final NodeModification modification, final Optional<TreeNode> current) throws DataValidationFailedException {
- Optional<TreeNode> original = modification.getOriginal();
- if (original.isPresent() && current.isPresent()) {
- checkNotConflicting(path, original.get(), current.get());
- } else if(original.isPresent()) {
- throw new ConflictingModificationAppliedException(path,"Node was deleted by other transaction.");
- }
- }
-
- private void checkDeleteApplicable(final NodeModification modification, final Optional<TreeNode> current) {
- // Delete is always applicable, we do not expose it to subclasses
- if (current.isPresent()) {
- LOG.trace("Delete operation turned to no-op on missing node {}", modification);
- }
- }
-
- @Override
- public final Optional<TreeNode> apply(final ModifiedNode modification,
- final Optional<TreeNode> currentMeta, final Version version) {
-
- switch (modification.getType()) {
- case DELETE:
- return modification.storeSnapshot(Optional.<TreeNode> absent());
- case SUBTREE_MODIFIED:
- Preconditions.checkArgument(currentMeta.isPresent(), "Metadata not available for modification",
- modification);
- return modification.storeSnapshot(Optional.of(applySubtreeChange(modification, currentMeta.get(),
- version)));
- case MERGE:
- if(currentMeta.isPresent()) {
- return modification.storeSnapshot(Optional.of(applyMerge(modification,currentMeta.get(), version)));
- } // Fallback to write is intentional - if node is not preexisting merge is same as write
- case WRITE:
- return modification.storeSnapshot(Optional.of(applyWrite(modification, currentMeta, version)));
- case UNMODIFIED:
- return currentMeta;
- default:
- throw new IllegalArgumentException("Provided modification type is not supported.");
- }
- }
-
- protected abstract TreeNode applyMerge(ModifiedNode modification,
- TreeNode currentMeta, Version version);
-
- protected abstract TreeNode applyWrite(ModifiedNode modification,
- Optional<TreeNode> currentMeta, Version version);
-
- protected abstract TreeNode applySubtreeChange(ModifiedNode modification,
- TreeNode currentMeta, Version version);
-
- /**
- *
- * Checks is supplied {@link NodeModification} is applicable for Subtree Modification.
- *
- * @param path Path to current node
- * @param modification Node modification which should be applied.
- * @param current Current state of data tree
- * @throws ConflictingModificationAppliedException If subtree was changed in conflicting way
- * @throws IncorrectDataStructureException If subtree modification is not applicable (e.g. leaf node).
- */
- protected abstract void checkSubtreeModificationApplicable(InstanceIdentifier path, final NodeModification modification,
- final Optional<TreeNode> current) throws DataValidationFailedException;
-
- protected abstract void verifyWrittenStructure(NormalizedNode<?, ?> writtenValue);
-
- public static class UnkeyedListModificationStrategy extends SchemaAwareApplyOperation {
-
- private final Optional<ModificationApplyOperation> entryStrategy;
-
- protected UnkeyedListModificationStrategy(final ListSchemaNode schema) {
- entryStrategy = Optional.<ModificationApplyOperation> of(new UnkeyedListItemModificationStrategy(schema));
- }
-
- @Override
- protected TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta,
- final Version version) {
- return applyWrite(modification, Optional.of(currentMeta), version);
- }
-
- @Override
- protected TreeNode applySubtreeChange(final ModifiedNode modification,
- final TreeNode currentMeta, final Version version) {
- throw new UnsupportedOperationException("UnkeyedList does not support subtree change.");
- }
-
- @Override
- protected TreeNode applyWrite(final ModifiedNode modification,
- final Optional<TreeNode> currentMeta, final Version version) {
- return TreeNodeFactory.createTreeNode(modification.getWrittenValue(), version);
- }
-
- @Override
- public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
- if (child instanceof NodeIdentifier) {
- return entryStrategy;
- }
- return Optional.absent();
- }
-
- @Override
- protected void verifyWrittenStructure(final NormalizedNode<?, ?> writtenValue) {
-
- }
-
- @Override
- protected void checkSubtreeModificationApplicable(final InstanceIdentifier path, final NodeModification modification,
- final Optional<TreeNode> current) throws IncorrectDataStructureException {
- throw new IncorrectDataStructureException(path, "Subtree modification is not allowed.");
- }
- }
-}
+++ /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.dom.store.impl.tree.data;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.IncorrectDataStructureException;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNodeFactory;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-
-import com.google.common.base.Optional;
-
-abstract class ValueNodeModificationStrategy<T extends DataSchemaNode> extends SchemaAwareApplyOperation {
-
- private final T schema;
- private final Class<? extends NormalizedNode<?, ?>> nodeClass;
-
- protected ValueNodeModificationStrategy(final T schema, final Class<? extends NormalizedNode<?, ?>> nodeClass) {
- super();
- this.schema = schema;
- this.nodeClass = nodeClass;
- }
-
- @Override
- protected void verifyWrittenStructure(final NormalizedNode<?, ?> writtenValue) {
- checkArgument(nodeClass.isInstance(writtenValue), "Node should must be of type %s", nodeClass);
- }
-
- @Override
- public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
- throw new UnsupportedOperationException("Node " + schema.getPath()
- + "is leaf type node. Child nodes not allowed");
- }
-
- @Override
- protected TreeNode applySubtreeChange(final ModifiedNode modification,
- final TreeNode currentMeta, final Version version) {
- throw new UnsupportedOperationException("Node " + schema.getPath()
- + "is leaf type node. Subtree change is not allowed.");
- }
-
- @Override
- protected TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta,
- final Version version) {
- // Just overwrite whatever was there
- return applyWrite(modification, null, version);
- }
-
- @Override
- protected TreeNode applyWrite(final ModifiedNode modification,
- final Optional<TreeNode> currentMeta, final Version version) {
- return TreeNodeFactory.createTreeNode(modification.getWrittenValue(), version);
- }
-
- @Override
- protected void checkSubtreeModificationApplicable(final InstanceIdentifier path, final NodeModification modification,
- final Optional<TreeNode> current) throws IncorrectDataStructureException {
- throw new IncorrectDataStructureException(path, "Subtree modification is not allowed.");
- }
-
- public static class LeafSetEntryModificationStrategy extends ValueNodeModificationStrategy<LeafListSchemaNode> {
- @SuppressWarnings({ "unchecked", "rawtypes" })
- protected LeafSetEntryModificationStrategy(final LeafListSchemaNode schema) {
- super(schema, (Class) LeafSetEntryNode.class);
- }
- }
-
- public static class LeafModificationStrategy extends ValueNodeModificationStrategy<LeafSchemaNode> {
- @SuppressWarnings({ "unchecked", "rawtypes" })
- protected LeafModificationStrategy(final LeafSchemaNode schema) {
- super(schema, (Class) LeafNode.class);
- }
- }
-}
\ No newline at end of file
+++ /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.dom.store.impl.tree.spi;
-
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-
-import com.google.common.base.Preconditions;
-
-/**
- * A very basic data tree node.
- */
-abstract class AbstractTreeNode implements TreeNode {
- private final NormalizedNode<?, ?> data;
- private final Version version;
-
- protected AbstractTreeNode(final NormalizedNode<?, ?> data, final Version version) {
- this.data = Preconditions.checkNotNull(data);
- this.version = Preconditions.checkNotNull(version);
- }
-
- @Override
- public PathArgument getIdentifier() {
- return data.getIdentifier();
- }
-
- @Override
- public final Version getVersion() {
- return version;
- }
-
- @Override
- public final NormalizedNode<?, ?> getData() {
- return data;
- }
-}
+++ /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.dom.store.impl.tree.spi;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.opendaylight.yangtools.util.MapAdaptor;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
-import org.opendaylight.yangtools.yang.data.api.schema.OrderedNodeContainer;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-
-/**
- * A TreeNode capable of holding child nodes. The fact that any of the children
- * changed is tracked by the subtree version.
- */
-final class ContainerNode extends AbstractTreeNode {
- private final Map<PathArgument, TreeNode> children;
- private final Version subtreeVersion;
-
- protected ContainerNode(final NormalizedNode<?, ?> data, final Version version,
- final Map<PathArgument, TreeNode> children, final Version subtreeVersion) {
- super(data, version);
- this.children = Preconditions.checkNotNull(children);
- this.subtreeVersion = Preconditions.checkNotNull(subtreeVersion);
- }
-
- @Override
- public Version getSubtreeVersion() {
- return subtreeVersion;
- }
-
- @Override
- public Optional<TreeNode> getChild(final PathArgument key) {
- return Optional.fromNullable(children.get(key));
- }
-
- @Override
- public MutableTreeNode mutable() {
- return new Mutable(this);
- }
-
- private static final class Mutable implements MutableTreeNode {
- private final Version version;
- private Map<PathArgument, TreeNode> children;
- private NormalizedNode<?, ?> data;
- private Version subtreeVersion;
-
- private Mutable(final ContainerNode parent) {
- this.data = parent.getData();
- this.children = MapAdaptor.getDefaultInstance().takeSnapshot(parent.children);
- this.subtreeVersion = parent.getSubtreeVersion();
- this.version = parent.getVersion();
- }
-
- @Override
- public Optional<TreeNode> getChild(final PathArgument child) {
- return Optional.fromNullable(children.get(child));
- }
-
- @Override
- public void setSubtreeVersion(final Version subtreeVersion) {
- this.subtreeVersion = Preconditions.checkNotNull(subtreeVersion);
- }
-
- @Override
- public void addChild(final TreeNode child) {
- children.put(child.getIdentifier(), child);
- }
-
- @Override
- public void removeChild(final PathArgument id) {
- children.remove(id);
- }
-
- @Override
- public TreeNode seal() {
- final TreeNode ret = new ContainerNode(data, version, MapAdaptor.getDefaultInstance().optimize(children), subtreeVersion);
-
- // This forces a NPE if this class is accessed again. Better than corruption.
- children = null;
- return ret;
- }
-
- @Override
- public void setData(final NormalizedNode<?, ?> data) {
- this.data = Preconditions.checkNotNull(data);
- }
- }
-
- private static ContainerNode create(final Version version, final NormalizedNode<?, ?> data,
- final Iterable<NormalizedNode<?, ?>> children) {
-
- final Map<PathArgument, TreeNode> map = new HashMap<>();
- for (NormalizedNode<?, ?> child : children) {
- map.put(child.getIdentifier(), TreeNodeFactory.createTreeNode(child, version));
- }
-
- return new ContainerNode(data, version, map, version);
- }
-
- public static ContainerNode create(final Version version, final NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>> container) {
- return create(version, container, container.getValue());
- }
-
- public static ContainerNode create(final Version version, final OrderedNodeContainer<NormalizedNode<?, ?>> container) {
- return create(version, container, container.getValue());
- }
-}
+++ /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.dom.store.impl.tree.spi;
-
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreTreeNode;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-
-/**
- * A mutable tree node. This is a transient view materialized from a pre-existing
- * node. Modifications are isolated. Once this object is {@link #seal()}-ed,
- * any interactions with it will result in undefined behavior.
- */
-public interface MutableTreeNode extends StoreTreeNode<TreeNode> {
- /**
- * Set the data component of the node.
- *
- * @param data New data component, may not be null.
- */
- void setData(NormalizedNode<?, ?> data);
-
- /**
- * Set the new subtree version. This is typically invoked when the user
- * has modified some of this node's children.
- *
- * @param subtreeVersion New subtree version.
- */
- void setSubtreeVersion(Version subtreeVersion);
-
- /**
- * Add a new child node. This acts as add-or-replace operation, e.g. it
- * succeeds even if a conflicting child is already present.
- *
- * @param child New child node.
- */
- void addChild(TreeNode child);
-
- /**
- * Remove a child node. This acts as delete-or-nothing operation, e.g. it
- * succeeds even if the corresponding child is not present.
- *
- * @param id Child identificator.
- */
- void removeChild(PathArgument id);
-
- /**
- * Finish node modification and return a read-only view of this node. After
- * this method is invoked, any further calls to this object's method result
- * in undefined behavior.
- *
- * @return Read-only view of this node.
- */
- TreeNode seal();
-}
+++ /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.dom.store.impl.tree.spi;
-
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreTreeNode;
-import org.opendaylight.yangtools.concepts.Identifiable;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-
-/**
- * A very basic data tree node. It has a version (when it was last modified),
- * a subtree version (when any of its children were modified) and some read-only
- * data.
- */
-public interface TreeNode extends Identifiable<PathArgument>, StoreTreeNode<TreeNode> {
- /**
- * Get the data node version.
- *
- * @return Current data node version.
- */
- Version getVersion();
-
- /**
- * Get the subtree version.
- *
- * @return Current subtree version.
- */
- Version getSubtreeVersion();
-
- /**
- * Get a read-only view of the underlying data.
- *
- * @return Unmodifiable view of the underlying data.
- */
- NormalizedNode<?, ?> getData();
-
- /**
- * Get a mutable, isolated copy of the node.
- *
- * @return Mutable copy
- */
- MutableTreeNode mutable();
-}
+++ /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.dom.store.impl.tree.spi;
-
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
-import org.opendaylight.yangtools.yang.data.api.schema.OrderedNodeContainer;
-
-/**
- * Public entrypoint for other packages. Allows instantiating a tree node
- * with specified version.
- */
-public final class TreeNodeFactory {
- private TreeNodeFactory() {
- throw new UnsupportedOperationException("Utility class should not be instantiated");
- }
-
- /**
- * Create a new AbstractTreeNode from a data node, descending recursively as needed.
- * This method should only ever be used for new data.
- *
- * @param data data node
- * @param version data node version
- * @return new AbstractTreeNode instance, covering the data tree provided
- */
- public static final TreeNode createTreeNode(final NormalizedNode<?, ?> data, final Version version) {
- if (data instanceof NormalizedNodeContainer<?, ?, ?>) {
- @SuppressWarnings("unchecked")
- NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>> container = (NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>>) data;
- return ContainerNode.create(version, container);
-
- }
- if (data instanceof OrderedNodeContainer<?>) {
- @SuppressWarnings("unchecked")
- OrderedNodeContainer<NormalizedNode<?, ?>> container = (OrderedNodeContainer<NormalizedNode<?, ?>>) data;
- return ContainerNode.create(version, container);
- }
-
- return new ValueNode(data, version);
- }
-}
+++ /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.dom.store.impl.tree.spi;
-
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Optional;
-
-/**
- * Concretization of AbstractTreeNode for leaf nodes which only contain data.
- * Instances of this class report all children as absent, subtree version
- * equal to this node's version and do not support mutable view.
- */
-final class ValueNode extends AbstractTreeNode {
- private static final Logger LOG = LoggerFactory.getLogger(ValueNode.class);
-
- protected ValueNode(final NormalizedNode<?, ?> data, final Version version) {
- super(data, version);
- }
-
- @Override
- public Optional<TreeNode> getChild(final PathArgument childId) {
- LOG.warn("Attempted to access child {} of value-node {}", childId, this);
- return Optional.absent();
- }
-
- @Override
- public Version getSubtreeVersion() {
- return getVersion();
- }
-
- @Override
- public MutableTreeNode mutable() {
- /**
- * Value nodes can only we read/written/delete, which does a straight
- * replace. That means they don't haver need to be made mutable.
- */
- throw new UnsupportedOperationException(String.format("Attempted to mutate value-node %s", this));
- }
-}
+++ /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.dom.store.impl.tree.spi;
-
-/**
- * The concept of a version, either node version, or a subtree version. The
- * only interface contract this class has is that no two versions are the
- * same.
- */
-public final class Version {
- private Version() {
-
- }
-
- /**
- * Create a new version, distinct from any other version.
- *
- * @return a new version.
- */
- public Version next() {
- return new Version();
- }
-
- /**
- * Create an initial version.
- *
- * @return a new version.
- */
- public static final Version initial() {
- return new Version();
- }
-}
import config { prefix config; revision-date 2013-04-05; }
import opendaylight-md-sal-dom {prefix sal;}
import opendaylight-md-sal-common {prefix common;}
+ import opendaylight-config-dom-datastore {prefix config-dom-store-spi;}
+ import opendaylight-operational-dom-datastore {prefix operational-dom-store-spi;}
description
- "Service definition for Binding Aware MD-SAL.";
+ "Service definition for Binding Aware MD-SAL.
+ Note: The dom-inmemory-data-broker utilizes configurable config-dom-datastore
+ and operation-dom-datastore. If configuration is not done for this stores
+ then it defaults to InMemoryDOMDataStore";
revision "2013-10-28" {
description
augment "/config:modules/config:module/config:configuration" {
case dom-inmemory-data-broker {
when "/config:modules/config:module/config:type = 'dom-inmemory-data-broker'";
-
+
+
container schema-service {
uses config:service-ref {
refine type {
config:required-identity sal:schema-service;
}
}
-
+
+ }
+
+ container config-data-store{
+ uses config:service-ref {
+ refine type {
+ mandatory false;
+ config:required-identity config-dom-store-spi:config-dom-datastore;
+ }
+ }
+ }
+
+ container operational-data-store{
+ uses config:service-ref {
+ refine type {
+ mandatory false;
+ config:required-identity operational-dom-store-spi:operational-dom-datastore;
+ }
+ }
}
}
}
@Before
public void setupStore() {
- InMemoryDOMDataStore operStore = new InMemoryDOMDataStore("OPER", MoreExecutors.sameThreadExecutor());
- InMemoryDOMDataStore configStore = new InMemoryDOMDataStore("CFG", MoreExecutors.sameThreadExecutor());
+ InMemoryDOMDataStore operStore = new InMemoryDOMDataStore("OPER", MoreExecutors.sameThreadExecutor());
+ InMemoryDOMDataStore configStore = new InMemoryDOMDataStore("CFG", MoreExecutors.sameThreadExecutor());
schemaContext = TestModel.createTestContext();
operStore.onGlobalContextUpdated(schemaContext);
+++ /dev/null
-package org.opendaylight.controller.md.sal.dom.store.impl;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.concurrent.ExecutionException;
-
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
-import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
-import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
-import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.MoreExecutors;
-
-public class InMemoryDataStoreTest {
-
- private SchemaContext schemaContext;
- private InMemoryDOMDataStore domStore;
-
- @Before
- public void setupStore() {
- domStore = new InMemoryDOMDataStore("TEST", MoreExecutors.sameThreadExecutor());
- schemaContext = TestModel.createTestContext();
- domStore.onGlobalContextUpdated(schemaContext);
-
- }
-
- @Test
- public void testTransactionIsolation() throws InterruptedException, ExecutionException {
-
- assertNotNull(domStore);
-
- DOMStoreReadTransaction readTx = domStore.newReadOnlyTransaction();
- assertNotNull(readTx);
-
- DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction();
- assertNotNull(writeTx);
- /**
- *
- * Writes /test in writeTx
- *
- */
- writeTx.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
-
- /**
- *
- * Reads /test from writeTx Read should return container.
- *
- */
- ListenableFuture<Optional<NormalizedNode<?, ?>>> writeTxContainer = writeTx.read(TestModel.TEST_PATH);
- assertTrue(writeTxContainer.get().isPresent());
-
- /**
- *
- * Reads /test from readTx Read should return Absent.
- *
- */
- ListenableFuture<Optional<NormalizedNode<?, ?>>> readTxContainer = readTx.read(TestModel.TEST_PATH);
- assertFalse(readTxContainer.get().isPresent());
- }
-
- @Test
- public void testTransactionCommit() throws InterruptedException, ExecutionException {
-
- DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction();
- assertNotNull(writeTx);
- /**
- *
- * Writes /test in writeTx
- *
- */
- writeTx.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
-
- /**
- *
- * Reads /test from writeTx Read should return container.
- *
- */
- ListenableFuture<Optional<NormalizedNode<?, ?>>> writeTxContainer = writeTx.read(TestModel.TEST_PATH);
- assertTrue(writeTxContainer.get().isPresent());
-
- DOMStoreThreePhaseCommitCohort cohort = writeTx.ready();
-
- assertThreePhaseCommit(cohort);
-
- Optional<NormalizedNode<?, ?>> afterCommitRead = domStore.newReadOnlyTransaction().read(TestModel.TEST_PATH)
- .get();
- assertTrue(afterCommitRead.isPresent());
- }
-
- @Test
- public void testTransactionAbort() throws InterruptedException, ExecutionException {
-
- DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction();
- assertNotNull(writeTx);
-
- assertTestContainerWrite(writeTx);
-
- DOMStoreThreePhaseCommitCohort cohort = writeTx.ready();
-
- assertTrue(cohort.canCommit().get().booleanValue());
- cohort.preCommit().get();
- cohort.abort().get();
-
- Optional<NormalizedNode<?, ?>> afterCommitRead = domStore.newReadOnlyTransaction().read(TestModel.TEST_PATH)
- .get();
- assertFalse(afterCommitRead.isPresent());
- }
-
- @Test
- public void testTransactionChain() throws InterruptedException, ExecutionException {
- DOMStoreTransactionChain txChain = domStore.createTransactionChain();
- assertNotNull(txChain);
-
- /**
- * We alocate new read-write transaction and write /test
- *
- *
- */
- DOMStoreReadWriteTransaction firstTx = txChain.newReadWriteTransaction();
- assertTestContainerWrite(firstTx);
-
- /**
- * First transaction is marked as ready, we are able to allocate chained
- * transactions
- */
- DOMStoreThreePhaseCommitCohort firstWriteTxCohort = firstTx.ready();
-
- /**
- * We alocate chained transaction - read transaction, note first one is
- * still not commited to datastore.
- */
- DOMStoreReadTransaction secondReadTx = txChain.newReadOnlyTransaction();
-
- /**
- *
- * We test if we are able to read data from tx, read should not fail
- * since we are using chained transaction.
- *
- *
- */
- assertTestContainerExists(secondReadTx);
-
- /**
- *
- * We alocate next transaction, which is still based on first one, but
- * is read-write.
- *
- */
- DOMStoreReadWriteTransaction thirdDeleteTx = txChain.newReadWriteTransaction();
-
- /**
- * We test existence of /test in third transaction container should
- * still be visible from first one (which is still uncommmited).
- *
- *
- */
- assertTestContainerExists(thirdDeleteTx);
-
- /**
- * We delete node in third transaction
- */
- thirdDeleteTx.delete(TestModel.TEST_PATH);
-
- /**
- * third transaction is sealed.
- */
- DOMStoreThreePhaseCommitCohort thirdDeleteTxCohort = thirdDeleteTx.ready();
-
- /**
- * We commit first transaction
- *
- */
- assertThreePhaseCommit(firstWriteTxCohort);
-
- // Alocates store transacion
- DOMStoreReadTransaction storeReadTx = domStore.newReadOnlyTransaction();
- /**
- * We verify transaction is commited to store, container should exists
- * in datastore.
- */
- assertTestContainerExists(storeReadTx);
- /**
- * We commit third transaction
- *
- */
- assertThreePhaseCommit(thirdDeleteTxCohort);
- }
-
- @Test
- @Ignore
- public void testTransactionConflict() throws InterruptedException, ExecutionException {
- DOMStoreReadWriteTransaction txOne = domStore.newReadWriteTransaction();
- DOMStoreReadWriteTransaction txTwo = domStore.newReadWriteTransaction();
- assertTestContainerWrite(txOne);
- assertTestContainerWrite(txTwo);
-
- /**
- * Commits transaction
- */
- assertThreePhaseCommit(txOne.ready());
-
- /**
- * Asserts that txTwo could not be commited
- */
- assertFalse(txTwo.ready().canCommit().get());
- }
-
- private static void assertThreePhaseCommit(final DOMStoreThreePhaseCommitCohort cohort)
- throws InterruptedException, ExecutionException {
- assertTrue(cohort.canCommit().get().booleanValue());
- cohort.preCommit().get();
- cohort.commit().get();
- }
-
- private static Optional<NormalizedNode<?, ?>> assertTestContainerWrite(final DOMStoreReadWriteTransaction writeTx)
- throws InterruptedException, ExecutionException {
- /**
- *
- * Writes /test in writeTx
- *
- */
- writeTx.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
-
- return assertTestContainerExists(writeTx);
- }
-
- /**
- *
- * Reads /test from readTx Read should return container.
- *
- */
- private static Optional<NormalizedNode<?, ?>> assertTestContainerExists(DOMStoreReadTransaction readTx)
- throws InterruptedException, ExecutionException {
-
- ListenableFuture<Optional<NormalizedNode<?, ?>>> writeTxContainer = readTx.read(TestModel.TEST_PATH);
- assertTrue(writeTxContainer.get().isPresent());
- return writeTxContainer.get();
- }
-
-}
*/
package org.opendaylight.controller.md.sal.dom.store.impl;
-import java.io.InputStream;
-import java.util.Collections;
-import java.util.Set;
-
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.Set;
+
public class TestModel {
public static final QName TEST_QNAME = QName.create("urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test", "2014-03-13",
+++ /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.dom.store.impl.tree.data;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-import static org.opendaylight.controller.md.sal.dom.store.impl.TestModel.ID_QNAME;
-import static org.opendaylight.controller.md.sal.dom.store.impl.TestModel.INNER_LIST_QNAME;
-import static org.opendaylight.controller.md.sal.dom.store.impl.TestModel.NAME_QNAME;
-import static org.opendaylight.controller.md.sal.dom.store.impl.TestModel.OUTER_LIST_PATH;
-import static org.opendaylight.controller.md.sal.dom.store.impl.TestModel.OUTER_LIST_QNAME;
-import static org.opendaylight.controller.md.sal.dom.store.impl.TestModel.TEST_PATH;
-import static org.opendaylight.controller.md.sal.dom.store.impl.TestModel.TEST_QNAME;
-import static org.opendaylight.controller.md.sal.dom.store.impl.TestModel.VALUE_QNAME;
-import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntry;
-import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntryBuilder;
-import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapNodeBuilder;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.opendaylight.controller.md.sal.dom.store.impl.TestModel;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTree;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeModification;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNodeFactory;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-
-import com.google.common.base.Optional;
-
-/**
- *
- * Schema structure of document is
- *
- * <pre>
- * container root {Â
- * list list-a {
- * key leaf-a;
- * leaf leaf-a;
- * choice choice-a {
- * case one {
- * leaf one;
- * }
- * case two-three {
- * leaf two;
- * leaf three;
- * }
- * }
- * list list-b {
- * key leaf-b;
- * leaf leaf-b;
- * }
- * }
- * }
- * </pre>
- *
- */
-public class ModificationMetadataTreeTest {
-
- private static final Short ONE_ID = 1;
- private static final Short TWO_ID = 2;
- private static final String TWO_ONE_NAME = "one";
- private static final String TWO_TWO_NAME = "two";
-
- private static final InstanceIdentifier OUTER_LIST_1_PATH = InstanceIdentifier.builder(OUTER_LIST_PATH)
- .nodeWithKey(OUTER_LIST_QNAME, ID_QNAME, ONE_ID) //
- .build();
-
- private static final InstanceIdentifier OUTER_LIST_2_PATH = InstanceIdentifier.builder(OUTER_LIST_PATH)
- .nodeWithKey(OUTER_LIST_QNAME, ID_QNAME, TWO_ID) //
- .build();
-
- private static final InstanceIdentifier TWO_TWO_PATH = InstanceIdentifier.builder(OUTER_LIST_2_PATH)
- .node(INNER_LIST_QNAME) //
- .nodeWithKey(INNER_LIST_QNAME, NAME_QNAME, TWO_TWO_NAME) //
- .build();
-
- private static final InstanceIdentifier TWO_TWO_VALUE_PATH = InstanceIdentifier.builder(TWO_TWO_PATH)
- .node(VALUE_QNAME) //
- .build();
-
- private static final MapEntryNode BAR_NODE = mapEntryBuilder(OUTER_LIST_QNAME, ID_QNAME, TWO_ID) //
- .withChild(mapNodeBuilder(INNER_LIST_QNAME) //
- .withChild(mapEntry(INNER_LIST_QNAME, NAME_QNAME, TWO_ONE_NAME)) //
- .withChild(mapEntry(INNER_LIST_QNAME, NAME_QNAME, TWO_TWO_NAME)) //
- .build()) //
- .build();
-
- private SchemaContext schemaContext;
- private ModificationApplyOperation applyOper;
-
- @Before
- public void prepare() {
- schemaContext = TestModel.createTestContext();
- assertNotNull("Schema context must not be null.", schemaContext);
- applyOper = SchemaAwareApplyOperation.from(schemaContext);
- }
-
- /**
- * Returns a test document
- *
- * <pre>
- * test
- * outer-list
- * id 1
- * outer-list
- * id 2
- * inner-list
- * name "one"
- * inner-list
- * name "two"
- *
- * </pre>
- *
- * @return
- */
- public NormalizedNode<?, ?> createDocumentOne() {
- return ImmutableContainerNodeBuilder
- .create()
- .withNodeIdentifier(new NodeIdentifier(schemaContext.getQName()))
- .withChild(createTestContainer()).build();
-
- }
-
- private ContainerNode createTestContainer() {
- return ImmutableContainerNodeBuilder
- .create()
- .withNodeIdentifier(new NodeIdentifier(TEST_QNAME))
- .withChild(
- mapNodeBuilder(OUTER_LIST_QNAME)
- .withChild(mapEntry(OUTER_LIST_QNAME, ID_QNAME, ONE_ID))
- .withChild(BAR_NODE).build()).build();
- }
-
- @Test
- public void basicReadWrites() {
- DataTreeModification modificationTree = new InMemoryDataTreeModification(new InMemoryDataTreeSnapshot(schemaContext,
- TreeNodeFactory.createTreeNode(createDocumentOne(), Version.initial()), applyOper),
- new SchemaAwareApplyOperationRoot(schemaContext));
- Optional<NormalizedNode<?, ?>> originalBarNode = modificationTree.readNode(OUTER_LIST_2_PATH);
- assertTrue(originalBarNode.isPresent());
- assertSame(BAR_NODE, originalBarNode.get());
-
- // writes node to /outer-list/1/inner_list/two/value
- modificationTree.write(TWO_TWO_VALUE_PATH, ImmutableNodes.leafNode(VALUE_QNAME, "test"));
-
- // reads node to /outer-list/1/inner_list/two/value
- // and checks if node is already present
- Optional<NormalizedNode<?, ?>> barTwoCModified = modificationTree.readNode(TWO_TWO_VALUE_PATH);
- assertTrue(barTwoCModified.isPresent());
- assertEquals(ImmutableNodes.leafNode(VALUE_QNAME, "test"), barTwoCModified.get());
-
- // delete node to /outer-list/1/inner_list/two/value
- modificationTree.delete(TWO_TWO_VALUE_PATH);
- Optional<NormalizedNode<?, ?>> barTwoCAfterDelete = modificationTree.readNode(TWO_TWO_VALUE_PATH);
- assertFalse(barTwoCAfterDelete.isPresent());
- }
-
-
- public DataTreeModification createEmptyModificationTree() {
- /**
- * Creates empty Snapshot with associated schema context.
- */
- DataTree t = InMemoryDataTreeFactory.getInstance().create();
- t.setSchemaContext(schemaContext);
-
- /**
- *
- * Creates Mutable Data Tree based on provided snapshot and schema
- * context.
- *
- */
- return t.takeSnapshot().newModification();
- }
-
- @Test
- public void createFromEmptyState() {
-
- DataTreeModification modificationTree = createEmptyModificationTree();
- /**
- * Writes empty container node to /test
- *
- */
- modificationTree.write(TEST_PATH, ImmutableNodes.containerNode(TEST_QNAME));
-
- /**
- * Writes empty list node to /test/outer-list
- */
- modificationTree.write(OUTER_LIST_PATH, ImmutableNodes.mapNodeBuilder(OUTER_LIST_QNAME).build());
-
- /**
- * Reads list node from /test/outer-list
- */
- Optional<NormalizedNode<?, ?>> potentialOuterList = modificationTree.readNode(OUTER_LIST_PATH);
- assertTrue(potentialOuterList.isPresent());
-
- /**
- * Reads container node from /test and verifies that it contains test
- * node
- */
- Optional<NormalizedNode<?, ?>> potentialTest = modificationTree.readNode(TEST_PATH);
- ContainerNode containerTest = assertPresentAndType(potentialTest, ContainerNode.class);
-
- /**
- *
- * Gets list from returned snapshot of /test and verifies it contains
- * outer-list
- *
- */
- assertPresentAndType(containerTest.getChild(new NodeIdentifier(OUTER_LIST_QNAME)), MapNode.class);
-
- }
-
- @Test
- public void writeSubtreeReadChildren() {
- DataTreeModification modificationTree = createEmptyModificationTree();
- modificationTree.write(TEST_PATH, createTestContainer());
- Optional<NormalizedNode<?, ?>> potential = modificationTree.readNode(TWO_TWO_PATH);
- assertPresentAndType(potential, MapEntryNode.class);
- }
-
- @Test
- public void writeSubtreeDeleteChildren() {
- DataTreeModification modificationTree = createEmptyModificationTree();
- modificationTree.write(TEST_PATH, createTestContainer());
-
- // We verify data are present
- Optional<NormalizedNode<?, ?>> potentialBeforeDelete = modificationTree.readNode(TWO_TWO_PATH);
- assertPresentAndType(potentialBeforeDelete, MapEntryNode.class);
-
- modificationTree.delete(TWO_TWO_PATH);
- Optional<NormalizedNode<?, ?>> potentialAfterDelete = modificationTree.readNode(TWO_TWO_PATH);
- assertFalse(potentialAfterDelete.isPresent());
-
- }
-
- private static <T> T assertPresentAndType(final Optional<?> potential, final Class<T> type) {
- assertNotNull(potential);
- assertTrue(potential.isPresent());
- assertTrue(type.isInstance(potential.get()));
- return type.cast(potential.get());
- }
-
-}
+++ /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.dom.store.impl.tree.data;
-
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-
-public class SchemaAwareApplyOperationRoot extends DataNodeContainerModificationStrategy<ContainerSchemaNode> {
- private final SchemaContext context;
-
- public SchemaAwareApplyOperationRoot(final SchemaContext context) {
- super(context,ContainerNode.class);
- this.context = context;
- }
-
- public SchemaContext getContext() {
- return context;
- }
-
- @Override
- public String toString() {
- return "SchemaAwareApplyOperationRoot [context=" + context + "]";
- }
-
- @Override
- @SuppressWarnings("rawtypes")
- protected DataContainerNodeBuilder createBuilder(NormalizedNode<?, ?> original) {
- return ImmutableContainerNodeBuilder.create((ContainerNode) original);
- }
-}
<artifactId>sal-core-api</artifactId>
</dependency>
</dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>config</id>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <codeGenerators>
+ <generator>
+ <codeGeneratorClass>org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator</codeGeneratorClass>
+ <outputBaseDir>${jmxGeneratorPath}</outputBaseDir>
+ <additionalConfiguration>
+ <namespaceToPackage1>urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang</namespaceToPackage1>
+ </additionalConfiguration>
+ </generator>
+ <generator>
+ <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass>
+ <outputBaseDir>${salGeneratorPath}</outputBaseDir>
+ </generator>
+ </codeGenerators>
+ <inspectDependencies>true</inspectDependencies>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
<scm>
<connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
<developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
--- /dev/null
+module opendaylight-config-dom-datastore {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:config-dom-store";
+ prefix "config-dom-store-spi";
+
+ import config { prefix config; revision-date 2013-04-05; }
+
+ description
+ "DOM Service Provider Interface definition for MD-SAL config store";
+
+ revision "2014-06-17" {
+ description
+ "Initial revision";
+ }
+
+ identity config-dom-datastore {
+ base "config:service-type";
+ config:java-class "org.opendaylight.controller.sal.core.spi.data.DOMStore";
+
+ }
+
+}
\ No newline at end of file
--- /dev/null
+module opendaylight-operational-dom-datastore {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:operational-dom-store";
+ prefix "operational-dom-store-spi";
+
+ import config { prefix config; revision-date 2013-04-05; }
+
+ description
+ "DOM Service Provider Interface definition for MD-SAL operational store";
+
+ revision "2014-06-17" {
+ description
+ "Initial revision";
+ }
+
+ identity operational-dom-datastore {
+ base "config:service-type";
+ config:java-class "org.opendaylight.controller.sal.core.spi.data.DOMStore";
+
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-parent</artifactId>
+ <version>1.1-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>sal-inmemory-datastore</artifactId>
+
+ <packaging>bundle</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+
+ <!-- SAL Dependencies -->
+
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-config</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-common-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-common-util</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-core-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-core-spi</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>concepts</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>util</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-binding</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-common</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-data-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-data-impl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-parser-impl</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+
+ <!-- Test Dependencies -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <version>${slf4j.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+
+ <Export-Package>org.opendaylight.controller.md.sal.dom.store.impl.*</Export-Package>
+
+ <Import-Package>*</Import-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>org.opendaylight.controller.*</include>
+ </includes>
+ <check>false</check>
+ </configuration>
+ <executions>
+ <execution>
+ <id>pre-test</id>
+ <goals>
+ <goal>prepare-agent</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>post-test</id>
+ <goals>
+ <goal>report</goal>
+ </goals>
+ <phase>test</phase>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>config</id>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <codeGenerators>
+ <generator>
+ <codeGeneratorClass>org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator</codeGeneratorClass>
+ <outputBaseDir>${jmxGeneratorPath}</outputBaseDir>
+ <additionalConfiguration>
+ <namespaceToPackage1>urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang</namespaceToPackage1>
+ </additionalConfiguration>
+ </generator>
+ <generator>
+ <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass>
+ <outputBaseDir>${salGeneratorPath}</outputBaseDir>
+ </generator>
+ </codeGenerators>
+ <inspectDependencies>true</inspectDependencies>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+ <tag>HEAD</tag>
+ <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:Architecture:Clustering</url>
+ </scm>
+
+</project>
--- /dev/null
+package org.opendaylight.controller.config.yang.inmemory_datastore_provider;
+
+import com.google.common.util.concurrent.MoreExecutors;
+import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
+
+public class InMemoryConfigDataStoreProviderModule extends org.opendaylight.controller.config.yang.inmemory_datastore_provider.AbstractInMemoryConfigDataStoreProviderModule {
+ public InMemoryConfigDataStoreProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public InMemoryConfigDataStoreProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.controller.config.yang.inmemory_datastore_provider.InMemoryConfigDataStoreProviderModule oldModule, java.lang.AutoCloseable oldInstance) {
+ super(identifier, dependencyResolver, oldModule, oldInstance);
+ }
+
+ @Override
+ public void customValidation() {
+ // add custom validation form module attributes here.
+ }
+
+ @Override
+ public java.lang.AutoCloseable createInstance() {
+ InMemoryDOMDataStore ids = new InMemoryDOMDataStore("DOM-CFG", MoreExecutors.sameThreadExecutor());
+ getSchemaServiceDependency().registerSchemaServiceListener(ids);
+ return ids;
+ }
+
+}
--- /dev/null
+/*
+* Generated file
+*
+* Generated from: yang module name: opendaylight-inmemory-datastore-provider yang module local name: inmemory-config-datastore-provider
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Thu Jun 19 17:10:42 PDT 2014
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.inmemory_datastore_provider;
+public class InMemoryConfigDataStoreProviderModuleFactory extends org.opendaylight.controller.config.yang.inmemory_datastore_provider.AbstractInMemoryConfigDataStoreProviderModuleFactory {
+
+}
--- /dev/null
+package org.opendaylight.controller.config.yang.inmemory_datastore_provider;
+
+import com.google.common.util.concurrent.MoreExecutors;
+import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
+
+public class InMemoryOperationalDataStoreProviderModule extends org.opendaylight.controller.config.yang.inmemory_datastore_provider.AbstractInMemoryOperationalDataStoreProviderModule {
+ public InMemoryOperationalDataStoreProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public InMemoryOperationalDataStoreProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.controller.config.yang.inmemory_datastore_provider.InMemoryOperationalDataStoreProviderModule oldModule, java.lang.AutoCloseable oldInstance) {
+ super(identifier, dependencyResolver, oldModule, oldInstance);
+ }
+
+ @Override
+ public void customValidation() {
+ // add custom validation form module attributes here.
+ }
+
+ @Override
+ public java.lang.AutoCloseable createInstance() {
+ InMemoryDOMDataStore ids = new InMemoryDOMDataStore("DOM-OPER", MoreExecutors.sameThreadExecutor());
+ getSchemaServiceDependency().registerSchemaServiceListener(ids);
+ return ids;
+ }
+
+}
--- /dev/null
+/*
+* Generated file
+*
+* Generated from: yang module name: opendaylight-inmemory-datastore-provider yang module local name: inmemory-operational-datastore-provider
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Thu Jun 19 17:10:42 PDT 2014
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.inmemory_datastore_provider;
+public class InMemoryOperationalDataStoreProviderModuleFactory extends org.opendaylight.controller.config.yang.inmemory_datastore_provider.AbstractInMemoryOperationalDataStoreProviderModuleFactory {
+
+}
*/
package org.opendaylight.controller.md.sal.dom.store.impl;
-import static com.google.common.base.Preconditions.checkState;
-
-import java.util.Collections;
-import java.util.concurrent.Callable;
-import java.util.concurrent.atomic.AtomicLong;
-
-import javax.annotation.concurrent.GuardedBy;
-
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
import org.opendaylight.controller.md.sal.common.api.data.OptimisticLockFailedException;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.controller.md.sal.dom.store.impl.SnapshotBackedWriteTransaction.TransactionReadyPrototype;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.ConflictingModificationAppliedException;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTree;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidate;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeModification;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeSnapshot;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataValidationFailedException;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.ConflictingModificationAppliedException;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.InMemoryDataTreeFactory;
+import org.opendaylight.yangtools.yang.data.impl.schema.tree.InMemoryDataTreeFactory;
import org.opendaylight.controller.sal.core.spi.data.DOMStore;
import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
+import javax.annotation.concurrent.GuardedBy;
+import java.util.Collections;
+import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicLong;
+
+import static com.google.common.base.Preconditions.checkState;
/**
* In-memory DOM Data Store
*
*/
public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, SchemaContextListener,
- TransactionReadyPrototype {
+ TransactionReadyPrototype,AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(InMemoryDOMDataStore.class);
private final DataTree dataTree = InMemoryDataTreeFactory.getInstance().create();
private final ListenerTree listenerTree = ListenerTree.create();
private final AtomicLong txCounter = new AtomicLong(0);
private final ListeningExecutorService executor;
+
private final String name;
public InMemoryDOMDataStore(final String name, final ListeningExecutorService executor) {
dataTree.setSchemaContext(ctx);
}
+ @Override
+ public void close(){
+ executor.shutdownNow();
+ }
@Override
public <L extends AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>> ListenerRegistration<L> registerChangeListener(
final InstanceIdentifier path, final L listener, final DataChangeScope scope) {
@Override
public void close() {
+ executor.shutdownNow();
+
}
protected synchronized void onTransactionFailed(final SnapshotBackedWriteTransaction transaction,
*/
package org.opendaylight.controller.md.sal.dom.store.impl;
-import static org.opendaylight.controller.md.sal.dom.store.impl.DOMImmutableDataChangeEvent.builder;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.concurrent.Callable;
-
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Multimap;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
import org.opendaylight.controller.md.sal.dom.store.impl.DOMImmutableDataChangeEvent.Builder;
import org.opendaylight.controller.md.sal.dom.store.impl.DOMImmutableDataChangeEvent.SimpleEventFactory;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidate;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidateNode;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree.Node;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree.Walker;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Multimap;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.Callable;
+
+import static org.opendaylight.controller.md.sal.dom.store.impl.DOMImmutableDataChangeEvent.builder;
/**
* Resolve Data Change Events based on modifications and listeners
*
* Dispatch between merge variant and reuse variant of notification task is
* done in
- * {@link #addNotificationTask(com.google.common.collect.ImmutableList.Builder, Node, Collection)}
+ * {@link #addNotificationTask(com.google.common.collect.ImmutableList.Builder, Node, java.util.Collection)}
*
* @return Collection of notification tasks.
*/
* {@link #addNotificationTaskByScope(com.google.common.collect.ImmutableList.Builder, Node, DOMImmutableDataChangeEvent)}
* . Otherwise events are merged by scope and distributed between listeners
* to particular scope. See
- * {@link #addNotificationTasksAndMergeEvents(com.google.common.collect.ImmutableList.Builder, Node, Collection)}
+ * {@link #addNotificationTasksAndMergeEvents(com.google.common.collect.ImmutableList.Builder, Node, java.util.Collection)}
* .
*
* @param taskListBuilder
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeSnapshot;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot;
import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
*/
package org.opendaylight.controller.md.sal.dom.store.impl;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeSnapshot;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot;
import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import static com.google.common.base.Preconditions.checkState;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeModification;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeSnapshot;
+
import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import com.google.common.base.Objects.ToStringHelper;
import com.google.common.base.Preconditions;
import com.google.common.base.Throwables;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
/**
* Implementation of Write transaction which is backed by
* {@link DataTreeSnapshot} and executed according to
- * {@link TransactionReadyPrototype}.
+ * {@link org.opendaylight.controller.md.sal.dom.store.impl.SnapshotBackedWriteTransaction.TransactionReadyPrototype}.
*
*/
class SnapshotBackedWriteTransaction extends AbstractDOMStoreTransaction implements DOMStoreWriteTransaction {
/**
* Prototype implementation of
- * {@link #ready(SnapshotBackedWriteTransaction)}
+ * {@link #ready(org.opendaylight.controller.md.sal.dom.store.impl.SnapshotBackedWriteTransaction)}
*
* This class is intended to be implemented by Transaction factories
- * responsible for allocation of {@link SnapshotBackedWriteTransaction} and
+ * responsible for allocation of {@link org.opendaylight.controller.md.sal.dom.store.impl.SnapshotBackedWriteTransaction} and
* providing underlying logic for applying implementation.
*
*/
*/
package org.opendaylight.controller.md.sal.dom.store.impl.tree;
-import java.lang.ref.Reference;
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
-import javax.annotation.concurrent.GuardedBy;
-
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
import org.opendaylight.controller.md.sal.dom.store.impl.DataChangeListenerRegistration;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.StoreTreeNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
+import javax.annotation.concurrent.GuardedBy;
+import java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* A set of listeners organized as a tree by node to which they listen. This class
* allows for efficient lookup of listeners when we walk the DataTreeCandidate.
*/
-public final class ListenerTree {
+public final class ListenerTree {
private static final Logger LOG = LoggerFactory.getLogger(ListenerTree.class);
private final ReadWriteLock rwLock = new ReentrantReadWriteLock(true);
private final Node rootNode = new Node(null, null);
/**
* This is a single node within the listener tree. Note that the data returned from
* and instance of this class is guaranteed to have any relevance or consistency
- * only as long as the {@link Walker} instance through which it is reached remains
+ * only as long as the {@link org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree.Walker} instance through which it is reached remains
* unclosed.
*/
public static final class Node implements StoreTreeNode<Node>, Identifiable<PathArgument> {
--- /dev/null
+
+module opendaylight-inmemory-datastore-provider {
+
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:controller:inmemory-datastore-provider";
+ prefix "inmemory-datastore-provider";
+
+ import config { prefix config; revision-date 2013-04-05; }
+ import rpc-context { prefix rpcx; revision-date 2013-06-17; }
+ import opendaylight-config-dom-datastore {prefix config-dom-store-spi;}
+ import opendaylight-operational-dom-datastore {prefix operational-dom-store-spi;}
+ import opendaylight-md-sal-dom {prefix sal;}
+
+ description
+ "InMemory datastore provider implementation for config & operational datastore";
+
+ revision "2014-06-17" {
+ description
+ "Initial revision.";
+ }
+
+ // This is the definition of the service implementation as a module identity.
+ identity inmemory-config-datastore-provider {
+ base config:module-type;
+ config:provided-service config-dom-store-spi:config-dom-datastore;
+ config:java-name-prefix InMemoryConfigDataStoreProvider;
+ }
+
+ // This is the definition of the service implementation as a module identity.
+
+ identity inmemory-operational-datastore-provider {
+ base config:module-type;
+ config:provided-service operational-dom-store-spi:operational-dom-datastore;
+ config:java-name-prefix InMemoryOperationalDataStoreProvider;
+ }
+
+
+ // Augments the 'configuration' choice node under modules/module.
+ augment "/config:modules/config:module/config:configuration" {
+ case inmemory-config-datastore-provider {
+ when "/config:modules/config:module/config:type = 'inmemory-config-datastore-provider'";
+
+ container schema-service {
+ uses config:service-ref {
+ refine type {
+ mandatory false;
+ config:required-identity sal:schema-service;
+ }
+ }
+ }
+ }
+ }
+
+
+
+ // Augments the 'configuration' choice node under modules/module.
+ augment "/config:modules/config:module/config:configuration" {
+ case inmemory-operational-datastore-provider {
+ when "/config:modules/config:module/config:type = 'inmemory-operational-datastore-provider'";
+
+ container schema-service {
+ uses config:service-ref {
+ refine type {
+ mandatory false;
+ config:required-identity sal:schema-service;
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+package org.opendaylight.controller.md.sal.dom.store.impl;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+import java.util.concurrent.ExecutionException;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+
+public class InMemoryDataStoreTest {
+
+ private SchemaContext schemaContext;
+ private InMemoryDOMDataStore domStore;
+
+ @Before
+ public void setupStore() {
+ domStore = new InMemoryDOMDataStore("TEST", MoreExecutors.sameThreadExecutor());
+ schemaContext = TestModel.createTestContext();
+ domStore.onGlobalContextUpdated(schemaContext);
+
+ }
+
+ @Test
+ public void testTransactionIsolation() throws InterruptedException, ExecutionException {
+
+ assertNotNull(domStore);
+
+ DOMStoreReadTransaction readTx = domStore.newReadOnlyTransaction();
+ assertNotNull(readTx);
+
+ DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction();
+ assertNotNull(writeTx);
+ /**
+ *
+ * Writes /test in writeTx
+ *
+ */
+ writeTx.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
+
+ /**
+ *
+ * Reads /test from writeTx Read should return container.
+ *
+ */
+ ListenableFuture<Optional<NormalizedNode<?, ?>>> writeTxContainer = writeTx.read(TestModel.TEST_PATH);
+ assertTrue(writeTxContainer.get().isPresent());
+
+ /**
+ *
+ * Reads /test from readTx Read should return Absent.
+ *
+ */
+ ListenableFuture<Optional<NormalizedNode<?, ?>>> readTxContainer = readTx.read(TestModel.TEST_PATH);
+ assertFalse(readTxContainer.get().isPresent());
+ }
+
+ @Test
+ public void testTransactionCommit() throws InterruptedException, ExecutionException {
+
+ DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction();
+ assertNotNull(writeTx);
+ /**
+ *
+ * Writes /test in writeTx
+ *
+ */
+ writeTx.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
+
+ /**
+ *
+ * Reads /test from writeTx Read should return container.
+ *
+ */
+ ListenableFuture<Optional<NormalizedNode<?, ?>>> writeTxContainer = writeTx.read(TestModel.TEST_PATH);
+ assertTrue(writeTxContainer.get().isPresent());
+
+ DOMStoreThreePhaseCommitCohort cohort = writeTx.ready();
+
+ assertThreePhaseCommit(cohort);
+
+ Optional<NormalizedNode<?, ?>> afterCommitRead = domStore.newReadOnlyTransaction().read(TestModel.TEST_PATH)
+ .get();
+ assertTrue(afterCommitRead.isPresent());
+ }
+
+ @Test
+ public void testTransactionAbort() throws InterruptedException, ExecutionException {
+
+ DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction();
+ assertNotNull(writeTx);
+
+ assertTestContainerWrite(writeTx);
+
+ DOMStoreThreePhaseCommitCohort cohort = writeTx.ready();
+
+ assertTrue(cohort.canCommit().get().booleanValue());
+ cohort.preCommit().get();
+ cohort.abort().get();
+
+ Optional<NormalizedNode<?, ?>> afterCommitRead = domStore.newReadOnlyTransaction().read(TestModel.TEST_PATH)
+ .get();
+ assertFalse(afterCommitRead.isPresent());
+ }
+
+ @Test
+ public void testTransactionChain() throws InterruptedException, ExecutionException {
+ DOMStoreTransactionChain txChain = domStore.createTransactionChain();
+ assertNotNull(txChain);
+
+ /**
+ * We alocate new read-write transaction and write /test
+ *
+ *
+ */
+ DOMStoreReadWriteTransaction firstTx = txChain.newReadWriteTransaction();
+ assertTestContainerWrite(firstTx);
+
+ /**
+ * First transaction is marked as ready, we are able to allocate chained
+ * transactions
+ */
+ DOMStoreThreePhaseCommitCohort firstWriteTxCohort = firstTx.ready();
+
+ /**
+ * We alocate chained transaction - read transaction, note first one is
+ * still not commited to datastore.
+ */
+ DOMStoreReadTransaction secondReadTx = txChain.newReadOnlyTransaction();
+
+ /**
+ *
+ * We test if we are able to read data from tx, read should not fail
+ * since we are using chained transaction.
+ *
+ *
+ */
+ assertTestContainerExists(secondReadTx);
+
+ /**
+ *
+ * We alocate next transaction, which is still based on first one, but
+ * is read-write.
+ *
+ */
+ DOMStoreReadWriteTransaction thirdDeleteTx = txChain.newReadWriteTransaction();
+
+ /**
+ * We test existence of /test in third transaction container should
+ * still be visible from first one (which is still uncommmited).
+ *
+ *
+ */
+ assertTestContainerExists(thirdDeleteTx);
+
+ /**
+ * We delete node in third transaction
+ */
+ thirdDeleteTx.delete(TestModel.TEST_PATH);
+
+ /**
+ * third transaction is sealed.
+ */
+ DOMStoreThreePhaseCommitCohort thirdDeleteTxCohort = thirdDeleteTx.ready();
+
+ /**
+ * We commit first transaction
+ *
+ */
+ assertThreePhaseCommit(firstWriteTxCohort);
+
+ // Alocates store transacion
+ DOMStoreReadTransaction storeReadTx = domStore.newReadOnlyTransaction();
+ /**
+ * We verify transaction is commited to store, container should exists
+ * in datastore.
+ */
+ assertTestContainerExists(storeReadTx);
+ /**
+ * We commit third transaction
+ *
+ */
+ assertThreePhaseCommit(thirdDeleteTxCohort);
+ }
+
+ @Test
+ @Ignore
+ public void testTransactionConflict() throws InterruptedException, ExecutionException {
+ DOMStoreReadWriteTransaction txOne = domStore.newReadWriteTransaction();
+ DOMStoreReadWriteTransaction txTwo = domStore.newReadWriteTransaction();
+ assertTestContainerWrite(txOne);
+ assertTestContainerWrite(txTwo);
+
+ /**
+ * Commits transaction
+ */
+ assertThreePhaseCommit(txOne.ready());
+
+ /**
+ * Asserts that txTwo could not be commited
+ */
+ assertFalse(txTwo.ready().canCommit().get());
+ }
+
+ private static void assertThreePhaseCommit(final DOMStoreThreePhaseCommitCohort cohort)
+ throws InterruptedException, ExecutionException {
+ assertTrue(cohort.canCommit().get().booleanValue());
+ cohort.preCommit().get();
+ cohort.commit().get();
+ }
+
+ private static Optional<NormalizedNode<?, ?>> assertTestContainerWrite(final DOMStoreReadWriteTransaction writeTx)
+ throws InterruptedException, ExecutionException {
+ /**
+ *
+ * Writes /test in writeTx
+ *
+ */
+ writeTx.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
+
+ return assertTestContainerExists(writeTx);
+ }
+
+ /**
+ * Reads /test from readTx Read should return container.
+ */
+ private static Optional<NormalizedNode<?, ?>> assertTestContainerExists(DOMStoreReadTransaction readTx)
+ throws InterruptedException, ExecutionException {
+
+ ListenableFuture<Optional<NormalizedNode<?, ?>>> writeTxContainer = readTx.read(TestModel.TEST_PATH);
+ assertTrue(writeTxContainer.get().isPresent());
+ return writeTxContainer.get();
+ }
+
+}
--- /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.dom.store.impl;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.Set;
+
+public class TestModel {
+
+ public static final QName TEST_QNAME = QName.create("urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test", "2014-03-13",
+ "test");
+ public static final QName OUTER_LIST_QNAME = QName.create(TEST_QNAME, "outer-list");
+ public static final QName INNER_LIST_QNAME = QName.create(TEST_QNAME, "inner-list");
+ public static final QName OUTER_CHOICE_QNAME = QName.create(TEST_QNAME, "outer-choice");
+ public static final QName ID_QNAME = QName.create(TEST_QNAME, "id");
+ public static final QName NAME_QNAME = QName.create(TEST_QNAME, "name");
+ public static final QName VALUE_QNAME = QName.create(TEST_QNAME, "value");
+ private static final String DATASTORE_TEST_YANG = "/odl-datastore-test.yang";
+
+ public static final InstanceIdentifier TEST_PATH = InstanceIdentifier.of(TEST_QNAME);
+ public static final InstanceIdentifier OUTER_LIST_PATH = InstanceIdentifier.builder(TEST_PATH).node(OUTER_LIST_QNAME).build();
+ public static final QName TWO_QNAME = QName.create(TEST_QNAME, "two");
+ public static final QName THREE_QNAME = QName.create(TEST_QNAME, "three");
+
+
+ public static final InputStream getDatastoreTestInputStream() {
+ return getInputStream(DATASTORE_TEST_YANG);
+ }
+
+ private static InputStream getInputStream(final String resourceName) {
+ return TestModel.class.getResourceAsStream(DATASTORE_TEST_YANG);
+ }
+
+ public static SchemaContext createTestContext() {
+ YangParserImpl parser = new YangParserImpl();
+ Set<Module> modules = parser.parseYangModelsFromStreams(Collections.singletonList(getDatastoreTestInputStream()));
+ return parser.resolveSchemaContext(modules);
+ }
+}
--- /dev/null
+module odl-datastore-test {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test";
+ prefix "store-test";
+
+ revision "2014-03-13" {
+ description "Initial revision.";
+ }
+
+ container test {
+ list outer-list {
+ key id;
+ leaf id {
+ type uint16;
+ }
+ choice outer-choice {
+ case one {
+ leaf one {
+ type string;
+ }
+ }
+ case two-three {
+ leaf two {
+ type string;
+ }
+ leaf three {
+ type string;
+ }
+ }
+ }
+ list inner-list {
+ key name;
+ leaf name {
+ type string;
+ }
+ leaf value {
+ type string;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file