BUG-732 Fix netconf client deadlock when downloading yang schemas from remote device 53/6253/2
authorMaros Marsalek <mmarsale@cisco.com>
Thu, 17 Apr 2014 10:12:25 +0000 (12:12 +0200)
committerMaros Marsalek <mmarsale@cisco.com>
Tue, 22 Apr 2014 12:53:09 +0000 (12:53 +0000)
Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
Change-Id: Ic70085655e38ebc1e159fd4ba4b93172e468f4ad

opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfMapping.java

index abbbb68..4ea0fa5 100644 (file)
@@ -172,30 +172,40 @@ public class NetconfDevice implements Provider, //
         }
     }
 
-    void bringUp(SchemaSourceProvider<String> delegate, Set<QName> capabilities) {
-        remoteSourceProvider = schemaSourceProvider.createInstanceFor(delegate);
-        deviceContextProvider = new NetconfDeviceSchemaContextProvider(this, remoteSourceProvider);
-        deviceContextProvider.createContextFromCapabilities(capabilities);
-        if (mountInstance != null && getSchemaContext().isPresent()) {
-            mountInstance.setSchemaContext(getSchemaContext().get());
-        }
+    void bringUp(final SchemaSourceProvider<String> delegate, final Set<QName> capabilities) {
+        // This has to be called from separate thread, not from netty thread calling onSessionUp in DeviceListener.
+        // Reason: delegate.getSchema blocks thread when waiting for response
+        // however, if the netty thread is blocked, no incoming message can be processed
+        // ... netty should pick another thread from pool to process incoming message, but it does not http://netty.io/wiki/thread-model.html
+        // TODO redesign +refactor
+        processingExecutor.submit(new Runnable() {
+            @Override
+            public void run() {
+                remoteSourceProvider = schemaSourceProvider.createInstanceFor(delegate);
+                deviceContextProvider = new NetconfDeviceSchemaContextProvider(NetconfDevice.this, remoteSourceProvider);
+                deviceContextProvider.createContextFromCapabilities(capabilities);
+                if (mountInstance != null && getSchemaContext().isPresent()) {
+                    mountInstance.setSchemaContext(getSchemaContext().get());
+                }
 
-        updateDeviceState(true, capabilities);
+                updateDeviceState(true, capabilities);
 
-        if (mountInstance != null) {
-            confReaderReg = mountInstance.registerConfigurationReader(ROOT_PATH, this);
-            operReaderReg = mountInstance.registerOperationalReader(ROOT_PATH, this);
-            commitHandlerReg = mountInstance.registerCommitHandler(ROOT_PATH, this);
+                if (mountInstance != null) {
+                    confReaderReg = mountInstance.registerConfigurationReader(ROOT_PATH, NetconfDevice.this);
+                    operReaderReg = mountInstance.registerOperationalReader(ROOT_PATH, NetconfDevice.this);
+                    commitHandlerReg = mountInstance.registerCommitHandler(ROOT_PATH, NetconfDevice.this);
 
-            List<RpcRegistration> rpcs = new ArrayList<>();
-            // TODO same condition twice
-            if (mountInstance != null && getSchemaContext().isPresent()) {
-                for (RpcDefinition rpc : mountInstance.getSchemaContext().getOperations()) {
-                    rpcs.add(mountInstance.addRpcImplementation(rpc.getQName(), this));
+                    List<RpcRegistration> rpcs = new ArrayList<>();
+                    // TODO same condition twice
+                    if (mountInstance != null && getSchemaContext().isPresent()) {
+                        for (RpcDefinition rpc : mountInstance.getSchemaContext().getOperations()) {
+                            rpcs.add(mountInstance.addRpcImplementation(rpc.getQName(), NetconfDevice.this));
+                        }
+                    }
+                    rpcReg = rpcs;
                 }
             }
-            rpcReg = rpcs;
-        }
+        });
     }
 
     private void updateDeviceState(boolean up, Set<QName> capabilities) {
index ce2661a..a8ef4dd 100644 (file)
@@ -143,8 +143,7 @@ public class NetconfMapping {
         try {
             w3cPayload = XmlDocumentUtils.toDocument(rpcPayload, XmlDocumentUtils.defaultValueCodecProvider());
         } catch (UnsupportedDataTypeException e) {
-            // FIXME Ex handling
-            e.printStackTrace();
+            throw new IllegalArgumentException("Unable to create message", e);
         }
         w3cPayload.getDocumentElement().setAttribute("message-id", "m-" + messageId.getAndIncrement());
         return new NetconfMessage(w3cPayload);
@@ -249,7 +248,7 @@ public class NetconfMapping {
     public static void checkValidReply(NetconfMessage input, NetconfMessage output) {
         String inputMsgId = input.getDocument().getDocumentElement().getAttribute("message-id");
         String outputMsgId = output.getDocument().getDocumentElement().getAttribute("message-id");
-        Preconditions.checkState(inputMsgId == outputMsgId, "Rpc request and reply message IDs must be same.");
+        Preconditions.checkState(inputMsgId.equals(outputMsgId), "Rpc request and reply message IDs must be same.");
     }
 
 }

©2013 OpenDaylight, A Linux Foundation Collaborative Project. All Rights Reserved.
OpenDaylight is a registered trademark of The OpenDaylight Project, Inc.
Linux Foundation and OpenDaylight are registered trademarks of the Linux Foundation.
Linux is a registered trademark of Linus Torvalds.