Use nio Channels in OpenAPI read 03/109803/8
authorIvan Hrasko <ivan.hrasko@pantheon.tech>
Tue, 16 Jan 2024 14:49:54 +0000 (15:49 +0100)
committerIvan Hrasko <ivan.hrasko@pantheon.tech>
Mon, 29 Jan 2024 11:38:21 +0000 (12:38 +0100)
Override read(byte[], int, int) method using nio Channels
to speed up retrieval of documentation.

JIRA: NETCONF-1234
Change-Id: I3bfc4110cfe828302a08f86756c4535077fe5c5c
Signed-off-by: Ivan Hrasko <ivan.hrasko@pantheon.tech>
Signed-off-by: Yaroslav Lastivka <yaroslav.lastivka@pantheon.tech>
restconf/restconf-openapi/src/main/java/org/opendaylight/restconf/openapi/impl/ComponentsStream.java
restconf/restconf-openapi/src/main/java/org/opendaylight/restconf/openapi/impl/InfoStream.java
restconf/restconf-openapi/src/main/java/org/opendaylight/restconf/openapi/impl/OpenApiInputStream.java
restconf/restconf-openapi/src/main/java/org/opendaylight/restconf/openapi/impl/OpenApiVersionStream.java
restconf/restconf-openapi/src/main/java/org/opendaylight/restconf/openapi/impl/PathsStream.java
restconf/restconf-openapi/src/main/java/org/opendaylight/restconf/openapi/impl/SchemaStream.java
restconf/restconf-openapi/src/main/java/org/opendaylight/restconf/openapi/impl/SchemasStream.java
restconf/restconf-openapi/src/main/java/org/opendaylight/restconf/openapi/impl/SecuritySchemesStream.java
restconf/restconf-openapi/src/main/java/org/opendaylight/restconf/openapi/impl/SecurityStream.java
restconf/restconf-openapi/src/main/java/org/opendaylight/restconf/openapi/impl/ServersStream.java

index b3cbb31f193d13263145008821c96570f3646ab5..5b97b7b52faa3519cac5c45d048bba1bb2295582 100644 (file)
@@ -14,6 +14,9 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
 import java.nio.charset.StandardCharsets;
 import java.util.Iterator;
 import java.util.Map;
