From: miroslav.kovac Date: Fri, 15 Apr 2016 07:07:47 +0000 (+0200) Subject: caching the same capabilities for devices using Interner. X-Git-Tag: release/boron~133^2 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=f80302b40463e50de60ef533cfc6dbf5e08edc21;hp=2e464bc9c0d2f88f3b2c4baab39bde48f68960e8;p=netconf.git caching the same capabilities for devices using Interner. Change-Id: I70ad61ad714e679b237ab01778690ab4fd1391f1 Signed-off-by: miroslav.kovac --- diff --git a/netconf/netconf-client/src/main/java/org/opendaylight/netconf/client/NetconfClientSessionNegotiator.java b/netconf/netconf-client/src/main/java/org/opendaylight/netconf/client/NetconfClientSessionNegotiator.java index 4ae7dea12c..55d92d6df6 100644 --- a/netconf/netconf-client/src/main/java/org/opendaylight/netconf/client/NetconfClientSessionNegotiator.java +++ b/netconf/netconf-client/src/main/java/org/opendaylight/netconf/client/NetconfClientSessionNegotiator.java @@ -9,7 +9,9 @@ package org.opendaylight.netconf.client; import com.google.common.base.Strings; -import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Interner; +import com.google.common.collect.Interners; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; @@ -17,20 +19,20 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.util.Timer; import io.netty.util.concurrent.Promise; -import java.util.Collection; +import java.util.Set; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpression; import org.opendaylight.controller.config.util.xml.XmlUtil; +import org.opendaylight.netconf.api.NetconfClientSessionPreferences; +import org.opendaylight.netconf.api.NetconfDocumentedException; +import org.opendaylight.netconf.api.NetconfMessage; +import org.opendaylight.netconf.api.messages.NetconfHelloMessage; +import org.opendaylight.netconf.api.xml.XmlNetconfConstants; import org.opendaylight.netconf.nettyutil.AbstractChannelInitializer; import org.opendaylight.netconf.nettyutil.AbstractNetconfSessionNegotiator; import org.opendaylight.netconf.nettyutil.handler.exi.NetconfStartExiMessage; -import org.opendaylight.netconf.api.messages.NetconfHelloMessage; import org.opendaylight.netconf.util.messages.NetconfMessageUtil; import org.opendaylight.netconf.util.xml.XMLNetconfUtil; -import org.opendaylight.netconf.api.NetconfClientSessionPreferences; -import org.opendaylight.netconf.api.NetconfDocumentedException; -import org.opendaylight.netconf.api.NetconfMessage; -import org.opendaylight.netconf.api.xml.XmlNetconfConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; @@ -50,6 +52,8 @@ public class NetconfClientSessionNegotiator extends private static final String EXI_1_0_CAPABILITY_MARKER = "exi:1.0"; + private static final Interner> INTERNER = Interners.newWeakInterner(); + protected NetconfClientSessionNegotiator(final NetconfClientSessionPreferences sessionPreferences, final Promise promise, final Channel channel, @@ -134,13 +138,14 @@ public class NetconfClientSessionNegotiator extends @Override protected NetconfClientSession getSession(final NetconfClientSessionListener sessionListener, final Channel channel, - final NetconfHelloMessage message) throws NetconfDocumentedException { - long sessionId = extractSessionId(message.getDocument()); + final NetconfHelloMessage message) throws NetconfDocumentedException { + final long sessionId = extractSessionId(message.getDocument()); // Copy here is important: it disconnects the strings from the document - Collection capabilities = ImmutableList.copyOf(NetconfMessageUtil.extractCapabilitiesFromHello(message.getDocument())); + Set capabilities = ImmutableSet.copyOf(NetconfMessageUtil.extractCapabilitiesFromHello(message.getDocument())); + + capabilities = INTERNER.intern(capabilities); - // FIXME: scalability: we could instantiate a cache to share the same collections return new NetconfClientSession(sessionListener, channel, sessionId, capabilities); } diff --git a/netconf/netconf-client/src/test/java/org/opendaylight/netconf/client/NetconfClientSessionNegotiatorTest.java b/netconf/netconf-client/src/test/java/org/opendaylight/netconf/client/NetconfClientSessionNegotiatorTest.java index 01c50c11e8..9632d176af 100644 --- a/netconf/netconf-client/src/test/java/org/opendaylight/netconf/client/NetconfClientSessionNegotiatorTest.java +++ b/netconf/netconf-client/src/test/java/org/opendaylight/netconf/client/NetconfClientSessionNegotiatorTest.java @@ -8,6 +8,9 @@ package org.opendaylight.netconf.client; +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertTrue; +import static org.junit.Assert.assertNotEquals; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyObject; import static org.mockito.Matchers.anyString; @@ -18,6 +21,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import com.google.common.base.Optional; +import com.google.common.collect.ImmutableSet; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; @@ -31,20 +35,23 @@ import io.netty.util.HashedWheelTimer; import io.netty.util.Timer; import io.netty.util.concurrent.GenericFutureListener; import io.netty.util.concurrent.Promise; +import java.io.InputStream; import java.util.Set; import org.junit.Before; import org.junit.Test; import org.mockito.internal.util.collections.Sets; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; +import org.opendaylight.controller.config.util.xml.XmlUtil; import org.opendaylight.netconf.api.NetconfClientSessionPreferences; import org.opendaylight.netconf.api.NetconfMessage; +import org.opendaylight.netconf.api.messages.NetconfHelloMessage; +import org.opendaylight.netconf.api.messages.NetconfHelloMessageAdditionalHeader; import org.opendaylight.netconf.nettyutil.handler.ChunkedFramingMechanismEncoder; import org.opendaylight.netconf.nettyutil.handler.NetconfXMLToHelloMessageDecoder; import org.opendaylight.netconf.nettyutil.handler.NetconfXMLToMessageDecoder; import org.opendaylight.netconf.nettyutil.handler.exi.NetconfStartExiMessage; -import org.opendaylight.netconf.api.messages.NetconfHelloMessage; -import org.opendaylight.netconf.api.messages.NetconfHelloMessageAdditionalHeader; +import org.opendaylight.netconf.util.messages.NetconfMessageUtil; import org.opendaylight.netconf.util.test.XmlFileLoader; import org.openexi.proc.common.EXIOptions; import org.w3c.dom.Document; @@ -131,6 +138,19 @@ public class NetconfClientSessionNegotiatorTest { return new NetconfClientSessionNegotiator(preferences, promise, channel, timer, sessionListener, timeout); } + private NetconfHelloMessage createHelloMsg(final String name) throws Exception { + final InputStream stream = NetconfClientSessionNegotiatorTest.class.getResourceAsStream(name); + final Document doc = XmlUtil.readXmlToDocument(stream); + + return new NetconfHelloMessage(doc); + } + + private Set createCapabilities(String name) throws Exception { + NetconfHelloMessage hello = createHelloMsg(name); + + return ImmutableSet.copyOf(NetconfMessageUtil.extractCapabilitiesFromHello(hello.getDocument())); + } + @Test public void testNetconfClientSessionNegotiator() throws Exception { Promise promise = mock(Promise.class); @@ -175,4 +195,28 @@ public class NetconfClientSessionNegotiatorTest { // two calls for exiMessage, 2 for hello message verify(pipeline, times(4)).replace(anyString(), anyString(), any(ChannelHandler.class)); } + + @Test + public void testNetconfClientSessionNegotiatorGetCached() throws Exception { + Promise promise = mock(Promise.class); + doReturn(promise).when(promise).setSuccess(anyObject()); + NetconfClientSessionListener sessionListener = mock(NetconfClientSessionListener.class); + NetconfClientSessionNegotiator negotiator = createNetconfClientSessionNegotiator(promise, null); + + Set set = createCapabilities("/helloMessage3.xml"); + + final Set cachedS1 = (Set) negotiator.getSession(sessionListener,channel,createHelloMsg("/helloMessage1.xml")).getServerCapabilities(); + + //helloMessage2 and helloMessage3 are the same with different order + final Set cachedS2 = (Set) negotiator.getSession(sessionListener,channel,createHelloMsg("/helloMessage2.xml")).getServerCapabilities(); + final Set cachedS3 = (Set) negotiator.getSession(sessionListener,channel,createHelloMsg("/helloMessage3.xml")).getServerCapabilities(); + + assertEquals(cachedS3, set); + assertNotEquals(cachedS1, set); + assertEquals(cachedS2, set); + assertEquals(cachedS3, cachedS2); + assertNotEquals(cachedS3, cachedS1); + assertNotEquals(cachedS2, cachedS1); + assertTrue(cachedS2 == cachedS3); + } } diff --git a/netconf/netconf-client/src/test/resources/helloMessage1.xml b/netconf/netconf-client/src/test/resources/helloMessage1.xml new file mode 100644 index 0000000000..9cc3feb849 --- /dev/null +++ b/netconf/netconf-client/src/test/resources/helloMessage1.xml @@ -0,0 +1,94 @@ + + + urn:ietf:params:xml:ns:yang:ietf-yang-types?module=ietf-yang-types&revision=2010-09-24 + urn:ietf:params:xml:ns:yang:iana-if-type?module=iana-if-type&revision=2014-05-08 + urn:ietf:params:xml:ns:yang:ietf-interfaces?module=ietf-interfaces&revision=2014-05-08 + urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl?module=opendaylight-sal-binding-broker-impl&revision=2013-10-28 + urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:flexible?module=threadpool-impl-flexible&revision=2013-12-01 + urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring?module=ietf-netconf-monitoring&revision=2010-10-04 + urn:opendaylight:params:xml:ns:yang:controller:config:netconf:client:dispatcher?module=odl-netconfig-client-cfg&revision=2014-04-08 + urn:ietf:params:xml:ns:yang:ietf-inet-types?module=ietf-inet-types&revision=2010-09-24 + urn:opendaylight:params:xml:ns:yang:controller:netconf:northbound:notification?module=netconf-northbound-notification&revision=2015-08-06 + urn:opendaylight:params:xml:ns:yang:controller:config:netconf:northbound:impl?module=netconf-northbound-impl&revision=2015-01-12 + urn:opendaylight:params:xml:ns:yang:controller:netconf:northbound:notification:impl?module=netconf-northbound-notification-impl&revision=2015-08-07 + urn:opendaylight:params:xml:ns:yang:controller:config:concurrent-data-broker?module=odl-concurrent-data-broker-cfg&revision=2014-11-24 + urn:TBD:params:xml:ns:yang:nt:l3-unicast-igp-topology?module=l3-unicast-igp-topology&revision=2013-10-21 + urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28 + urn:opendaylight:params:xml:ns:yang:controller:netty:eventexecutor?module=netty-event-executor&revision=2013-11-12 + urn:opendaylight:params:xml:ns:yang:controller:netconf:topology:shared:schema:repository?module=shared-schema-repository&revision=2015-07-27 + urn:opendaylight:params:xml:ns:yang:controller:md:sal:cluster:admin?module=cluster-admin&revision=2015-10-13 + urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:general-entity?module=general-entity&revision=2015-08-20 + urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom?module=opendaylight-md-sal-dom&revision=2013-10-28 + urn:opendaylight:yang:extension:yang-ext?module=yang-ext&revision=2013-07-09 + urn:ietf:params:xml:ns:yang:rpc-context?module=rpc-context&revision=2013-06-17 + urn:ietf:params:xml:ns:yang:ietf-network-topology?module=ietf-network-topology&revision=2015-06-08 + urn:ietf:params:xml:ns:yang:ietf-netconf-notifications?module=ietf-netconf-notifications&revision=2012-02-06 + urn:TBD:params:xml:ns:yang:ospf-topology?module=ospf-topology&revision=2013-10-21 + config:aaa:authn:netconf:plugin?module=aaa-authn-netconf-plugin&revision=2015-07-15 + urn:opendaylight:params:xml:ns:yang:controller:config:netconf:auth?module=netconf-auth&revision=2015-07-15 + urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:operational-dom-store?module=opendaylight-operational-dom-datastore&revision=2014-06-17 + urn:ietf:params:xml:ns:yang:ospf-topology?module=ospf-topology&revision=2013-07-12 + urn:ietf:params:netconf:capability:exi:1.0 + urn:opendaylight:params:xml:ns:yang:controller:netconf:north:mapper?module=netconf-northbound-mapper&revision=2015-01-14 + urn:ietf:params:xml:ns:netconf:base:1.0?module=ietf-netconf&revision=2011-06-01 + urn:TBD:params:xml:ns:yang:network-topology?module=network-topology&revision=2013-10-21 + urn:opendaylight:params:xml:ns:yang:controller:shutdown:impl?module=shutdown-impl&revision=2013-12-18 + urn:opendaylight:params:xml:ns:yang:controller:netconf:topology?module=netconf-topology&revision=2015-07-27 + urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl?module=threadpool-impl&revision=2013-04-05 + urn:ietf:params:xml:ns:yang:ietf-yang-types?module=ietf-yang-types&revision=2013-07-15 + urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&revision=2013-10-28 + urn:opendaylight:params:xml:ns:yang:controller:netconf:northbound:ssh?module=netconf-northbound-ssh&revision=2015-01-14 + urn:opendaylight:params:xml:ns:yang:controller:shutdown?module=shutdown&revision=2013-12-18 + urn:opendaylight:params:xml:ns:yang:aaa:credential-store?module=credential-store&revision=2015-02-26 + urn:TBD:params:xml:ns:yang:network-topology?module=network-topology&revision=2013-07-12 + urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:pingpong?module=opendaylight-pingpong-broker&revision=2014-11-07 + urn:opendaylight:params:xml:ns:yang:controller:netty:threadgroup?module=threadgroup&revision=2013-11-07 + urn:ietf:params:netconf:capability:candidate:1.0 + urn:ietf:params:xml:ns:yang:ietf-restconf?module=ietf-restconf&revision=2013-10-19 + urn:opendaylight:netconf-node-inventory?module=netconf-node-inventory&revision=2014-01-08 + urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:entity-ownership-service?module=opendaylight-entity-ownership-service&revision=2015-08-10 + urn:TBD:params:xml:ns:yang:nt:l3-unicast-igp-topology?module=l3-unicast-igp-topology&revision=2013-07-12 + urn:TBD:params:xml:ns:yang:network:ted?module=ted&revision=2013-07-12 + urn:TBD:params:xml:ns:yang:network:isis-topology?module=isis-topology&revision=2013-10-21 + config:aaa:authn:idmlight?module=aaa-idmlight&revision=2015-12-04 + urn:TBD:params:xml:ns:yang:network:isis-topology?module=isis-topology&revision=2013-07-12 + config:aaa:authn:h2:store?module=aaa-h2-store&revision=2015-11-28 + urn:TBD:params:xml:ns:yang:network:ted?module=ted&revision=2013-10-21 + urn:opendaylight:params:xml:ns:yang:controller:netconf:northbound:tcp?module=netconf-northbound-tcp&revision=2015-04-23 + urn:opendaylight:params:xml:ns:yang:controller:clustered:netconf:topology?module=clustered-netconf-topology&revision=2015-11-04 + urn:opendaylight:params:xml:ns:yang:controller:md:sal:clustering:entity-owners?module=entity-owners&revision=2015-08-04 + urn:opendaylight:params:xml:ns:yang:controller:md:sal:common?module=opendaylight-md-sal-common&revision=2013-10-28 + urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:fixed?module=threadpool-impl-fixed&revision=2013-12-01 + urn:opendaylight:params:xml:ns:yang:controller:config:actor-system-provider:service?module=actor-system-provider-service&revision=2015-10-05 + urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf?module=odl-sal-netconf-connector-cfg&revision=2015-08-03 + urn:opendaylight:netconf-node-topology?module=netconf-node-topology&revision=2015-01-14 + urn:opendaylight:params:xml:ns:yang:controller:config:distributed-entity-ownership-service?module=distributed-entity-ownership-service&revision=2015-08-10 + urn:opendaylight:params:xml:ns:yang:controller:inmemory-datastore-provider?module=opendaylight-inmemory-datastore-provider&revision=2014-06-17 + urn:opendaylight:inventory?module=opendaylight-inventory&revision=2013-08-19 + urn:opendaylight:params:xml:ns:yang:controller:config?module=config&revision=2013-04-05 + urn:opendaylight:params:xml:ns:yang:controller:netty:timer?module=netty-timer&revision=2013-11-19 + urn:ietf:params:xml:ns:netconf:notification:1.0?module=notifications&revision=2008-07-14 + urn:opendaylight:params:xml:ns:yang:controller:config:cluster-admin-provider?module=cluster-admin-provider&revision=2015-10-13 + urn:ietf:params:xml:ns:netmod:notification?module=nc-notifications&revision=2008-07-14 + urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring-extension?module=ietf-netconf-monitoring-extension&revision=2013-12-10 + urn:ietf:params:netconf:base:1.1 + urn:ietf:params:netconf:base:1.0 + urn:opendaylight:params:xml:ns:yang:controller:config:distributed-datastore-provider?module=distributed-datastore-provider&revision=2014-06-12 + urn:opendaylight:params:xml:ns:yang:controller:config:remote-rpc-connector?module=remote-rpc-connector&revision=2014-07-07 + urn:ietf:params:netconf:capability:notification:1.0 + urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:config-dom-store?module=opendaylight-config-dom-datastore&revision=2014-06-17 + urn:ietf:params:xml:ns:yang:iana-afn-safi?module=iana-afn-safi&revision=2013-07-04 + urn:opendaylight:params:xml:ns:yang:controller:config:netconf?module=odl-netconf-cfg&revision=2014-04-08 + urn:opendaylight:params:xml:ns:yang:controller:config:netconf:northbound?module=netconf-northbound&revision=2015-01-14 + urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:scheduled?module=threadpool-impl-scheduled&revision=2013-12-01 + urn:opendaylight:params:xml:ns:yang:controller:config:actor-system-provider:impl?module=actor-system-provider-impl&revision=2015-10-05 + urn:opendaylight:params:xml:ns:yang:controller:netty?module=netty&revision=2013-11-19 + urn:opendaylight:params:xml:ns:yang:controller:threadpool?module=threadpool&revision=2013-04-09 + urn:ietf:params:xml:ns:yang:ietf-network?module=ietf-network&revision=2015-06-08 + urn:opendaylight:l2:types?module=opendaylight-l2-types&revision=2013-08-27 + urn:opendaylight:params:xml:ns:yang:controller:protocol:framework?module=protocol-framework&revision=2014-03-13 + urn:ietf:params:xml:ns:yang:ietf-inet-types?module=ietf-inet-types&revision=2013-07-15 + + 1 + + diff --git a/netconf/netconf-client/src/test/resources/helloMessage2.xml b/netconf/netconf-client/src/test/resources/helloMessage2.xml new file mode 100644 index 0000000000..e95f5bb4e6 --- /dev/null +++ b/netconf/netconf-client/src/test/resources/helloMessage2.xml @@ -0,0 +1,14 @@ + + + urn:ietf:params:xml:ns:yang:ietf-yang-types?module=ietf-yang-types&revision=2010-09-24 + urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring?module=ietf-netconf-monitoring&revision=2010-10-04 + urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring-extension?module=ietf-netconf-monitoring-extension&revision=2013-12-10 + urn:ietf:params:netconf:capability:exi:1.0 + http://example.com/system?module=empolyees&revision=2007-06-09 + urn:ietf:params:netconf:capability:candidate:1.0 + urn:ietf:params:xml:ns:yang:ietf-inet-types?module=ietf-inet-types&revision=2010-09-24 + urn:ietf:params:netconf:base:1.1 + urn:ietf:params:netconf:base:1.0 + + 1 + diff --git a/netconf/netconf-client/src/test/resources/helloMessage3.xml b/netconf/netconf-client/src/test/resources/helloMessage3.xml new file mode 100644 index 0000000000..6ee373deae --- /dev/null +++ b/netconf/netconf-client/src/test/resources/helloMessage3.xml @@ -0,0 +1,14 @@ + + + urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring?module=ietf-netconf-monitoring&revision=2010-10-04 + urn:ietf:params:xml:ns:yang:ietf-yang-types?module=ietf-yang-types&revision=2010-09-24 + urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring-extension?module=ietf-netconf-monitoring-extension&revision=2013-12-10 + urn:ietf:params:netconf:capability:exi:1.0 + http://example.com/system?module=empolyees&revision=2007-06-09 + urn:ietf:params:netconf:capability:candidate:1.0 + urn:ietf:params:xml:ns:yang:ietf-inet-types?module=ietf-inet-types&revision=2010-09-24 + urn:ietf:params:netconf:base:1.0 + urn:ietf:params:netconf:base:1.1 + + 1 +