From: Maros Marsalek Date: Thu, 17 Apr 2014 10:12:25 +0000 (+0200) Subject: BUG-732 Fix netconf client deadlock when downloading yang schemas from remote device X-Git-Tag: autorelease-tag-v20140601202136_82eb3f9~183^2 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=335821ba0e63f03416b15ac0902af326c2968671;ds=sidebyside BUG-732 Fix netconf client deadlock when downloading yang schemas from remote device Signed-off-by: Maros Marsalek Change-Id: Ic70085655e38ebc1e159fd4ba4b93172e468f4ad --- diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.java index abbbb68265..4ea0fa5645 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.java @@ -172,30 +172,40 @@ public class NetconfDevice implements Provider, // } } - void bringUp(SchemaSourceProvider delegate, Set 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 delegate, final Set 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 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 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 capabilities) { diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfMapping.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfMapping.java index ce2661a7b3..a8ef4dd2fb 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfMapping.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfMapping.java @@ -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."); } }