@@ -36,6 +39,7 @@ public final class ComponentsStream extends InputStream {
     private boolean schemasWritten;
     private boolean securityWritten;
     private Reader reader;
+    private ReadableByteChannel channel;
 
     public ComponentsStream(final EffectiveModelContext context, final OpenApiBodyWriter writer,
         final JsonGenerator generator, final ByteArrayOutputStream stream,
@@ -84,6 +88,35 @@ public final class ComponentsStream extends InputStream {
 
     @Override
     public int read(final byte[] array, final int off, final int len) throws IOException {
-        return super.read(array, off, len);
+        if (channel == null) {
+            generator.writeObjectFieldStart("components");
+            generator.flush();
+            channel = Channels.newChannel(new ByteArrayInputStream(stream.toByteArray()));
+            stream.reset();
+        }
+
+        var read = channel.read(ByteBuffer.wrap(array, off, len));
+        while (read == -1) {
+            if (!schemasWritten) {
+                channel = Channels.newChannel(new SchemasStream(context, writer, generator, stream, iterator,
+                    isForSingleModule));
+                read = channel.read(ByteBuffer.wrap(array));
+                schemasWritten = true;
+                continue;
+            }
+            if (!securityWritten) {
+                channel = Channels.newChannel(new SecuritySchemesStream(writer, Map.of(BASIC_AUTH_NAME,
+                    OPEN_API_BASIC_AUTH)));
+                read = channel.read(ByteBuffer.wrap(array, off, len));
+                securityWritten = true;
+                generator.writeEndObject();
+                continue;
+            }
+            generator.flush();
+            channel = Channels.newChannel(new ByteArrayInputStream(stream.toByteArray()));
+            stream.reset();
+            return channel.read(ByteBuffer.wrap(array, off, len));
+        }
+        return read;
     }
 }
index e41129f9f4aed47bb7d28c8601fae5d6575da577..50eac5752a5e4b2dbc142095f3d40511a5cf288a 100644 (file)
@@ -13,6 +13,9 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
 import java.nio.charset.StandardCharsets;
 import org.opendaylight.restconf.openapi.jaxrs.OpenApiBodyWriter;
 import org.opendaylight.restconf.openapi.model.InfoEntity;
@@ -23,6 +26,7 @@ public final class InfoStream extends InputStream {
     private final OpenApiBodyWriter writer;
 
     private Reader reader;
+    private ReadableByteChannel channel;
 
     public InfoStream(final InfoEntity entity, final OpenApiBodyWriter writer) {
         this.entity = entity;
@@ -40,7 +44,10 @@ public final class InfoStream extends InputStream {
 
     @Override
     public int read(final byte[] array, final int off, final int len) throws IOException {
-        return super.read(array, off, len);
+        if (channel == null) {
+            channel = Channels.newChannel(new ByteArrayInputStream(writeNextEntity(entity)));
+        }
+        return channel.read(ByteBuffer.wrap(array, off, len));
     }
 
     private byte[] writeNextEntity(final OpenApiEntity next) throws IOException {
index e39f21d288364e183beac94694f68f5a03ccb76b..6adcc7fa6e41f786bcd0fbd8a2a7be7e5b8c2668 100644 (file)
@@ -16,6 +16,9 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayDeque;
 import java.util.Collection;
@@ -37,6 +40,7 @@ public final class OpenApiInputStream extends InputStream {
     private final Deque<InputStream> stack = new ArrayDeque<>();
 
     private Reader reader;
+    private ReadableByteChannel channel;
 
     private boolean eof;
 
@@ -87,6 +91,30 @@ public final class OpenApiInputStream extends InputStream {
 
     @Override
     public int read(final byte[] array, final int off, final int len) throws IOException {
-        return super.read(array, off, len);
+        if (eof) {
+            return -1;
+        }
+        if (channel == null) {
+            generator.writeStartObject();
+            generator.flush();
+            channel = Channels.newChannel(new ByteArrayInputStream(stream.toByteArray()));
+            stream.reset();
+        }
+
+        var read = channel.read(ByteBuffer.wrap(array, off, len));
+        while (read == -1) {
+            if (stack.isEmpty()) {
+                generator.writeEndObject();
+                generator.flush();
+                channel = Channels.newChannel(new ByteArrayInputStream(stream.toByteArray()));
+                stream.reset();
+                eof = true;
+                return channel.read(ByteBuffer.wrap(array, off, len));
+            }
+            channel = Channels.newChannel(stack.pop());
+            read = channel.read(ByteBuffer.wrap(array, off, len));
+        }
+
+        return read;
     }
 }
index 0553d0e6595d09357d23dc8688e03db5b91665f3..e412e542797dad8dacc901d464d1d814085ce770 100644 (file)
@@ -13,6 +13,9 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
 import java.nio.charset.StandardCharsets;
 import org.opendaylight.restconf.openapi.jaxrs.OpenApiBodyWriter;
 import org.opendaylight.restconf.openapi.model.OpenApiEntity;
@@ -23,6 +26,7 @@ public final class OpenApiVersionStream extends InputStream {
     private final OpenApiBodyWriter writer;
 
     private Reader reader;
+    private ReadableByteChannel channel;
 
     public OpenApiVersionStream(final OpenApiVersionEntity entity, final OpenApiBodyWriter writer) {
         this.entity = entity;
@@ -40,7 +44,10 @@ public final class OpenApiVersionStream extends InputStream {
 
     @Override
     public int read(final byte[] array, final int off, final int len) throws IOException {
-        return super.read(array, off, len);
+        if (channel == null) {
+            channel = Channels.newChannel(new ByteArrayInputStream(writeNextEntity(entity)));
+        }
+        return channel.read(ByteBuffer.wrap(array, off, len));
     }
 
     private byte[] writeNextEntity(final OpenApiEntity next) throws IOException {
index 2c72fc672e1e27c04054dbd47961b5dbf752b3ad..01ed0346e8affac94a571b8e2422e4a0b972d67e 100644 (file)
@@ -16,6 +16,9 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
@@ -70,6 +73,7 @@ public final class PathsStream extends InputStream {
     private boolean hasRootPostLink;
     private boolean hasAddedDataStore;
     private Reader reader;
+    private ReadableByteChannel channel;
 
     public PathsStream(final EffectiveModelContext schemaContext, final OpenApiBodyWriter writer,
             final String deviceName, final String urlPrefix, final boolean isForSingleModule,
@@ -98,7 +102,10 @@ public final class PathsStream extends InputStream {
 
     @Override
     public int read(final byte[] array, final int off, final int len) throws IOException {
-        return super.read(array, off, len);
+        if (channel == null) {
+            channel = Channels.newChannel(new ByteArrayInputStream(writeNextEntity(new PathsEntity(toPaths()))));
+        }
+        return channel.read(ByteBuffer.wrap(array, off, len));
     }
 
     private byte[] writeNextEntity(final OpenApiEntity next) throws IOException {
index 6036b7e48ca6f7a59da0d8a420264cd4a6fb5443..dc75c6995030f56bd04cf4d15f14396b4fb797d4 100644 (file)
@@ -13,6 +13,9 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
 import java.nio.charset.StandardCharsets;
 import java.util.Deque;
 import org.opendaylight.restconf.openapi.jaxrs.OpenApiBodyWriter;
@@ -24,6 +27,7 @@ public final class SchemaStream extends InputStream {
     private final OpenApiBodyWriter writer;
 
     private Reader reader;
+    private ReadableByteChannel channel;
 
     public SchemaStream(final Deque<SchemaEntity> schemas, final OpenApiBodyWriter writer) {
         this.stack = schemas;
@@ -55,7 +59,23 @@ public final class SchemaStream extends InputStream {
 
     @Override
     public int read(final byte[] array, final int off, final int len) throws IOException {
-        return super.read(array, off, len);
+        if (channel == null) {
+            if (stack.isEmpty()) {
+                return -1;
+            }
+            channel = Channels.newChannel(new ByteArrayInputStream(writeNextEntity(stack.pop())));
+        }
+
+        var read = channel.read(ByteBuffer.wrap(array, off, len));
+        while (read == -1) {
+            if (stack.isEmpty()) {
+                return -1;
+            }
+            channel = Channels.newChannel(new ByteArrayInputStream(writeNextEntity(stack.pop())));
+            read = channel.read(ByteBuffer.wrap(array, off, len));
+        }
+
+        return read;
     }
 
     private byte[] writeNextEntity(final OpenApiEntity entity) throws IOException {
index c002e6401034bbbecfc23bdead8ed2a4ba42af1d..fa4e8280d461eb0bf2c899010c3fe77ea01b326c 100644 (file)
@@ -15,6 +15,9 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
@@ -46,6 +49,7 @@ public final class SchemasStream extends InputStream {
     private final boolean isForSingleModule;
 
     private Reader reader;
+    private ReadableByteChannel channel;
     private boolean schemesWritten;
 
     public SchemasStream(final EffectiveModelContext context, final OpenApiBodyWriter writer,
@@ -95,7 +99,33 @@ public final class SchemasStream extends InputStream {
 
     @Override
     public int read(final byte[] array, final int off, final int len) throws IOException {
-        return super.read(array, off, len);
+        if (channel == null) {
+            generator.writeObjectFieldStart("schemas");
+            generator.flush();
+            channel = Channels.newChannel(new ByteArrayInputStream(stream.toByteArray()));
+            stream.reset();
+        }
+
+        var read = channel.read(ByteBuffer.wrap(array, off, len));
+        while (read == -1) {
+            if (iterator.hasNext()) {
+                channel = Channels.newChannel(new SchemaStream(toComponents(iterator.next(), context,
+                    isForSingleModule), writer));
+                read = channel.read(ByteBuffer.wrap(array, off, len));
+                continue;
+            }
+            if (!schemesWritten) {
+                generator.writeEndObject();
+                schemesWritten = true;
+                continue;
+            }
+            generator.flush();
+            channel = Channels.newChannel(new ByteArrayInputStream(stream.toByteArray()));
+            stream.reset();
+            return channel.read(ByteBuffer.wrap(array, off, len));
+        }
+
+        return read;
     }
 
     private static Deque<SchemaEntity> toComponents(final Module module, final EffectiveModelContext context,
index 73e40c9079e3096fe2667ded75e0c011466d161f..5c7e53b5b2422784290fed65deec78131a23623d 100644 (file)
@@ -13,6 +13,9 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
 import java.nio.charset.StandardCharsets;
 import java.util.Map;
 import org.opendaylight.restconf.openapi.jaxrs.OpenApiBodyWriter;
@@ -25,6 +28,7 @@ public final class SecuritySchemesStream extends InputStream {
     private final SecuritySchemesEntity securitySchemesEntity;
 
     private Reader reader;
+    private ReadableByteChannel channel;
 
     public SecuritySchemesStream(final OpenApiBodyWriter writer,
             final Map<String, SecuritySchemeObject> securitySchemes) {
@@ -44,7 +48,11 @@ public final class SecuritySchemesStream extends InputStream {
 
     @Override
     public int read(final byte[] array, final int off, final int len) throws IOException {
-        return super.read(array, off, len);
+        if (channel == null) {
+            final var stream = new ByteArrayInputStream(writeNextEntity(securitySchemesEntity));
+            channel = Channels.newChannel(stream);
+        }
+        return channel.read(ByteBuffer.wrap(array, off, len));
     }
 
     private byte[] writeNextEntity(final OpenApiEntity next) throws IOException {
index 0cea95ff8442d1ea3fa3d6da8753415b963816fe..f3d16505fa145f2ee845ff35e270cc50baf50267 100644 (file)
@@ -13,6 +13,9 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
 import java.nio.charset.StandardCharsets;
 import org.opendaylight.restconf.openapi.jaxrs.OpenApiBodyWriter;
 import org.opendaylight.restconf.openapi.model.OpenApiEntity;
@@ -23,6 +26,7 @@ public final class SecurityStream extends InputStream {
     private final SecurityEntity entity;
 
     private Reader reader;
+    private ReadableByteChannel channel;
 
     public SecurityStream(final OpenApiBodyWriter writer, final SecurityEntity entity) {
         this.writer = writer;
@@ -40,7 +44,10 @@ public final class SecurityStream extends InputStream {
 
     @Override
     public int read(final byte[] array, final int off, final int len) throws IOException {
-        return super.read(array, off, len);
+        if (channel == null) {
+            channel = Channels.newChannel(new ByteArrayInputStream(writeNextEntity(entity)));
+        }
+        return channel.read(ByteBuffer.wrap(array, off, len));
     }
 
     private byte[] writeNextEntity(final OpenApiEntity next) throws IOException {
index db8194a862e8379d68398c55cc2f0f63d1035ed8..bff54b2e5481356ec07bb01969eca5d3db739637 100644 (file)
@@ -13,6 +13,9 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
 import java.nio.charset.StandardCharsets;
 import org.opendaylight.restconf.openapi.jaxrs.OpenApiBodyWriter;
 import org.opendaylight.restconf.openapi.model.OpenApiEntity;
@@ -23,6 +26,7 @@ public final class ServersStream extends InputStream {
     private final OpenApiBodyWriter writer;
 
     private Reader reader;
+    private ReadableByteChannel channel;
 
     public ServersStream(final ServersEntity entity, final OpenApiBodyWriter writer) {
         this.entity = entity;
@@ -40,7 +44,10 @@ public final class ServersStream extends InputStream {
 
     @Override
     public int read(final byte[] array, final int off, final int len) throws IOException {
-        return super.read(array, off, len);
+        if (channel == null) {
+            channel = Channels.newChannel(new ByteArrayInputStream(writeNextEntity(entity)));
+        }
+        return channel.read(ByteBuffer.wrap(array, off, len));
     }
 
     private byte[] writeNextEntity(final OpenApiEntity next) throws IOException {