Fixed two-phase commit bug when change originated in DOM Broker 66/3066/2
authorTony Tkacik <ttkacik@cisco.com>
Mon, 25 Nov 2013 15:58:53 +0000 (16:58 +0100)
committerGerrit Code Review <gerrit@opendaylight.org>
Mon, 25 Nov 2013 17:49:58 +0000 (17:49 +0000)
  - DataServiceConnector is now tracking all opened transaction
    in order to prevent creating loop if transaction was
    already forwarded from other broker (DataServiceConnector
    is not publishing it back).
  - Added logging to TwoPhase Commit and Transaction
    forwarding
  - Fixed some warnings regarding wildcards in generics.

Change-Id: I6e3169f20ac84222ed0837735c3ddd95115db38a
Signed-off-by: Tony Tkacik <ttkacik@cisco.com>
31 files changed:
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RpcRoutingTableImpl.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RuntimeCodeGenerator.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/BindingClassListener.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/CodecMapping.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/GeneratorListener.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/InstanceIdentifierCodecImpl.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/LazyGeneratedCodecRegistry.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/RuntimeGeneratedMappingServiceImpl.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/dom/serializer/impl/TransformerGenerator.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataBrokerImpl.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataTransactionImpl.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentDataServiceConnector.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentMappingService.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/CommitHandlersTransactions.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/DataModificationTracker.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/spi/RpcRoutingContext.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/AbstractDataServiceTest.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug01Test.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug02Test.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug03Test.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/RpcRegistrationNullPointer.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/BrokerIntegrationTest.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/RegistrationListener.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataCommitHandlerRegistration.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataProvisionService.java
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/AbstractDataBroker.xtend
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerImpl.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataTransactionImpl.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointImpl.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/DataProviderServiceProxy.java

index 02da17465665e06e572639343d93b0c42c8635d4..116a8177f977ca98f864e0d7c10eea5eaf561605 100644 (file)
@@ -30,7 +30,7 @@ class RpcRoutingTableImpl<C extends BaseIdentity,S extends RpcService> implement
     }
     
     
-    override getRoute(InstanceIdentifier nodeInstance) {
+    override getRoute(InstanceIdentifier<? extends Object> nodeInstance) {
         val ret = routes.get(nodeInstance);
         if(ret !== null) {
             return ret;
@@ -44,6 +44,6 @@ class RpcRoutingTableImpl<C extends BaseIdentity,S extends RpcService> implement
     
     @SuppressWarnings("rawtypes")
     override updateRoute(InstanceIdentifier<? extends Object> path, S service) {
-        routes.put(path as InstanceIdentifier,service);
+        routes.put(path as InstanceIdentifier<? extends DataObject>,service);
     }
 }
\ No newline at end of file
index e1e66aa9b4e76a29bd9df07717cfd4da5700b053..801e4984c0401b04ce268b11fb2f5c9360f71f57 100644 (file)
@@ -11,7 +11,6 @@ import javassist.ClassPool
 import org.opendaylight.yangtools.yang.binding.RpcService
 
 import javassist.CtClass
-import static com.google.common.base.Preconditions.*
 import javassist.CtMethod
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
 import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext
@@ -65,8 +64,6 @@ class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.co
     }
 
     override <T extends RpcService> getRouterFor(Class<T> iface) {
-        val contexts = new HashSet<Class<? extends BaseIdentity>>
-
         val instance = <RpcRouterCodegenInstance<T>>withClassLoaderAndLock(iface.classLoader,lock) [ |
             val supertype = iface.asCtClass
             val metadata = supertype.rpcMetadata;
@@ -210,7 +207,7 @@ class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.co
         ]
         val finalClass = targetCls.toClass(iface.classLoader, iface.protectionDomain)
         return new RuntimeGeneratedInvokerPrototype(supportedNotification,
-            finalClass as Class<? extends org.opendaylight.controller.sal.binding.api.NotificationListener>);
+            finalClass as Class<? extends org.opendaylight.controller.sal.binding.api.NotificationListener<?>>);
     }
 
     
