BUG-2459: reuse EXI Reader 12/13312/18
authorRobert Varga <rovarga@cisco.com>
Tue, 2 Dec 2014 15:21:14 +0000 (16:21 +0100)
committerRobert Varga <rovarga@cisco.com>
Thu, 18 Dec 2014 15:58:36 +0000 (16:58 +0100)
The reader performs an internal reset on each invocation of parse(), so
it can be freely reused as long as we guarantee there are no concurrent
invocations. Our decoder class is not Shared, so netty guarantees this.

Change-Id: Icd575988e48ca5252d6f6716f4e08f83b23c99ca
Signed-off-by: Robert Varga <rovarga@cisco.com>
opendaylight/netconf/netconf-client/src/test/java/org/opendaylight/controller/netconf/client/NetconfClientSessionTest.java
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/AbstractNetconfSession.java
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfEXIToMessageDecoder.java
opendaylight/netconf/netconf-netty-util/src/test/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfEXIHandlersTest.java

index 103585c..2a3ecf2 100644 (file)
@@ -55,7 +55,7 @@ public class NetconfClientSessionTest {
 
         NetconfClientSession session = new NetconfClientSession(sessionListener, channel, sessId, caps);
         final NetconfMessageToEXIEncoder exiEncoder = NetconfMessageToEXIEncoder.create(codec);
-        final NetconfEXIToMessageDecoder exiDecoder = new NetconfEXIToMessageDecoder(codec);
+        final NetconfEXIToMessageDecoder exiDecoder = NetconfEXIToMessageDecoder.create(codec);
         session.addExiHandlers(exiDecoder, exiEncoder);
         session.stopExiCommunication();
 
index 13b72bc..a59b1a0 100644 (file)
@@ -132,9 +132,15 @@ public abstract class AbstractNetconfSession<S extends NetconfSession, L extends
             throw new IllegalStateException("Cannot instantiate encoder for options", e);
         }
 
-        final NetconfEXIToMessageDecoder exiDecoder = new NetconfEXIToMessageDecoder(exiCodec);
-        addExiHandlers(exiDecoder, exiEncoder);
+        final NetconfEXIToMessageDecoder exiDecoder;
+        try {
+            exiDecoder = NetconfEXIToMessageDecoder.create(exiCodec);
+        } catch (EXIOptionsException e) {
+            LOG.warn("Failed to instantiate EXI decodeer for {} on session {}", exiCodec, this, e);
+            throw new IllegalStateException("Cannot instantiate encoder for options", e);
+        }
 
+        addExiHandlers(exiDecoder, exiEncoder);
         LOG.debug("Session {} EXI handlers added to pipeline", this);
     }
 
index 77d33e1..db265de 100644 (file)
@@ -33,11 +33,19 @@ public final class NetconfEXIToMessageDecoder extends ByteToMessageDecoder {
 
     private static final Logger LOG = LoggerFactory.getLogger(NetconfEXIToMessageDecoder.class);
     private static final SAXTransformerFactory FACTORY = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
+    /**
+     * This class is not marked as shared, so it can be attached to only a single channel,
+     * which means that {@link #decode(ChannelHandlerContext, ByteBuf, List)}
+     * cannot be invoked concurrently. Hence we can reuse the reader.
+     */
+    private final EXIReader reader;
 
-    private final NetconfEXICodec codec;
+    private NetconfEXIToMessageDecoder(final EXIReader reader) {
+        this.reader = Preconditions.checkNotNull(reader);
+    }
 
-    public NetconfEXIToMessageDecoder(final NetconfEXICodec codec) {
-        this.codec = Preconditions.checkNotNull(codec);
+    public static NetconfEXIToMessageDecoder create(final NetconfEXICodec codec) throws EXIOptionsException {
+        return new NetconfEXIToMessageDecoder(codec.getReader());
     }
 
     @Override
@@ -59,15 +67,15 @@ public final class NetconfEXIToMessageDecoder extends ByteToMessageDecoder {
             LOG.trace("Received to decode: {}", ByteBufUtil.hexDump(in));
         }
 
-        final EXIReader r = codec.getReader();
         final TransformerHandler handler = FACTORY.newTransformerHandler();
-        r.setContentHandler(handler);
+        reader.setContentHandler(handler);
 
         final DOMResult domResult = new DOMResult();
         handler.setResult(domResult);
 
         try (final InputStream is = new ByteBufInputStream(in)) {
-            r.parse(new InputSource(is));
+            // Performs internal reset before doing anything
+            reader.parse(new InputSource(is));
         }
 
         out.add(new NetconfMessage((Document) domResult.getNode()));
index 1972cb1..666da8a 100644 (file)
@@ -41,7 +41,7 @@ public class NetconfEXIHandlersTest {
     public void setUp() throws Exception {
         final NetconfEXICodec codec = new NetconfEXICodec(new EXIOptions());
         netconfMessageToEXIEncoder = NetconfMessageToEXIEncoder.create(codec);
-        netconfEXIToMessageDecoder = new NetconfEXIToMessageDecoder(codec);
+        netconfEXIToMessageDecoder = NetconfEXIToMessageDecoder.create(codec);
 
         msg = new NetconfMessage(XmlUtil.readXmlToDocument(msgAsString));
         this.msgAsExi = msgToExi(msgAsString, codec);