From 69e914b3889a82fa2f7daa8d55e1aa0de23fb454 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Tue, 28 May 2019 15:28:55 +0200 Subject: [PATCH] Separate lazy-versioned NormalizedNodeDataInput NormalizedNodeInputStreamReader is really only one implementation of the streaming format, which happens to be bound to LITHIUM_VERSION. This effectively means NormalizedNodeInputOutput can give out either a version-bound reader or an unbound reader -- which we facilitate by creating VersionedNormalizedNodeDataInput which is a simple forwarder with lazily-initialized delegate. Since this increases the number of (NormalizedNode)DataInput implementations, we share as much code as possible through the use of forwarding implementations. JIRA: CONTROLLER-1898 Change-Id: I28713346730ed5bf7f912bf8afa5d8722b202035 Signed-off-by: Robert Varga --- .../utils/stream/ForwardingDataInput.java | 96 +++++++++++++ .../ForwardingNormalizedNodeDataInput.java | 41 ++++++ .../InvalidNormalizedNodeStreamException.java | 6 +- .../stream/NormalizedNodeInputOutput.java | 15 +-- .../NormalizedNodeInputStreamReader.java | 126 ++---------------- .../VersionedNormalizedNodeDataInput.java | 65 +++++++++ 6 files changed, 218 insertions(+), 131 deletions(-) create mode 100644 opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/ForwardingDataInput.java create mode 100644 opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/ForwardingNormalizedNodeDataInput.java create mode 100644 opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/VersionedNormalizedNodeDataInput.java diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/ForwardingDataInput.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/ForwardingDataInput.java new file mode 100644 index 0000000000..0ec7fbeb4e --- /dev/null +++ b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/ForwardingDataInput.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2019 PANTHEON.tech, s.r.o. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.cluster.datastore.node.utils.stream; + +import java.io.DataInput; +import java.io.IOException; +import org.eclipse.jdt.annotation.NonNull; + +// Not a ForwardingObject because delegate() can legally throw and we do not want redirect toString() +abstract class ForwardingDataInput implements DataInput { + + abstract @NonNull DataInput delegate() throws IOException; + + @Override + @SuppressWarnings("checkstyle:parameterName") + public final void readFully(final byte[] b) throws IOException { + delegate().readFully(b); + } + + @Override + @SuppressWarnings("checkstyle:parameterName") + public final void readFully(final byte[] b, final int off, final int len) throws IOException { + delegate().readFully(b, off, len); + } + + @Override + @SuppressWarnings("checkstyle:parameterName") + public final int skipBytes(final int n) throws IOException { + return delegate().skipBytes(n); + } + + @Override + public final boolean readBoolean() throws IOException { + return delegate().readBoolean(); + } + + @Override + public final byte readByte() throws IOException { + return delegate().readByte(); + } + + @Override + public final int readUnsignedByte() throws IOException { + return delegate().readUnsignedByte(); + } + + @Override + public final short readShort() throws IOException { + return delegate().readShort(); + } + + @Override + public final int readUnsignedShort() throws IOException { + return delegate().readUnsignedShort(); + } + + @Override + public final char readChar() throws IOException { + return delegate().readChar(); + } + + @Override + public final int readInt() throws IOException { + return delegate().readInt(); + } + + @Override + public final long readLong() throws IOException { + return delegate().readLong(); + } + + @Override + public final float readFloat() throws IOException { + return delegate().readFloat(); + } + + @Override + public final double readDouble() throws IOException { + return delegate().readDouble(); + } + + @Override + public final String readLine() throws IOException { + return delegate().readLine(); + } + + @Override + public final String readUTF() throws IOException { + return delegate().readUTF(); + } +} diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/ForwardingNormalizedNodeDataInput.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/ForwardingNormalizedNodeDataInput.java new file mode 100644 index 0000000000..590a8b0205 --- /dev/null +++ b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/ForwardingNormalizedNodeDataInput.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2019 PANTHEON.tech, s.r.o. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.cluster.datastore.node.utils.stream; + +import java.io.IOException; +import org.eclipse.jdt.annotation.NonNull; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.model.api.SchemaPath; + +abstract class ForwardingNormalizedNodeDataInput extends ForwardingDataInput implements NormalizedNodeDataInput { + + @Override + abstract @NonNull NormalizedNodeDataInput delegate() throws IOException; + + @Override + public final NormalizedNode readNormalizedNode() throws IOException { + return delegate().readNormalizedNode(); + } + + @Override + public final YangInstanceIdentifier readYangInstanceIdentifier() throws IOException { + return delegate().readYangInstanceIdentifier(); + } + + @Override + public final PathArgument readPathArgument() throws IOException { + return delegate().readPathArgument(); + } + + @Override + public final SchemaPath readSchemaPath() throws IOException { + return delegate().readSchemaPath(); + } +} diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/InvalidNormalizedNodeStreamException.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/InvalidNormalizedNodeStreamException.java index da60496a22..2099e3d5a6 100644 --- a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/InvalidNormalizedNodeStreamException.java +++ b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/InvalidNormalizedNodeStreamException.java @@ -18,7 +18,11 @@ import java.io.IOException; public class InvalidNormalizedNodeStreamException extends IOException { private static final long serialVersionUID = 1L; - public InvalidNormalizedNodeStreamException(String message) { + public InvalidNormalizedNodeStreamException(final String message) { super(message); } + + public InvalidNormalizedNodeStreamException(final String message, final Throwable cause) { + super(message, cause); + } } diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/NormalizedNodeInputOutput.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/NormalizedNodeInputOutput.java index 5ad195a9b7..f46a9e2a5b 100644 --- a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/NormalizedNodeInputOutput.java +++ b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/NormalizedNodeInputOutput.java @@ -28,18 +28,7 @@ public final class NormalizedNodeInputOutput { * @throws IOException if an error occurs reading from the input */ public static NormalizedNodeDataInput newDataInput(final @NonNull DataInput input) throws IOException { - final byte marker = input.readByte(); - if (marker != TokenTypes.SIGNATURE_MARKER) { - throw new InvalidNormalizedNodeStreamException(String.format("Invalid signature marker: %d", marker)); - } - - final short version = input.readShort(); - switch (version) { - case TokenTypes.LITHIUM_VERSION: - return new NormalizedNodeInputStreamReader(input, true); - default: - throw new InvalidNormalizedNodeStreamException(String.format("Unhandled stream version %s", version)); - } + return new VersionedNormalizedNodeDataInput(input).delegate(); } /** @@ -50,7 +39,7 @@ public final class NormalizedNodeInputOutput { * @return a new {@link NormalizedNodeDataInput} instance */ public static NormalizedNodeDataInput newDataInputWithoutValidation(final @NonNull DataInput input) { - return new NormalizedNodeInputStreamReader(input, false); + return new VersionedNormalizedNodeDataInput(input); } /** diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/NormalizedNodeInputStreamReader.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/NormalizedNodeInputStreamReader.java index 9b2ce2b64d..239cd7cb57 100755 --- a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/NormalizedNodeInputStreamReader.java +++ b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/NormalizedNodeInputStreamReader.java @@ -25,6 +25,7 @@ import java.util.Set; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.dom.DOMSource; +import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.controller.cluster.datastore.node.utils.QNameFactory; import org.opendaylight.yangtools.util.ImmutableOffsetMapTemplate; import org.opendaylight.yangtools.yang.common.Empty; @@ -54,11 +55,11 @@ import org.xml.sax.SAXException; * nodes. This process goes in recursive manner, where each NodeTypes object signifies the start of the object, except * END_NODE. If a node can have children, then that node's end is calculated based on appearance of END_NODE. */ -public class NormalizedNodeInputStreamReader implements NormalizedNodeDataInput { +public class NormalizedNodeInputStreamReader extends ForwardingDataInput implements NormalizedNodeDataInput { private static final Logger LOG = LoggerFactory.getLogger(NormalizedNodeInputStreamReader.class); - private final DataInput input; + private final @NonNull DataInput input; private final List codedStringMap = new ArrayList<>(); @@ -69,34 +70,18 @@ public class NormalizedNodeInputStreamReader implements NormalizedNodeDataInput @SuppressWarnings("rawtypes") private NormalizedNodeBuilder> leafSetEntryBuilder; - private boolean readSignatureMarker = true; - - NormalizedNodeInputStreamReader(final DataInput input, final boolean versionChecked) { + NormalizedNodeInputStreamReader(final DataInput input) { this.input = requireNonNull(input); - readSignatureMarker = !versionChecked; } @Override - public NormalizedNode readNormalizedNode() throws IOException { - readSignatureMarkerAndVersionIfNeeded(); - return readNormalizedNodeInternal(); + final DataInput delegate() { + return input; } - private void readSignatureMarkerAndVersionIfNeeded() throws IOException { - if (readSignatureMarker) { - readSignatureMarker = false; - - final byte marker = input.readByte(); - if (marker != TokenTypes.SIGNATURE_MARKER) { - throw new InvalidNormalizedNodeStreamException(String.format( - "Invalid signature marker: %d", marker)); - } - - final short version = input.readShort(); - if (version != TokenTypes.LITHIUM_VERSION) { - throw new InvalidNormalizedNodeStreamException(String.format("Unhandled stream version %s", version)); - } - } + @Override + public NormalizedNode readNormalizedNode() throws IOException { + return readNormalizedNodeInternal(); } private NormalizedNode readNormalizedNodeInternal() throws IOException { @@ -356,8 +341,6 @@ public class NormalizedNodeInputStreamReader implements NormalizedNodeDataInput @Override public SchemaPath readSchemaPath() throws IOException { - readSignatureMarkerAndVersionIfNeeded(); - final boolean absolute = input.readBoolean(); final int size = input.readInt(); @@ -370,7 +353,6 @@ public class NormalizedNodeInputStreamReader implements NormalizedNodeDataInput @Override public YangInstanceIdentifier readYangInstanceIdentifier() throws IOException { - readSignatureMarkerAndVersionIfNeeded(); return readYangInstanceIdentifierInternal(); } @@ -442,94 +424,4 @@ public class NormalizedNodeInputStreamReader implements NormalizedNodeDataInput } return builder; } - - @Override - public void readFully(final byte[] value) throws IOException { - readSignatureMarkerAndVersionIfNeeded(); - input.readFully(value); - } - - @Override - public void readFully(final byte[] str, final int off, final int len) throws IOException { - readSignatureMarkerAndVersionIfNeeded(); - input.readFully(str, off, len); - } - - @Override - public int skipBytes(final int num) throws IOException { - readSignatureMarkerAndVersionIfNeeded(); - return input.skipBytes(num); - } - - @Override - public boolean readBoolean() throws IOException { - readSignatureMarkerAndVersionIfNeeded(); - return input.readBoolean(); - } - - @Override - public byte readByte() throws IOException { - readSignatureMarkerAndVersionIfNeeded(); - return input.readByte(); - } - - @Override - public int readUnsignedByte() throws IOException { - readSignatureMarkerAndVersionIfNeeded(); - return input.readUnsignedByte(); - } - - @Override - public short readShort() throws IOException { - readSignatureMarkerAndVersionIfNeeded(); - return input.readShort(); - } - - @Override - public int readUnsignedShort() throws IOException { - readSignatureMarkerAndVersionIfNeeded(); - return input.readUnsignedShort(); - } - - @Override - public char readChar() throws IOException { - readSignatureMarkerAndVersionIfNeeded(); - return input.readChar(); - } - - @Override - public int readInt() throws IOException { - readSignatureMarkerAndVersionIfNeeded(); - return input.readInt(); - } - - @Override - public long readLong() throws IOException { - readSignatureMarkerAndVersionIfNeeded(); - return input.readLong(); - } - - @Override - public float readFloat() throws IOException { - readSignatureMarkerAndVersionIfNeeded(); - return input.readFloat(); - } - - @Override - public double readDouble() throws IOException { - readSignatureMarkerAndVersionIfNeeded(); - return input.readDouble(); - } - - @Override - public String readLine() throws IOException { - readSignatureMarkerAndVersionIfNeeded(); - return input.readLine(); - } - - @Override - public String readUTF() throws IOException { - readSignatureMarkerAndVersionIfNeeded(); - return input.readUTF(); - } } diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/VersionedNormalizedNodeDataInput.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/VersionedNormalizedNodeDataInput.java new file mode 100644 index 0000000000..860fe39874 --- /dev/null +++ b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/VersionedNormalizedNodeDataInput.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2019 PANTHEON.tech, s.r.o. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.cluster.datastore.node.utils.stream; + +import static java.util.Objects.requireNonNull; + +import java.io.DataInput; +import java.io.IOException; + +final class VersionedNormalizedNodeDataInput extends ForwardingNormalizedNodeDataInput { + private DataInput input; + private NormalizedNodeDataInput delegate; + + VersionedNormalizedNodeDataInput(final DataInput input) { + this.input = requireNonNull(input); + } + + @Override + NormalizedNodeDataInput delegate() throws IOException { + if (delegate != null) { + return delegate; + } + + final byte marker = input.readByte(); + if (marker != TokenTypes.SIGNATURE_MARKER) { + throw defunct("Invalid signature marker: %d", marker); + } + + final short version = input.readShort(); + final NormalizedNodeDataInput ret; + switch (version) { + case TokenTypes.LITHIUM_VERSION: + ret = new NormalizedNodeInputStreamReader(input); + break; + default: + throw defunct("Unhandled stream version %s", version); + } + + setDelegate(ret); + return ret; + } + + private InvalidNormalizedNodeStreamException defunct(final String format, final Object... args) { + final InvalidNormalizedNodeStreamException ret = new InvalidNormalizedNodeStreamException( + String.format(format, args)); + // Make sure the stream is not touched + setDelegate(new ForwardingNormalizedNodeDataInput() { + @Override + NormalizedNodeDataInput delegate() throws IOException { + throw new InvalidNormalizedNodeStreamException("Stream is not usable", ret); + } + }); + return ret; + } + + private void setDelegate(final NormalizedNodeDataInput delegate) { + this.delegate = requireNonNull(delegate); + input = null; + } +} -- 2.36.6