@@ -238,7 +235,7 @@ package class RuntimeGeneratedInvoker implements NotificationInvoker {
     val NotificationListener delegate;
 
     @Property
-    var org.opendaylight.controller.sal.binding.api.NotificationListener invocationProxy;
+    var org.opendaylight.controller.sal.binding.api.NotificationListener<Notification> invocationProxy;
 
     @Property
     var RuntimeGeneratedInvokerPrototype prototype;
@@ -246,7 +243,7 @@ package class RuntimeGeneratedInvoker implements NotificationInvoker {
     new(NotificationListener delegate, RuntimeGeneratedInvokerPrototype prototype) {
         _delegate = delegate;
         _prototype = prototype;
-        _invocationProxy = prototype.protoClass.newInstance;
+        _invocationProxy = prototype.protoClass.newInstance as org.opendaylight.controller.sal.binding.api.NotificationListener<Notification>;
         RuntimeCodeHelper.setDelegate(_invocationProxy, delegate);
     }
 
@@ -265,7 +262,7 @@ package class RuntimeGeneratedInvokerPrototype {
     val Set<Class<? extends Notification>> supportedNotifications;
 
     @Property
-    val Class<? extends org.opendaylight.controller.sal.binding.api.NotificationListener> protoClass;
+    val Class<? extends org.opendaylight.controller.sal.binding.api.NotificationListener<?>> protoClass;
 }
 
 package class RpcServiceMetadata {
index 19e99617606ff9198379f48fec1be32a052e11b5..35f48745f9fc86a9919c751419fd6254744de2d5 100644 (file)
@@ -30,8 +30,8 @@ public class CodecMapping {
         }
     }
 
-    public static void setClassToCaseMap(Class<? extends BindingCodec> codec,
-            Map<Class,BindingCodec> classToCaseRawCodec) {
+    public static void setClassToCaseMap(Class<? extends BindingCodec<?,?>> codec,
+            Map<Class<?>,BindingCodec<?,?>> classToCaseRawCodec) {
         Field instanceIdField;
         try {
             instanceIdField = codec.getField(CLASS_TO_CASE_MAP);
@@ -47,8 +47,8 @@ public class CodecMapping {
         
     }
 
-    public static void setCompositeNodeToCaseMap(Class<? extends BindingCodec> codec,
-            Map<CompositeNode,BindingCodec> compositeToCase) {
+    public static void setCompositeNodeToCaseMap(Class<? extends BindingCodec<?,?>> codec,
+            Map<CompositeNode,BindingCodec<?,?>> compositeToCase) {
         Field instanceIdField;
         try {
             instanceIdField = codec.getField(COMPOSITE_TO_CASE);
@@ -63,7 +63,7 @@ public class CodecMapping {
     }
 
     public static void setAugmentationCodec(Class<? extends BindingCodec<Map<QName, Object>, Object>> dataCodec,
-            BindingCodec augmentableCodec) {
+            BindingCodec<?,?> augmentableCodec) {
             Field instanceIdField;
             try {
                 instanceIdField = dataCodec.getField(AUGMENTATION_CODEC);
index 3f74c9eaf4bd0387e1e31157fe3c7039570a845e..0a8ea84cf60638f7290bc01ba1bfb4512d35c02c 100644 (file)
@@ -9,6 +9,8 @@ public interface GeneratorListener {
 
     
     
+    void onClassProcessed(Class<?> cl);
+    
     void onCodecCreated(Class<?> codec);
     void onValueCodecCreated(Class<?> valueClass,Class<?> valueCodec);
     void onChoiceCodecCreated(Class<?> choiceClass,Class<? extends BindingCodec<Map<QName, Object>,Object>> choiceCodec);
index c48aab73273d5dc0650d1821eefc5732b9c3e5f9..270660980643cfa6e58a1bcc5fc7aeff856fc584 100644 (file)
@@ -95,6 +95,7 @@ class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec {
         return new NodeIdentifier(QName.create(previousQname,qname.localName));
     }
     
+    @SuppressWarnings("rawtypes")
     private def dispatch PathArgument serializePathArgument(IdentifiableItem argument, QName previousQname) {
         val Map<QName,Object> predicates = new HashMap();
         val type = argument.type;
@@ -111,7 +112,7 @@ class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec {
         return new NodeIdentifierWithPredicates(QName.create(previousQname,qname.localName),predicates);
     }
     
-    def resolveQname(Class class1) {
+    def resolveQname(Class<?> class1) {
         val qname = classToQName.get(class1);
         if(qname !== null) {
             return qname;
index 758ea731dc56709d92714f0faa18bc19d4bcc7a3..b81100836f7a422cdebca5de63010e512e5d7ac0 100644 (file)
@@ -36,6 +36,7 @@ import org.opendaylight.yangtools.yang.binding.Augmentable;
 import org.opendaylight.yangtools.yang.binding.Augmentation;
 import org.opendaylight.yangtools.yang.binding.BindingCodec;
 import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.Identifier;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
@@ -120,6 +121,9 @@ public class LazyGeneratedCodecRegistry implements //
         ReferencedTypeImpl typeref = new ReferencedTypeImpl(type.getPackageName(), type.getName());
         @SuppressWarnings("rawtypes")
         WeakReference<Class> weakRef = typeToClass.get(typeref);
+        if(weakRef == null) {
+            LOG.error("Could not find loaded class for path: {} and type: {}",path,typeref.getFullyQualifiedName());
+        }
         return weakRef.get();
     }
 
@@ -147,9 +151,29 @@ public class LazyGeneratedCodecRegistry implements //
     @Override
     @SuppressWarnings("rawtypes")
     public void bindingClassEncountered(Class cls) {
+        
         ConcreteType typeRef = Types.typeForClass(cls);
+        if(typeToClass.containsKey(typeRef)) {
+            return;
+        }
+        LOG.info("Binding Class {} encountered.",cls);
         WeakReference<Class> weakRef = new WeakReference<>(cls);
         typeToClass.put(typeRef, weakRef);
+        if(DataObject.class.isAssignableFrom(cls)) {
+            @SuppressWarnings({"unchecked","unused"})
+            Object cdc = getCodecForDataObject((Class<? extends DataObject>) cls);
+        }
+    }
+    
+    @Override
+    public void onClassProcessed(Class<?> cls) {
+        ConcreteType typeRef = Types.typeForClass(cls);
+        if(typeToClass.containsKey(typeRef)) {
+            return;
+        }
+        LOG.info("Binding Class {} encountered.",cls);
+        WeakReference<Class> weakRef = new WeakReference<>((Class) cls);
+        typeToClass.put(typeRef, weakRef);
     }
 
     private DataSchemaNode getSchemaNode(List<QName> path) {
@@ -280,11 +304,12 @@ public class LazyGeneratedCodecRegistry implements //
             ReferencedTypeImpl typeref = new ReferencedTypeImpl(caseNode.getValue().getPackageName(), caseNode
                     .getValue().getName());
             ChoiceCaseNode node = (ChoiceCaseNode) SchemaContextUtil.findDataSchemaNode(module, caseNode.getKey());
-            if(node == null) {
-                LOG.error("YANGTools Bug: SchemaNode for {}, with path {} was not found in context.",typeref.getFullyQualifiedName(), caseNode.getKey());
+            if (node == null) {
+                LOG.error("YANGTools Bug: SchemaNode for {}, with path {} was not found in context.",
+                        typeref.getFullyQualifiedName(), caseNode.getKey());
                 continue;
             }
-            
+
             @SuppressWarnings("rawtypes")
             ChoiceCaseCodecImpl value = new ChoiceCaseCodecImpl(node);
             typeToCaseNodes.putIfAbsent(typeref, value);
@@ -305,7 +330,7 @@ public class LazyGeneratedCodecRegistry implements //
         BindingCodec<Map<QName, Object>, Object> delegate = newInstanceOf(choiceCodec);
         ChoiceCodecImpl<?> newCodec = new ChoiceCodecImpl(delegate);
         choiceCodecs.put(choiceClass, newCodec);
-        CodecMapping.setClassToCaseMap(choiceCodec, (Map<Class, BindingCodec>) classToCaseRawCodec);
+        CodecMapping.setClassToCaseMap(choiceCodec, (Map<Class<?>, BindingCodec<?, ?>>) classToCaseRawCodec);
         CodecMapping.setCompositeNodeToCaseMap(choiceCodec, newCodec.getCompositeToCase());
 
     }
@@ -545,7 +570,7 @@ public class LazyGeneratedCodecRegistry implements //
         public BindingCodec get(Object key) {
             if (key instanceof Class) {
                 Class cls = (Class) key;
-                bindingClassEncountered(cls);
+                //bindingClassEncountered(cls);
                 ChoiceCaseCodecImpl caseCodec = getCaseCodecFor(cls);
                 return caseCodec.getDelegate();
             }
@@ -562,11 +587,6 @@ public class LazyGeneratedCodecRegistry implements //
             this.choiceCases = choiceCases;
         }
 
-        @Override
-        public Set<java.util.Map.Entry<CompositeNode, BindingCodec>> entrySet() {
-            return null;
-        }
-
         @Override
         public BindingCodec get(Object key) {
             if (false == (key instanceof CompositeNode)) {
@@ -580,6 +600,8 @@ public class LazyGeneratedCodecRegistry implements //
             }
             return null;
         }
+        
+        
     }
 
     /**
@@ -590,7 +612,7 @@ public class LazyGeneratedCodecRegistry implements //
      *            Key type
      */
     @SuppressWarnings("rawtypes")
-    private static abstract class MapFacadeBase<T> implements Map<T, BindingCodec> {
+    private static abstract class MapFacadeBase<T> implements Map<T, BindingCodec<?, ?>> {
 
         @Override
         public boolean containsKey(Object key) {
@@ -618,7 +640,7 @@ public class LazyGeneratedCodecRegistry implements //
         }
 
         @Override
-        public Collection<BindingCodec> values() {
+        public Collection<BindingCodec<?, ?>> values() {
             return null;
         }
 
@@ -627,12 +649,12 @@ public class LazyGeneratedCodecRegistry implements //
         }
 
         @Override
-        public BindingCodec<Map<QName, Object>, Object> put(T key, BindingCodec value) {
+        public BindingCodec<Map<QName, Object>, Object> put(T key, BindingCodec<?,?> value) {
             throw notModifiable();
         }
 
         @Override
-        public void putAll(Map<? extends T, ? extends BindingCodec> m) {
+        public void putAll(Map<? extends T, ? extends BindingCodec<?, ?>> m) {
             throw notModifiable();
         }
 
@@ -652,7 +674,8 @@ public class LazyGeneratedCodecRegistry implements //
         }
 
         @Override
-        public Set<java.util.Map.Entry<T, BindingCodec>> entrySet() {
+        public Set<java.util.Map.Entry<T, BindingCodec<?, ?>>> entrySet() {
+            // TODO Auto-generated method stub
             return null;
         }
 
index 5b567b10272bd8054f29dfc10b99f12afc40f664..0ddc2c88c8bd5bc99c85260bb13f7ce1c86f592b 100644 (file)
@@ -17,18 +17,9 @@ import java.util.Map.Entry
 import java.util.AbstractMap.SimpleEntry
 import org.opendaylight.yangtools.yang.model.api.SchemaPath
 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil
-import java.util.ArrayList
-import org.opendaylight.yangtools.yang.common.QName
 import org.opendaylight.yangtools.yang.binding.DataContainer
-import static com.google.common.base.Preconditions.*;
-import java.util.List
-import org.opendaylight.yangtools.yang.data.api.Node
-import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
-import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
-import org.opendaylight.yangtools.concepts.Delegator
 import java.util.concurrent.ConcurrentMap
 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
-import org.opendaylight.yangtools.yang.binding.BindingCodec
 import com.google.common.collect.HashMultimap
 import com.google.common.util.concurrent.SettableFuture
 import java.util.concurrent.Future
@@ -144,6 +135,10 @@ class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingSer
         val ret = transformer.deserialize(node)?.value as DataObject;
         return ret;
     }
+    
+    override fromDataDom(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry) {
+        return registry.instanceIdentifierCodec.deserialize(entry);
+    }
 
     private def void updateBindingFor(Map<SchemaPath, GeneratedTypeBuilder> map, SchemaContext module) {
         for (entry : map.entrySet) {
index 96c3872ed0290c55dfb8a3a12bf77eda9783f13d..01390d7c41612e819b3cffc9964538f66263bf38 100644 (file)
@@ -95,6 +95,7 @@ class TransformerGenerator {
         return withClassLoaderAndLock(inputType.classLoader, lock) [ |
             val ret = getGeneratedClass(inputType)
             if (ret !== null) {
+                listener.onClassProcessed(inputType);
                 return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
             }
             val ref = Types.typeForClass(inputType)
@@ -102,6 +103,7 @@ class TransformerGenerator {
             val typeSpecBuilder = typeToDefinition.get(ref)
             val typeSpec = typeSpecBuilder.toInstance();
             val newret = generateTransformerFor(inputType, typeSpec, node);
+            listener.onClassProcessed(inputType);
             return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
         ]
     }
@@ -117,6 +119,7 @@ class TransformerGenerator {
             val typeSpecBuilder = typeToDefinition.get(ref)
             val typeSpec = typeSpecBuilder.toInstance();
             val newret = generateAugmentationTransformerFor(inputType, typeSpec, node);
+            listener.onClassProcessed(inputType);
             return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
         ]
     }
@@ -184,7 +187,7 @@ class TransformerGenerator {
         ]
     }
 
-    private def Class getGeneratedClass(Class<? extends Object> cls) {
+    private def Class<?> getGeneratedClass(Class<? extends Object> cls) {
 
         try {
             return loadClassWithTCCL(cls.codecClassName)
@@ -219,7 +222,7 @@ class TransformerGenerator {
 
     private def generateKeyTransformerFor(Class<? extends Object> inputType, GeneratedType typeSpec, ListSchemaNode node) {
         try {
-            log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
+            //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
             val properties = typeSpec.allProperties;
             val ctCls = createClass(inputType.codecClassName) [
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
@@ -293,10 +296,10 @@ class TransformerGenerator {
         }
     }
 
-    private def Class<? extends BindingCodec<Object, Object>> generateCaseCodec(Class inputType, GeneratedType type,
+    private def Class<? extends BindingCodec<Object, Object>> generateCaseCodec(Class<?> inputType, GeneratedType type,
         ChoiceCaseNode node) {
         try {
-            log.info("Generating DOM Codec for {} with {}, TCCL is: {}", inputType, inputType.classLoader,Thread.currentThread.contextClassLoader)
+            //log.info("Generating DOM Codec for {} with {}, TCCL is: {}", inputType, inputType.classLoader,Thread.currentThread.contextClassLoader)
             val ctCls = createClass(type.codecClassName) [
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
                 implementsType(BINDING_CODEC)
@@ -310,7 +313,7 @@ class TransformerGenerator {
                             Â«QName.name» _resultName = Â«QName.name».create($1,QNAME.getLocalName());
                             java.util.List _childNodes = new java.util.ArrayList();
                             Â«type.resolvedName» value = («type.resolvedName») $2;
-                            Â«transformDataContainerBody(type.allProperties, node)»
+                            Â«transformDataContainerBody(type,type.allProperties, node)»
                             return ($r) _childNodes;
                         }
                     '''
@@ -351,9 +354,9 @@ class TransformerGenerator {
     }
 
     private def dispatch  Class<? extends BindingCodec<Map<QName, Object>, Object>> generateTransformerFor(
-        Class inputType, GeneratedType typeSpec, SchemaNode node) {
+        Class<?> inputType, GeneratedType typeSpec, SchemaNode node) {
         try {
-            log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
+            //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
             val ctCls = createClass(typeSpec.codecClassName) [
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
                 staticQNameField(inputType);
@@ -398,9 +401,9 @@ class TransformerGenerator {
     }
 
     private def Class<? extends BindingCodec<Map<QName, Object>, Object>> generateAugmentationTransformerFor(
-        Class inputType, GeneratedType type, AugmentationSchema node) {
+        Class<?> inputType, GeneratedType type, AugmentationSchema node) {
         try {
-            log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
+            //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
             val properties = type.allProperties
             val ctCls = createClass(type.codecClassName) [
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
@@ -448,7 +451,7 @@ class TransformerGenerator {
                             return null;
                             }
                             java.util.Map _compositeNode = (java.util.Map) $2;
-                            ////System.out.println(_localQName + " " + _compositeNode);
+                            //System.out.println(_localQName + " " + _compositeNode);
                             Â«type.builderName» _builder = new Â«type.builderName»();
                             Â«FOR child : node.childNodes»
                                 Â«val signature = properties.getFor(child)»
@@ -477,9 +480,9 @@ class TransformerGenerator {
     }
 
     private def dispatch  Class<? extends BindingCodec<Map<QName, Object>, Object>> generateTransformerFor(
-        Class inputType, GeneratedType typeSpec, ChoiceNode node) {
+        Class<?> inputType, GeneratedType typeSpec, ChoiceNode node) {
         try {
-            log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
+            //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
             val ctCls = createClass(typeSpec.codecClassName) [
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
                 //staticQNameField(inputType);
@@ -502,7 +505,9 @@ class TransformerGenerator {
                                 return null;
                             }
                             java.util.Map.Entry _input = new Â«SimpleEntry.name»($1,_baValue);
-                            return (java.util.List) _codec.serialize(_input);
+                            Object _ret =  _codec.serialize(_input);
+                            //System.out.println("«typeSpec.name»#toDomStatic: " + _ret);
+                            return («List.name») _ret;
                         }
                     '''
                 ]
@@ -619,7 +624,7 @@ class TransformerGenerator {
                 return null;
             }
             java.util.Map _compositeNode = (java.util.Map) $2;
-            ////System.out.println(_localQName + " " + _compositeNode);
+            //System.out.println(_localQName + " " + _compositeNode);
             Â«type.builderName» _builder = new Â«type.builderName»();
             Â«deserializeDataNodeContainerBody(type, node)»
             Â«deserializeAugmentations»
@@ -662,7 +667,7 @@ class TransformerGenerator {
         String propertyName) '''
         java.util.List _dom_«propertyName» = _compositeNode.get(«QName.name».create(_localQName,"«schema.QName.
             localName»"));
-        ////System.out.println("«propertyName»#deCode"+_dom_«propertyName»);
+        //System.out.println("«propertyName»#deCode"+_dom_«propertyName»);
         java.util.List Â«propertyName» = new java.util.ArrayList();
         if(_dom_«propertyName» != null) {
             java.util.List _serialized = new java.util.ArrayList();
@@ -670,15 +675,15 @@ class TransformerGenerator {
             boolean _hasNext = _iterator.hasNext();
             while(_hasNext) {
                 Object _listItem = _iterator.next();
-                ////System.out.println("  item" + _listItem);
+                //System.out.println("  item" + _listItem);
                 Object _value = Â«type.actualTypeArguments.get(0).serializer.resolvedName».fromDomStatic(_localQName,_listItem);
-                ////System.out.println("  value" + _value);
+                //System.out.println("  value" + _value);
                 Â«propertyName».add(_value);
                 _hasNext = _iterator.hasNext();
             }
         }
         
-        ////System.out.println(" list" + Â«propertyName»);
+        //System.out.println(" list" + Â«propertyName»);
     '''
 
     private def dispatch CharSequence deserializeProperty(LeafListSchemaNode schema, ParameterizedType type,
@@ -746,7 +751,7 @@ class TransformerGenerator {
             var hasBinding = false;
             try {
                 val bindingCodecClass = loadClassWithTCCL(BINDING_CODEC.name);
-                hasBinding = true;
+                hasBinding = bindingCodecClass !== null;
             } catch (ClassNotFoundException e) {
                 hasBinding = false;
             }
@@ -762,15 +767,15 @@ class TransformerGenerator {
                     modifiers = PUBLIC + FINAL + STATIC
                     body = '''
                         {
-                            ////System.out.println("«inputType.simpleName»#toDomValue: "+$1);
+                            //System.out.println("«inputType.simpleName»#toDomValue: "+$1);
                             
                             if($1 == null) {
                                 return null;
                             }
                             Â«typeSpec.resolvedName» _encapsulatedValue = («typeSpec.resolvedName») $1;
-                            ////System.out.println("«inputType.simpleName»#toDomValue:Enc: "+_encapsulatedValue);
+                            //System.out.println("«inputType.simpleName»#toDomValue:Enc: "+_encapsulatedValue);
                             Â«returnType.resolvedName» _value =  _encapsulatedValue.getValue();
-                            ////System.out.println("«inputType.simpleName»#toDomValue:DeEnc: "+_value);
+                            //System.out.println("«inputType.simpleName»#toDomValue:DeEnc: "+_value);
                             Object _domValue = Â«serializeValue(returnType, "_value")»;
                             return _domValue;
                         }
@@ -787,7 +792,7 @@ class TransformerGenerator {
                     modifiers = PUBLIC + FINAL + STATIC
                     body = '''
                         {
-                            ////System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
+                            //System.out.println("«inputType.simpleName»#fromDomValue: "+$1);
                             
                             if($1 == null) {
                                 return null;
@@ -863,7 +868,7 @@ class TransformerGenerator {
     private def dispatch Class<?> generateValueTransformer(
         Class<?> inputType, Enumeration typeSpec) {
         try {
-            log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
+            //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader)
             val ctCls = createClass(typeSpec.codecClassName) [
                 //staticField(Map,"AUGMENTATION_SERIALIZERS");
                 //implementsType(BINDING_CODEC)
@@ -994,7 +999,7 @@ class TransformerGenerator {
             Â«QName.name» _resultName = Â«QName.name».create($1,QNAME.getLocalName());
             java.util.List _childNodes = new java.util.ArrayList();
             Â«type.resolvedName» value = («type.resolvedName») $2;
-            Â«transformDataContainerBody(type.allProperties, node)»
+            Â«transformDataContainerBody(type,type.allProperties, node)»
             Â«serializeAugmentations»
             return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
         }
@@ -1005,7 +1010,7 @@ class TransformerGenerator {
             Â«QName.name» _resultName = Â«QName.name».create($1,QNAME.getLocalName());
             java.util.List _childNodes = new java.util.ArrayList();
             Â«type.resolvedName» value = («type.resolvedName») $2;
-            Â«transformDataContainerBody(type.allProperties, node)»
+            Â«transformDataContainerBody(type,type.allProperties, node)»
             Â«serializeAugmentations»
             return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
         }
@@ -1016,7 +1021,7 @@ class TransformerGenerator {
         Â«QName.name» _resultName = Â«QName.name».create($1,QNAME.getLocalName());
             java.util.List _childNodes = new java.util.ArrayList();
             Â«type.resolvedName» value = («type.resolvedName») $2;
-            Â«transformDataContainerBody(type.allProperties, node)»
+            Â«transformDataContainerBody(type,type.allProperties, node)»
             Â«serializeAugmentations»
             return ($r) java.util.Collections.singletonMap(_resultName,_childNodes);
         }
@@ -1031,11 +1036,11 @@ class TransformerGenerator {
         }
     '''
 
-    private def transformDataContainerBody(Map<String, Type> properties, DataNodeContainer node) {
+    private def transformDataContainerBody(Type type,Map<String, Type> properties, DataNodeContainer node) {
         val ret = '''
             Â«FOR child : node.childNodes.filter[!augmenting]»
                 Â«var signature = properties.getFor(child)»
-                //System.out.println("«signature.key»" + value.«signature.key»());
+                //System.out.println("«type.name»#«signature.key»" + value.«signature.key»());
                 Â«serializeProperty(child, signature.value, signature.key)»
             Â«ENDFOR»
         '''
@@ -1164,11 +1169,11 @@ class TransformerGenerator {
         return '''«typeSpec.resolvedName»$Broker$Codec$DOM'''
     }
 
-    private def codecClassName(Class typeSpec) {
+    private def codecClassName(Class<?> typeSpec) {
         return '''«typeSpec.name»$Broker$Codec$DOM'''
     }
 
-    private def dispatch HashMap<String, Type> getAllProperties(GeneratedType type) {
+    private def HashMap<String, Type> getAllProperties(GeneratedType type) {
         val ret = new HashMap<String, Type>();
         type.collectAllProperties(ret);
         return ret;
@@ -1198,12 +1203,11 @@ class TransformerGenerator {
         return type.asCtClass.name;
     }
 
-    def String getResolvedName(Class type) {
+    def String getResolvedName(Class<?> type) {
         return type.asCtClass.name;
     }
 
     def CtClass asCtClass(Type type) {
-        val name = type.fullyQualifiedName
         val cls = loadClassWithTCCL(type.fullyQualifiedName)
         return cls.asCtClass;
     }
index b08c72aa4cc36122c5b700c8d8a7fbfefa89e7dd..2f4510d5b4f035e98e9351bcba8775a126f1f8a1 100644 (file)
@@ -2,6 +2,7 @@ package org.opendaylight.controller.sal.binding.impl;
 
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Future;
+import java.util.concurrent.atomic.AtomicLong;
 
 import org.opendaylight.controller.md.sal.common.api.data.DataReader;
 import org.opendaylight.controller.md.sal.common.impl.service.AbstractDataBroker;
@@ -19,13 +20,18 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
 public class DataBrokerImpl extends AbstractDataBroker<InstanceIdentifier<? extends DataObject>, DataObject, DataChangeListener> implements
         DataProviderService, AutoCloseable {
 
+    
+    
+    private final AtomicLong nextTransaction = new AtomicLong();
+    
     public DataBrokerImpl() {
         setDataReadRouter(new BindingAwareDataReaderRouter());
     }
 
     @Override
     public DataTransactionImpl beginTransaction() {
-        return new DataTransactionImpl(this);
+        String transactionId = "BA-" + nextTransaction.getAndIncrement();
+        return new DataTransactionImpl(transactionId,this);
     }
 
     @Override
index f7967beaae6471a482885535e02d2aae26a06536..b0eb9eeb42a9fedae6286082ccf4ae127aec25a2 100644 (file)
@@ -15,8 +15,8 @@ public class DataTransactionImpl extends AbstractDataTransaction<InstanceIdentif
     
     
     
-    public DataTransactionImpl(DataBrokerImpl dataBroker) {
-        super(dataBroker);
+    public DataTransactionImpl(Object identifier,DataBrokerImpl dataBroker) {
+        super(identifier,dataBroker);
     }
 
     @Override
index 10fcbae28a8dbc6d08e4308f0fa963b13661a072..ccd6079cc997b00b9de8a2a6f5ee935155f01340 100644 (file)
@@ -2,43 +2,61 @@ package org.opendaylight.controller.sal.binding.impl.connect.dom;
 
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Map;
 import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 
-import org.opendaylight.controller.config.api.jmx.CommitStatus;
+import org.opendaylight.controller.md.sal.common.api.RegistrationListener;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
-import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-import org.opendaylight.controller.md.sal.common.api.data.DataReader;
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandlerRegistration;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
 import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider;
 import org.opendaylight.controller.sal.common.util.Rpcs;
 import org.opendaylight.controller.sal.core.api.Provider;
 import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
-import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
 import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
+import org.opendaylight.yangtools.concepts.Registration;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-
-import com.google.common.base.Preconditions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class BindingIndependentDataServiceConnector implements //
         RuntimeDataProvider, //
-        DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>, Provider {
+        Provider {
+
+    private final Logger LOG = LoggerFactory.getLogger(BindingIndependentDataServiceConnector.class);
 
     private static final InstanceIdentifier<? extends DataObject> ROOT = InstanceIdentifier.builder().toInstance();
 
+    private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier ROOT_BI = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+            .builder().toInstance();
+
     private BindingIndependentMappingService mappingService;
 
-    private DataBrokerService biDataService;
+    private org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService;
 
     private DataProviderService baDataService;
 
+    private ConcurrentMap<Object, BindingToDomTransaction> domOpenedTransactions = new ConcurrentHashMap<>();
+    private ConcurrentMap<Object, DomToBindingTransaction> bindingOpenedTransactions = new ConcurrentHashMap<>();
+
+    private BindingToDomCommitHandler bindingToDomCommitHandler = new BindingToDomCommitHandler();
+    private DomToBindingCommitHandler domToBindingCommitHandler = new DomToBindingCommitHandler();
+
+    private Registration<DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>> baCommitHandlerRegistration;
+
+    private Registration<DataCommitHandler<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode>> biCommitHandlerRegistration;
+
     @Override
     public DataObject readOperationalData(InstanceIdentifier<? extends DataObject> path) {
         org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path);
@@ -53,15 +71,7 @@ public class BindingIndependentDataServiceConnector implements //
         return mappingService.dataObjectFromDataDom(path, result);
     }
 
-    @Override
-    public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> requestCommit(
-            DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
-
-        DataModificationTransaction translated = translateTransaction(modification);
-        return new WrappedTransaction(translated, modification);
-    }
-
-    private DataModificationTransaction translateTransaction(
+    private DataModificationTransaction createBindingToDomTransaction(
             DataModification<InstanceIdentifier<? extends DataObject>, DataObject> source) {
         DataModificationTransaction target = biDataService.beginTransaction();
         for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : source.getUpdatedConfigurationData()
@@ -76,27 +86,133 @@ public class BindingIndependentDataServiceConnector implements //
                     .toDataDom(entry);
             target.putOperationalData(biEntry.getKey(), biEntry.getValue());
         }
-        for(InstanceIdentifier<? extends DataObject> entry : source.getRemovedConfigurationData()) {
+        for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedConfigurationData()) {
             org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
             target.removeConfigurationData(biEntry);
         }
-        for(InstanceIdentifier<? extends DataObject> entry : source.getRemovedOperationalData()) {
+        for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedOperationalData()) {
             org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
             target.removeOperationalData(biEntry);
         }
         return target;
     }
 
-    private class WrappedTransaction implements
+    private org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction createDomToBindingTransaction(
+            DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> source) {
+        org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction target = baDataService
+                .beginTransaction();
+        for (Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> entry : source
+                .getUpdatedConfigurationData().entrySet()) {
+            InstanceIdentifier<?> baKey = mappingService.fromDataDom(entry.getKey());
+            DataObject baData = mappingService.dataObjectFromDataDom(baKey, entry.getValue());
+            target.putConfigurationData(baKey, baData);
+        }
+        for (Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> entry : source
+                .getUpdatedOperationalData().entrySet()) {
+            InstanceIdentifier<?> baKey = mappingService.fromDataDom(entry.getKey());
+            DataObject baData = mappingService.dataObjectFromDataDom(baKey, entry.getValue());
+            target.putOperationalData(baKey, baData);
+        }
+        for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedConfigurationData()) {
+            InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
+            target.removeConfigurationData(baEntry);
+        }
+        for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedOperationalData()) {
+            InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
+            target.removeOperationalData(baEntry);
+        }
+        return target;
+    }
+
+    public org.opendaylight.controller.sal.core.api.data.DataProviderService getBiDataService() {
+        return biDataService;
+    }
+
+    public void setBiDataService(org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService) {
+        this.biDataService = biDataService;
+    }
+
+    public DataProviderService getBaDataService() {
+        return baDataService;
+    }
+
+    public void setBaDataService(DataProviderService baDataService) {
+        this.baDataService = baDataService;
+    }
+
+    public void start() {
+        baDataService.registerDataReader(ROOT, this);
+        baCommitHandlerRegistration = baDataService.registerCommitHandler(ROOT, bindingToDomCommitHandler);
+        biCommitHandlerRegistration = biDataService.registerCommitHandler(ROOT_BI, domToBindingCommitHandler);
+        baDataService.registerCommitHandlerListener(domToBindingCommitHandler);
+    }
+
+    public void setMappingService(BindingIndependentMappingService mappingService) {
+        this.mappingService = mappingService;
+    }
+
+    @Override
+    public Collection<ProviderFunctionality> getProviderFunctionality() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public void onSessionInitiated(ProviderSession session) {
+        setBiDataService(session.getService(org.opendaylight.controller.sal.core.api.data.DataProviderService.class));
+        start();
+    }
+
+    private class DomToBindingTransaction implements
+            DataCommitTransaction<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> {
+
+        private final org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction backing;
+        private final DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> modification;
+
+        public DomToBindingTransaction(
+                org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction backing,
+                DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> modification) {
+            super();
+            this.backing = backing;
+            this.modification = modification;
+            bindingOpenedTransactions.put(backing.getIdentifier(), this);
+        }
+
+        @Override
+        public DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getModification() {
+            return modification;
+        }
+
+        @Override
+        public RpcResult<Void> rollback() throws IllegalStateException {
+            // backing.cancel();
+            return Rpcs.<Void> getRpcResult(true, null, Collections.<RpcError> emptySet());
+        }
+
+        @Override
+        public RpcResult<Void> finish() throws IllegalStateException {
+            Future<RpcResult<TransactionStatus>> result = backing.commit();
+            try {
+                RpcResult<TransactionStatus> baResult = result.get();
+                return Rpcs.<Void> getRpcResult(baResult.isSuccessful(), null, baResult.getErrors());
+            } catch (InterruptedException e) {
+                throw new IllegalStateException("", e);
+            } catch (ExecutionException e) {
+                throw new IllegalStateException("", e);
+            }
+        }
+    }
+
+    private class BindingToDomTransaction implements
             DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> {
 
         private DataModificationTransaction backing;
         private DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification;
 
-        public WrappedTransaction(DataModificationTransaction backing,
+        public BindingToDomTransaction(DataModificationTransaction backing,
                 DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
             this.backing = backing;
             this.modification = modification;
+            domOpenedTransactions.put(backing.getIdentifier(), this);
         }
 
         @Override
@@ -108,57 +224,84 @@ public class BindingIndependentDataServiceConnector implements //
         public RpcResult<Void> finish() throws IllegalStateException {
             Future<RpcResult<TransactionStatus>> result = backing.commit();
             try {
-                RpcResult<TransactionStatus> biresult = result.get();
+                RpcResult<TransactionStatus> biResult = result.get();
+                return Rpcs.<Void> getRpcResult(biResult.isSuccessful(), null, biResult.getErrors());
             } catch (InterruptedException e) {
                 throw new IllegalStateException("", e);
             } catch (ExecutionException e) {
                 throw new IllegalStateException("", e);
+            } finally {
+                domOpenedTransactions.remove(backing.getIdentifier());
             }
-            return Rpcs.<Void> getRpcResult(true, null, Collections.<RpcError> emptySet());
         }
 
         @Override
         public RpcResult<Void> rollback() throws IllegalStateException {
-            // backing.cancel();
+            domOpenedTransactions.remove(backing.getIdentifier());
             return Rpcs.<Void> getRpcResult(true, null, Collections.<RpcError> emptySet());
         }
-
     }
 
-    public DataBrokerService getBiDataService() {
-        return biDataService;
-    }
+    private class BindingToDomCommitHandler implements
+            DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
 
-    public void setBiDataService(DataBrokerService biDataService) {
-        this.biDataService = biDataService;
-    }
+        @Override
+        public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> requestCommit(
+                DataModification<InstanceIdentifier<? extends DataObject>, DataObject> bindingTransaction) {
 
-    public DataProviderService getBaDataService() {
-        return baDataService;
-    }
+            /**
+             * Transaction was created as DOM transaction, in that case we do
+             * not need to forward it back.
+             */
+            if (bindingOpenedTransactions.containsKey(bindingTransaction.getIdentifier())) {
 
-    public void setBaDataService(DataProviderService baDataService) {
-        this.baDataService = baDataService;
+                return CommitHandlersTransactions.allwaysSuccessfulTransaction(bindingTransaction);
+            }
+            DataModificationTransaction domTransaction = createBindingToDomTransaction(bindingTransaction);
+            BindingToDomTransaction wrapped = new BindingToDomTransaction(domTransaction, bindingTransaction);
+            LOG.info("Forwarding Binding Transaction: {} as DOM Transaction: {} .", bindingTransaction.getIdentifier(),
+                    domTransaction.getIdentifier());
+            return wrapped;
+        }
     }
 
-    public void start() {
-        baDataService.registerDataReader(ROOT, this);
-        baDataService.registerCommitHandler(ROOT, this);
-    }
+    private class DomToBindingCommitHandler implements //
+            RegistrationListener<DataCommitHandlerRegistration<InstanceIdentifier<?>, DataObject>>, //
+            DataCommitHandler<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> {
 
-    public void setMappingService(BindingIndependentMappingService mappingService) {
-        this.mappingService = mappingService;
-    }
-    
-    @Override
-    public Collection<ProviderFunctionality> getProviderFunctionality() {
-        return Collections.emptyList();
-    }
-    
-    @Override
-    public void onSessionInitiated(ProviderSession session) {
-        setBiDataService(session.getService(org.opendaylight.controller.sal.core.api.data.DataProviderService.class));
-        start();
-    }
+        @Override
+        public void onRegister(DataCommitHandlerRegistration<InstanceIdentifier<?>, DataObject> registration) {
+            
+            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier domPath = mappingService.toDataDom(registration.getPath());
+            // FIXME: do registration based on only active commit handlers.
+            
+        }
 
+        @Override
+        public void onUnregister(DataCommitHandlerRegistration<InstanceIdentifier<?>, DataObject> registration) {
+            // NOOP for now
+            // FIXME: do registration based on only active commit handlers.
+        }
+
+        public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> requestCommit(
+                DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> domTransaction) {
+            Object identifier = domTransaction.getIdentifier();
+
+            /**
+             * We checks if the transcation was originated in this mapper. If it
+             * was originated in this mapper we are returing allways success
+             * commit hanlder to prevent creating loop in two-phase commit and
+             * duplicating data.
+             */
+            if (domOpenedTransactions.containsKey(identifier)) {
+                return CommitHandlersTransactions.allwaysSuccessfulTransaction(domTransaction);
+            }
+
+            org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction baTransaction = createDomToBindingTransaction(domTransaction);
+            DomToBindingTransaction forwardedTransaction = new DomToBindingTransaction(baTransaction, domTransaction);
+            LOG.info("Forwarding DOM Transaction: {} as Binding Transaction: {}.", domTransaction.getIdentifier(),
+                    baTransaction.getIdentifier());
+            return forwardedTransaction;
+        }
+    }
 }
index d96f175c562bb1cada57399db365b25f3a865600..9e175b8cb0e0f6c5e79550218986e0f552ae3edd 100644 (file)
@@ -18,4 +18,6 @@ public interface BindingIndependentMappingService {
 
     DataObject dataObjectFromDataDom(InstanceIdentifier<? extends DataObject> path, CompositeNode result);
 
+    InstanceIdentifier<?> fromDataDom(org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry);
+
 }
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/CommitHandlersTransactions.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/CommitHandlersTransactions.java
new file mode 100644 (file)
index 0000000..ea48374
--- /dev/null
@@ -0,0 +1,40 @@
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+import java.util.Collections;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
+import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.yangtools.concepts.Path;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+public class CommitHandlersTransactions {
+
+    private static class AllwaysSuccessfulTransaction<P,D> implements DataCommitTransaction<P, D> {
+        
+        private final  DataModification<P, D> modification;
+
+        public AllwaysSuccessfulTransaction(DataModification<P, D> modification) {
+            this.modification = modification;
+        }
+        @Override
+        public RpcResult<Void> rollback() throws IllegalStateException {
+            return Rpcs.<Void>getRpcResult(true, null, Collections.<RpcError>emptyList());
+        }
+        @Override
+        public RpcResult<Void> finish() throws IllegalStateException {
+            return Rpcs.<Void>getRpcResult(true, null, Collections.<RpcError>emptyList());
+        }
+        
+        @Override
+        public DataModification<P, D> getModification() {
+            return modification;
+        }
+    }
+    
+    
+    public static final <P extends Path<P>,D> AllwaysSuccessfulTransaction<P, D> allwaysSuccessfulTransaction(DataModification<P, D> modification)  {
+        return new AllwaysSuccessfulTransaction<>(modification);
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/DataModificationTracker.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/DataModificationTracker.java
new file mode 100644 (file)
index 0000000..3fc377f
--- /dev/null
@@ -0,0 +1,25 @@
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.yangtools.concepts.Path;
+
+import com.google.common.util.concurrent.JdkFutureAdapters;
+
+public final class DataModificationTracker<P extends Path<P>,D> {
+
+    ConcurrentMap<Object, DataModification<P,D>> trackedTransactions = new ConcurrentHashMap<>();
+    
+    
+    public void startTrackingModification(DataModification<P,D> modification) {
+        trackedTransactions.putIfAbsent(modification.getIdentifier(), modification);
+        
+        
+    }
+    
+    public boolean containsIdentifier(Object identifier) {
+        return trackedTransactions.containsKey(identifier);
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/spi/RpcRoutingContext.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/spi/RpcRoutingContext.java
new file mode 100644 (file)
index 0000000..e3a7235
--- /dev/null
@@ -0,0 +1,10 @@
+package org.opendaylight.controller.sal.binding.spi;
+
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+
+public interface RpcRoutingContext<C extends BaseIdentity,S extends RpcService> {
+
+    Class<C> getContextType();
+    Class<S> getServiceType();
+}
index d047f9c5f2b22f90122280c1a8cc4876f015738a..5b35861e9dd189bbabc2d385a82d0fd6ea5b24fa 100644 (file)
@@ -27,7 +27,7 @@ import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.common.util.concurrent.MoreExecutors;
 
 public  abstract class AbstractDataServiceTest {
-    protected DataBrokerService biDataService;
+    protected org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService;
     protected DataProviderService baDataService;
     
     /**
index 5ef4cc10973f08cbaaa0ac2f48f046ad52517476..f60ddb991dfc54017e8df463bcb14d0642ee144b 100644 (file)
@@ -1,24 +1,21 @@
 package org.opendaylight.controller.sal.binding.test.bugfix;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
+
+
 
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DropAction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DropActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopMplsAction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopMplsActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
@@ -26,9 +23,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
@@ -37,7 +32,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.N
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
@@ -50,7 +44,6 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 
-import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
@@ -72,16 +65,7 @@ public class DOMCodecBug01Test extends AbstractDataServiceTest {
     private static final Map<QName, Object> NODE_KEY_BI = Collections.<QName, Object> singletonMap(NODE_ID_QNAME,
             NODE_ID);
 
-    private static final InstanceIdentifier<Nodes> NODES_INSTANCE_ID_BA = InstanceIdentifier.builder(Nodes.class) // //
-            .toInstance();
-
-    private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier NODES_INSTANCE_ID_BI = //
-    org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() //
-            .node(Nodes.QNAME) //
-            .toInstance();
-
-    private static final InstanceIdentifier<Node> NODE_INSTANCE_ID_BA = InstanceIdentifier.builder() //
-            .node(Nodes.class) //
+    private static final InstanceIdentifier<Node> NODE_INSTANCE_ID_BA = InstanceIdentifier.builder(Nodes.class) //
             .child(Node.class, NODE_KEY).toInstance();
 
     private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier NODE_INSTANCE_ID_BI = //
@@ -144,6 +128,7 @@ public class DOMCodecBug01Test extends AbstractDataServiceTest {
         ListenableFuture<Void> task3Future = listenablePool.submit(task3);
 
 
+        @SuppressWarnings("unchecked")
         ListenableFuture<List<Void>> compositeFuture = Futures.allAsList(task1Future,task2Future,task3Future);
 
         Thread.sleep(500);
@@ -236,10 +221,7 @@ public class DOMCodecBug01Test extends AbstractDataServiceTest {
 
     private class CreateFlowTask implements Callable<Void> {
 
-        final Object startSyncObject;
-
         public CreateFlowTask(Object startSync) {
-            startSyncObject = startSync;
         }
 
         @Override
index 773bab80f1669c9a1c5736cbe2dc25784ffb716b..4df10bc135e51082169c9cd7c8072c6422e4de02 100644 (file)
@@ -1,8 +1,6 @@
 package org.opendaylight.controller.sal.binding.test.bugfix;
 
-import java.util.Arrays;
 import java.util.Collections;
-import java.util.List;
 import java.util.Map;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutorService;
@@ -13,43 +11,22 @@ import org.junit.Test;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
-import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
 
 import static org.junit.Assert.*;
 
 public class DOMCodecBug02Test extends AbstractDataServiceTest {
 
     private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id");
-    private static final QName FLOW_ID_QNAME = QName.create(Flow.QNAME, "id");
-    private static final QName FLOW_NODE_QNAME = QName.create(Flow.QNAME, "node");
-
-    private static final String FLOW_ID = "foo";
     private static final String NODE_ID = "node:1";
 
     private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID));
@@ -57,8 +34,7 @@ public class DOMCodecBug02Test extends AbstractDataServiceTest {
     private static final Map<QName, Object> NODE_KEY_BI = Collections.<QName, Object> singletonMap(NODE_ID_QNAME,
             NODE_ID);
 
-    private static final InstanceIdentifier<Nodes> NODES_INSTANCE_ID_BA = InstanceIdentifier.builder() //
-            .node(Nodes.class) //
+    private static final InstanceIdentifier<Nodes> NODES_INSTANCE_ID_BA = InstanceIdentifier.builder(Nodes.class) //
             .toInstance();
 
     private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier NODES_INSTANCE_ID_BI = //
@@ -66,8 +42,7 @@ public class DOMCodecBug02Test extends AbstractDataServiceTest {
             .node(Nodes.QNAME) //
             .toInstance();
 
-    private static final InstanceIdentifier<Node> NODE_INSTANCE_ID_BA = InstanceIdentifier.builder() //
-            .node(Nodes.class) //
+    private static final InstanceIdentifier<Node> NODE_INSTANCE_ID_BA = InstanceIdentifier.builder(Nodes.class) //
             .child(Node.class, NODE_KEY).toInstance();
 
     private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier NODE_INSTANCE_ID_BI = //
index 282aa564ac08a11ed0fab459be84d2d87ec7325c..2cd396dedc091076e08a28fe964a984619698eb9 100644 (file)
@@ -1,13 +1,7 @@
 package org.opendaylight.controller.sal.binding.test.bugfix;
-
-import java.util.Arrays;
 import java.util.Collections;
-import java.util.List;
 import java.util.Map;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
+
 
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
@@ -15,14 +9,8 @@ import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
 import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
 import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
@@ -30,26 +18,15 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.N
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
+
 
 import static org.junit.Assert.*;
 
@@ -66,10 +43,6 @@ public class DOMCodecBug03Test extends AbstractDataServiceTest implements DataCh
     private static final InstanceIdentifier<Nodes> NODES_INSTANCE_ID_BA = InstanceIdentifier.builder(Nodes.class) //
             .toInstance();
 
-    private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier NODES_INSTANCE_ID_BI = //
-    org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() //
-            .node(Nodes.QNAME) //
-            .toInstance();
 
     private static final InstanceIdentifier<Node> NODE_INSTANCE_ID_BA = InstanceIdentifier.builder(NODES_INSTANCE_ID_BA) //
             .child(Node.class, NODE_KEY).toInstance();
@@ -79,7 +52,6 @@ public class DOMCodecBug03Test extends AbstractDataServiceTest implements DataCh
             .node(Nodes.QNAME) //
             .nodeWithKey(Node.QNAME, NODE_KEY_BI) //
             .toInstance();
-    private static final NodeRef NODE_REF = new NodeRef(NODE_INSTANCE_ID_BA);
     private DataChangeEvent<InstanceIdentifier<?>, DataObject> receivedChangeEvent;
 
     
@@ -145,7 +117,7 @@ public class DOMCodecBug03Test extends AbstractDataServiceTest implements DataCh
         DataModificationTransaction transaction = baDataService.beginTransaction();
         transaction.putOperationalData(ncInstanceId, connector);
         RpcResult<TransactionStatus> result = transaction.commit().get();
-        
+        assertEquals(TransactionStatus.COMMITED, result.getResult());
         Node node = (Node) baDataService.readOperationalData(NODE_INSTANCE_ID_BA);
         assertNotNull(node);
         assertNotNull(node.getNodeConnector());
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/RpcRegistrationNullPointer.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/RpcRegistrationNullPointer.java
new file mode 100644 (file)
index 0000000..0c7f039
--- /dev/null
@@ -0,0 +1,8 @@
+package org.opendaylight.controller.sal.binding.test.bugfix;
+
+public class RpcRegistrationNullPointer {
+
+    
+    
+    
+}
index 7706cda750bd342555da2a95dc5b4e635daf6099..e326fd093116d4e7d3d45f5ba046c0bffb5f28a4 100644 (file)
@@ -63,7 +63,7 @@ public class BrokerIntegrationTest extends AbstractDataServiceTest {
         assertNotNull(result2.getResult());
         assertEquals(TransactionStatus.COMMITED, result.getResult());
 
-        Nodes allNodes = (Nodes) baDataService.readConfigurationData(InstanceIdentifier.builder().node(Nodes.class)
+        Nodes allNodes = (Nodes) baDataService.readConfigurationData(InstanceIdentifier.builder(Nodes.class)
                 .toInstance());
         assertNotNull(allNodes);
         assertNotNull(allNodes.getNode());
@@ -100,7 +100,7 @@ public class BrokerIntegrationTest extends AbstractDataServiceTest {
 
     private static NodeRef createNodeRef(String string) {
         NodeKey key = new NodeKey(new NodeId(string));
-        InstanceIdentifier<Node> path = InstanceIdentifier.builder().node(Nodes.class).node(Node.class, key)
+        InstanceIdentifier<Node> path = InstanceIdentifier.builder(Nodes.class).child(Node.class, key)
                 .toInstance();
         return new NodeRef(path);
     }
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java
new file mode 100644 (file)
index 0000000..63368bd
--- /dev/null
@@ -0,0 +1,190 @@
+package org.opendaylight.controller.sal.binding.test.connect.dom;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+
+
+
+
+
+
+
+
+
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Future;
+
+
+
+
+
+
+
+
+
+
+
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.CommitHandlersTransactions;
+import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
+import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopMplsActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+import com.google.common.collect.ImmutableMap;
+
+public class ChangeOriginatedInDomBrokerTest extends AbstractDataServiceTest {
+
+    private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id");
+    private static final QName FLOW_ID_QNAME = QName.create(Flow.QNAME, "id");
+    private static final QName FLOW_NODE_QNAME = QName.create(Flow.QNAME, "node");
+    private static final long FLOW_ID = 1234;
+    private static final String NODE_ID = "node:1";
+    
+    private DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modificationCapture;
+
+
+    private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID));
+
+    private static final Map<QName, Object> NODE_KEY_BI = Collections.<QName, Object> singletonMap(NODE_ID_QNAME,
+            NODE_ID);
+
+    private static final InstanceIdentifier<Node> NODE_INSTANCE_ID_BA = InstanceIdentifier.builder(Nodes.class) //
+            .child(Node.class, NODE_KEY).toInstance();
+
+    private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier NODE_INSTANCE_ID_BI = //
+    org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() //
+            .node(Nodes.QNAME) //
+            .nodeWithKey(Node.QNAME, NODE_KEY_BI) //
+            .toInstance();
+    private static final NodeRef NODE_REF = new NodeRef(NODE_INSTANCE_ID_BA);
+
+    private static final FlowKey FLOW_KEY = new FlowKey(FLOW_ID, NODE_REF);
+
+    private static final Map<QName, Object> FLOW_KEY_BI = //
+    ImmutableMap.<QName, Object> of(FLOW_ID_QNAME, FLOW_ID, FLOW_NODE_QNAME, NODE_INSTANCE_ID_BI);
+
+    private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier FLOW_INSTANCE_ID_BI = //
+    org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() //
+            .node(Flows.QNAME) //
+            .nodeWithKey(Flow.QNAME, FLOW_KEY_BI) //
+            .toInstance();
+    
+    private static final InstanceIdentifier<Flows> FLOWS_PATH_BA = //
+            InstanceIdentifier.builder(Flows.class) //
+                    .toInstance();
+            
+    
+    private static final InstanceIdentifier<Flow> FLOW_INSTANCE_ID_BA = //
+    InstanceIdentifier.builder(Flows.class) //
+            .child(Flow.class, FLOW_KEY) //
+            .toInstance();
+    
+    @Test
+    public void simpleModifyOperation() throws Exception {
+        
+        registerCommitHandler();
+        
+        CompositeNode domflow = createXmlFlow();
+        DataModificationTransaction biTransaction = biDataService.beginTransaction();
+        biTransaction.putConfigurationData(FLOW_INSTANCE_ID_BI, domflow);
+        RpcResult<TransactionStatus> biResult = biTransaction.commit().get();
+        
+        assertNotNull(modificationCapture);
+        Flow flow = (Flow) modificationCapture.getCreatedConfigurationData().get(FLOW_INSTANCE_ID_BA);
+        assertNotNull(flow);
+        assertNotNull(flow.getMatch());
+        assertEquals(TransactionStatus.COMMITED, biResult.getResult());
+        
+    }
+
+    
+
+    private void registerCommitHandler() {
+        DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> flowTestCommitHandler = new DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>() {
+            
+            
+            @Override
+            public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> requestCommit(
+                    DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
+                modificationCapture = modification;
+                return CommitHandlersTransactions.allwaysSuccessfulTransaction(modification);
+            }
+            
+            
+        };
+        Registration<DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>> registration = baDataService.registerCommitHandler(FLOWS_PATH_BA, flowTestCommitHandler);
+        assertNotNull(registration);
+    }
+    
+    private CompositeNode createXmlFlow() {
+        
+        FlowBuilder flow = new FlowBuilder();
+        MatchBuilder match = new MatchBuilder();
+        VlanMatchBuilder vlanBuilder = new VlanMatchBuilder();
+        VlanIdBuilder vlanIdBuilder = new VlanIdBuilder();
+        VlanId vlanId = new VlanId(10);
+        vlanBuilder.setVlanId(vlanIdBuilder.setVlanId(vlanId).build());
+        match.setVlanMatch(vlanBuilder.build());
+
+        flow.setKey(FLOW_KEY);
+        flow.setMatch(match.build());
+        flow.setNode(NODE_REF);
+        InstructionsBuilder instructions = new InstructionsBuilder();
+        InstructionBuilder instruction = new InstructionBuilder();
+        ApplyActionsBuilder applyActions = new ApplyActionsBuilder();
+        List<Action> actionList = new ArrayList<>();
+        PopMplsActionBuilder popMplsAction = new PopMplsActionBuilder();
+        popMplsAction.setEthernetType(34);
+        actionList.add(new ActionBuilder().setAction(popMplsAction.build()).build());
+
+        applyActions.setAction(actionList );
+        
+
+
+        instruction.setInstruction(applyActions.build());
+
+
+        List<Instruction> instructionList = Collections.<Instruction>singletonList(instruction.build());
+        instructions.setInstruction(instructionList );
+
+        flow.setInstructions(instructions.build());
+        
+        CompositeNode domFlow = mappingService.toDataDom(flow.build());
+        return domFlow;
+    }
+}
diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/RegistrationListener.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/RegistrationListener.java
new file mode 100644 (file)
index 0000000..f6efd57
--- /dev/null
@@ -0,0 +1,12 @@
+package org.opendaylight.controller.md.sal.common.api;
+
+import java.util.EventListener;
+
+import org.opendaylight.yangtools.concepts.Registration;
+
+public interface RegistrationListener<T extends Registration<?>> extends EventListener {
+
+    void onRegister(T registration);
+    
+    void onUnregister(T registration);
+}
diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataCommitHandlerRegistration.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataCommitHandlerRegistration.java
new file mode 100644 (file)
index 0000000..85db5a0
--- /dev/null
@@ -0,0 +1,9 @@
+package org.opendaylight.controller.md.sal.common.api.data;
+
+import org.opendaylight.yangtools.concepts.Path;
+import org.opendaylight.yangtools.concepts.Registration;
+
+public interface DataCommitHandlerRegistration<P extends Path<P>,D> extends Registration<DataCommitHandler<P, D>>{
+
+    P getPath();
+}
index 264d076b69be8074e443a0052e28eafbbfbe8f61..7d78fd283d169d16cc11510d4b68750ecb5c5733 100644 (file)
@@ -7,13 +7,17 @@
  */
 package org.opendaylight.controller.md.sal.common.api.data;
 
-// FIXME: After 0.6 Release of YANGTools refactor to use Path marker interface for arguments.
-// import org.opendaylight.yangtools.concepts.Path;
+import org.opendaylight.controller.md.sal.common.api.RegistrationListener;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.Path;
 import org.opendaylight.yangtools.concepts.Registration;
 
 
-public interface DataProvisionService<P/* extends Path<P> */, D> {
+public interface DataProvisionService<P extends Path<P> , D> {
 
     public Registration<DataCommitHandler<P, D>> registerCommitHandler(P path, DataCommitHandler<P, D> commitHandler);
+    
+    public ListenerRegistration<RegistrationListener<DataCommitHandlerRegistration<P, D>>> 
+        registerCommitHandlerListener(RegistrationListener<DataCommitHandlerRegistration<P, D>> commitHandlerListener);
 
 }
index 74c4e0a148640a2278deee8a87bf67c4c27eb334..e3d2b567a71f42b202bf028db6f0d8dcd5f70ae2 100644 (file)
@@ -34,12 +34,18 @@ import java.util.Collection
 import com.google.common.collect.FluentIterable;
 import java.util.Set
 import com.google.common.collect.ImmutableList
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandlerRegistration
+import org.opendaylight.controller.md.sal.common.api.RegistrationListener
+import org.opendaylight.yangtools.concepts.util.ListenerRegistry
+import java.util.concurrent.atomic.AtomicLong
 
 abstract class AbstractDataBroker<P extends Path<P>, D, DCL extends DataChangeListener<P, D>> implements DataModificationTransactionFactory<P, D>, //
 DataReader<P, D>, //
 DataChangePublisher<P, D, DCL>, //
 DataProvisionService<P, D> {
 
+    private static val LOG = LoggerFactory.getLogger(AbstractDataBroker);
+
     @Property
     var ExecutorService executor;
 
@@ -47,17 +53,17 @@ DataProvisionService<P, D> {
     var AbstractDataReadRouter<P, D> dataReadRouter;
 
     Multimap<P, DataChangeListenerRegistration<P, D, DCL>> listeners = HashMultimap.create();
-    Multimap<P, DataCommitHandlerRegistration<P, D>> commitHandlers = HashMultimap.create();
-
+    Multimap<P, DataCommitHandlerRegistrationImpl<P, D>> commitHandlers = HashMultimap.create();
+    
+    val ListenerRegistry<RegistrationListener<DataCommitHandlerRegistration<P,D>>> commitHandlerRegistrationListeners = new ListenerRegistry();
     public new() {
     }
 
     protected def /*Iterator<Entry<Collection<DataChangeListenerRegistration<P,D,DCL>>,D>>*/ affectedCommitHandlers(
         HashSet<P> paths) {
-        return FluentIterable.from(commitHandlers.asMap.entrySet)
-            .filter[key.isAffectedBy(paths)] //
-            .transformAndConcat [value] //
-            .transform[instance].toList()
+        return FluentIterable.from(commitHandlers.asMap.entrySet).filter[key.isAffectedBy(paths)] //
+        .transformAndConcat[value] //
+        .transform[instance].toList()
     }
 
     override final readConfigurationData(P path) {
@@ -69,8 +75,16 @@ DataProvisionService<P, D> {
     }
 
     override final registerCommitHandler(P path, DataCommitHandler<P, D> commitHandler) {
-        val registration = new DataCommitHandlerRegistration(path, commitHandler, this);
+        val registration = new DataCommitHandlerRegistrationImpl(path, commitHandler, this);
         commitHandlers.put(path, registration)
+        LOG.info("Registering Commit Handler {} for path: {}",commitHandler,path);
+        for(listener : commitHandlerRegistrationListeners) {
+            try {
+                listener.instance.onRegister(registration);
+            } catch (Exception e) {
+                LOG.error("Unexpected exception in listener {} during invoking onRegister",listener.instance,e);
+            }
+        }
         return registration;
     }
 
@@ -87,13 +101,29 @@ DataProvisionService<P, D> {
 
         return new CompositeObjectRegistration(reader, Arrays.asList(confReg, dataReg));
     }
+    
+    override registerCommitHandlerListener(RegistrationListener<DataCommitHandlerRegistration<P, D>> commitHandlerListener) {
+        val ret = commitHandlerRegistrationListeners.register(commitHandlerListener);
+        
+        return ret;
+    }
+    
 
     protected final def removeListener(DataChangeListenerRegistration<P, D, DCL> registration) {
         listeners.remove(registration.path, registration);
     }
 
-    protected final def removeCommitHandler(DataCommitHandlerRegistration<P, D> registration) {
+    protected final def removeCommitHandler(DataCommitHandlerRegistrationImpl<P, D> registration) {
         commitHandlers.remove(registration.path, registration);
+        
+         LOG.info("Removing Commit Handler {} for path: {}",registration.instance,registration.path);
+        for(listener : commitHandlerRegistrationListeners) {
+            try {
+                listener.instance.onUnregister(registration);
+            } catch (Exception e) {
+                LOG.error("Unexpected exception in listener {} during invoking onUnregister",listener.instance,e);
+            }
+        }
     }
 
     protected final def getActiveCommitHandlers() {
@@ -132,7 +162,7 @@ DataProvisionService<P, D> {
 }
 
 @Data
-package class ListenerStateCapture<P extends Path<P>, D,DCL extends DataChangeListener<P, D>> {
+package class ListenerStateCapture<P extends Path<P>, D, DCL extends DataChangeListener<P, D>> {
 
     @Property
     P path;
@@ -167,7 +197,9 @@ package class DataChangeListenerRegistration<P extends Path<P>, D, DCL extends D
 
 }
 
-package class DataCommitHandlerRegistration<P extends Path<P>, D> extends AbstractObjectRegistration<DataCommitHandler<P, D>> {
+package class DataCommitHandlerRegistrationImpl<P extends Path<P>, D> //
+extends AbstractObjectRegistration<DataCommitHandler<P, D>> //
+implements DataCommitHandlerRegistration<P, D> {
 
     AbstractDataBroker<P, D, ?> dataBroker;
 
@@ -184,10 +216,9 @@ package class DataCommitHandlerRegistration<P extends Path<P>, D> extends Abstra
         dataBroker.removeCommitHandler(this);
         dataBroker = null;
     }
-
 }
 
-package class TwoPhaseCommit<P extends Path<P>, D,DCL extends DataChangeListener<P, D>> implements Callable<RpcResult<TransactionStatus>> {
+package class TwoPhaseCommit<P extends Path<P>, D, DCL extends DataChangeListener<P, D>> implements Callable<RpcResult<TransactionStatus>> {
 
     private static val log = LoggerFactory.getLogger(TwoPhaseCommit);
 
@@ -214,15 +245,18 @@ package class TwoPhaseCommit<P extends Path<P>, D,DCL extends DataChangeListener
 
         val listeners = dataBroker.affectedListenersWithInitialState(affectedPaths);
 
+        val transactionId = transaction.identifier;
+
+        log.info("Transaction: {} Started.",transactionId);
         // requesting commits
-        val Iterable<DataCommitHandler<P, D>> commitHandlers =   dataBroker.affectedCommitHandlers(affectedPaths);
+        val Iterable<DataCommitHandler<P, D>> commitHandlers = dataBroker.affectedCommitHandlers(affectedPaths);
         val List<DataCommitTransaction<P, D>> handlerTransactions = new ArrayList();
         try {
             for (handler : commitHandlers) {
                 handlerTransactions.add(handler.requestCommit(transaction));
             }
         } catch (Exception e) {
-            log.error("Request Commit failded", e);
+            log.error("Transaction: {} Request Commit failed", transactionId,e);
             return rollback(handlerTransactions, e);
         }
         val List<RpcResult<Void>> results = new ArrayList();
@@ -232,25 +266,25 @@ package class TwoPhaseCommit<P extends Path<P>, D,DCL extends DataChangeListener
             }
             listeners.publishDataChangeEvent();
         } catch (Exception e) {
-            log.error("Finish Commit failed", e);
+            log.error("Transaction: {} Finish Commit failed",transactionId, e);
             return rollback(handlerTransactions, e);
         }
-
-        
+        log.info("Transaction: {} Finished succesfully.",transactionId);
         return Rpcs.getRpcResult(true, TransactionStatus.COMMITED, Collections.emptySet());
 
     }
-    
-    def void publishDataChangeEvent(ImmutableList<ListenerStateCapture<P, D,DCL>> listeners) {
-        for(listenerSet : listeners) {
+
+    def void publishDataChangeEvent(ImmutableList<ListenerStateCapture<P, D, DCL>> listeners) {
+        for (listenerSet : listeners) {
             val updatedConfiguration = dataBroker.readConfigurationData(listenerSet.path);
             val updatedOperational = dataBroker.readOperationalData(listenerSet.path);
-            
-            val changeEvent = new DataChangeEventImpl(transaction,listenerSet.initialConfigurationState,listenerSet.initialOperationalState,updatedOperational,updatedConfiguration);
-            for(listener : listenerSet.listeners) {
+
+            val changeEvent = new DataChangeEventImpl(transaction, listenerSet.initialConfigurationState,
+                listenerSet.initialOperationalState, updatedOperational, updatedConfiguration);
+            for (listener : listenerSet.listeners) {
                 try {
                     listener.instance.onDataChanged(changeEvent);
-                    
+
                 } catch (Exception e) {
                     e.printStackTrace();
                 }
@@ -267,6 +301,7 @@ package class TwoPhaseCommit<P extends Path<P>, D,DCL extends DataChangeListener
         return Rpcs.getRpcResult(false, TransactionStatus.FAILED, Collections.emptySet());
     }
 }
+
 public abstract class AbstractDataTransaction<P extends Path<P>, D> extends AbstractDataModification<P, D> {
 
     @Property
@@ -276,9 +311,9 @@ public abstract class AbstractDataTransaction<P extends Path<P>, D> extends Abst
 
     var AbstractDataBroker<P, D, ?> broker;
 
-    protected new(AbstractDataBroker<P, D, ?> dataBroker) {
+    protected new(Object identifier,AbstractDataBroker<P, D, ?> dataBroker) {
         super(dataBroker);
-        _identifier = new Object();
+        _identifier = identifier;
         broker = dataBroker;
         status = TransactionStatus.NEW;
 
index d95fdcc53dbc68019704b876c7a2ea7bdb34051e..1197ef34bd926d2de186931184c70043c5404033 100644 (file)
@@ -1,5 +1,7 @@
 package org.opendaylight.controller.sal.dom.broker;
 
+import java.util.concurrent.atomic.AtomicLong;
+
 import org.opendaylight.controller.md.sal.common.api.data.DataReader;
 import org.opendaylight.controller.md.sal.common.impl.service.AbstractDataBroker;
 import org.opendaylight.controller.sal.common.DataStoreIdentifier;
@@ -18,9 +20,12 @@ public class DataBrokerImpl extends AbstractDataBroker<InstanceIdentifier, Compo
         setDataReadRouter(new DataReaderRouter());
     }
 
+    private AtomicLong nextTransaction = new AtomicLong();
+    
     @Override
     public DataTransactionImpl beginTransaction() {
-        return new DataTransactionImpl(this);
+        String transactionId = "DOM-" + nextTransaction.getAndIncrement();
+        return new DataTransactionImpl(transactionId,this);
     }
 
     @Override
@@ -38,29 +43,26 @@ public class DataBrokerImpl extends AbstractDataBroker<InstanceIdentifier, Compo
     @Deprecated
     @Override
     public void addValidator(DataStoreIdentifier store, DataValidator validator) {
-        // TODO Auto-generated method stub
+        throw new UnsupportedOperationException("Deprecated");
 
     }
 
     @Deprecated
     @Override
     public void removeValidator(DataStoreIdentifier store, DataValidator validator) {
-        // TODO Auto-generated method stub
-
+        throw new UnsupportedOperationException("Deprecated");
     }
 
     @Deprecated
     @Override
     public void addRefresher(DataStoreIdentifier store, DataRefresher refresher) {
-        // TODO Auto-generated method stub
-
+        throw new UnsupportedOperationException("Deprecated");
     }
 
     @Deprecated
     @Override
     public void removeRefresher(DataStoreIdentifier store, DataRefresher refresher) {
-        // TODO Auto-generated method stub
-
+        throw new UnsupportedOperationException("Deprecated");
     }
 
 }
\ No newline at end of file
index 5cb01c9a1064eeaa024ae68cbc20c0e2d440bbcf..8c289f05082e0b7c45fbabff30d51e0ef9f753fa 100644 (file)
@@ -14,8 +14,8 @@ public class DataTransactionImpl extends AbstractDataTransaction<InstanceIdentif
     
     
     
-    public DataTransactionImpl(DataBrokerImpl dataBroker) {
-        super(dataBroker);
+    public DataTransactionImpl(Object identifier,DataBrokerImpl dataBroker) {
+        super(identifier,dataBroker);
     }
 
     @Override
index eafc402ddcea6987b82980b5a2d92ffec5443108..7509a38a1429308029f25bcc85d90a32b6ed8f2d 100644 (file)
@@ -4,7 +4,9 @@ import java.util.List;
 import java.util.Set;
 import java.util.concurrent.Future;
 
+import org.opendaylight.controller.md.sal.common.api.RegistrationListener;
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandlerRegistration;
 import org.opendaylight.controller.md.sal.common.api.data.DataReader;
 import org.opendaylight.controller.sal.common.DataStoreIdentifier;
 import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
@@ -191,4 +193,11 @@ public class MountPointImpl implements MountProvisionInstance {
             return MountPointImpl.this.readOperationalData(newPath);
         }
     }
+
+    @Override
+    public ListenerRegistration<RegistrationListener<DataCommitHandlerRegistration<InstanceIdentifier, CompositeNode>>> registerCommitHandlerListener(
+            RegistrationListener<DataCommitHandlerRegistration<InstanceIdentifier, CompositeNode>> commitHandlerListener) {
+        // TODO Auto-generated method stub
+        return null;
+    }
 }
index 2fded87981e8fa2fa67651b8c4182f034d73156e..329219ebb0dc7e90583d5fd76984653513bcbcf8 100644 (file)
@@ -1,6 +1,8 @@
 package org.opendaylight.controller.sal.dom.broker.osgi;
 
+import org.opendaylight.controller.md.sal.common.api.RegistrationListener;
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandlerRegistration;
 import org.opendaylight.controller.md.sal.common.api.data.DataReader;
 import org.opendaylight.controller.sal.common.DataStoreIdentifier;
 import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
@@ -74,4 +76,10 @@ public class DataProviderServiceProxy extends AbstractBrokerServiceProxy<DataPro
     public void removeValidator(DataStoreIdentifier store, DataValidator validator) {
         getDelegate().removeValidator(store, validator);
     }
+    
+    @Override
+    public ListenerRegistration<RegistrationListener<DataCommitHandlerRegistration<InstanceIdentifier, CompositeNode>>> registerCommitHandlerListener(
+            RegistrationListener<DataCommitHandlerRegistration<InstanceIdentifier, CompositeNode>> commitHandlerListener) {
+        return addRegistration(getDelegate().registerCommitHandlerListener(commitHandlerListener));
+    }
 }