From: Robert Varga Date: Mon, 23 May 2016 14:44:35 +0000 (+0200) Subject: BUG-5280: move DataTreeCandidate serialization to its own class X-Git-Tag: release/boron~136 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=175f38490b56c4b4e0ec356b17b91f887b295da4 BUG-5280: move DataTreeCandidate serialization to its own class This is a useful utility, which can be reused across multiple objects. Split it out into its own class. Change-Id: Ib21abf0ae42e3f70f44b3214039c0f26464bbc3e Signed-off-by: Robert Varga --- diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DataTreeCandidatePayload.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DataTreeCandidatePayload.java index 21083618f0..8da70c2e29 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DataTreeCandidatePayload.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DataTreeCandidatePayload.java @@ -8,40 +8,21 @@ package org.opendaylight.controller.cluster.datastore; import com.google.common.base.Preconditions; -import com.google.common.io.ByteArrayDataInput; import com.google.common.io.ByteArrayDataOutput; import com.google.common.io.ByteStreams; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import org.opendaylight.controller.cluster.datastore.node.utils.stream.NormalizedNodeDataInput; -import org.opendaylight.controller.cluster.datastore.node.utils.stream.NormalizedNodeDataOutput; -import org.opendaylight.controller.cluster.datastore.node.utils.stream.NormalizedNodeInputStreamReader; -import org.opendaylight.controller.cluster.datastore.node.utils.stream.NormalizedNodeInputOutput; +import org.opendaylight.controller.cluster.datastore.persisted.DataTreeCandidateInputOutput; import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload; -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.tree.DataTreeCandidate; -import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode; -import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNodes; -import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidates; -import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; final class DataTreeCandidatePayload extends Payload implements Externalizable { private static final Logger LOG = LoggerFactory.getLogger(DataTreeCandidatePayload.class); private static final long serialVersionUID = 1L; - private static final byte DELETE = 0; - private static final byte SUBTREE_MODIFIED = 1; - private static final byte UNMODIFIED = 2; - private static final byte WRITE = 3; - private static final byte APPEARED = 4; - private static final byte DISAPPEARED = 5; private transient byte[] serialized; @@ -53,81 +34,10 @@ final class DataTreeCandidatePayload extends Payload implements Externalizable { this.serialized = Preconditions.checkNotNull(serialized); } - private static void writeChildren(final NormalizedNodeDataOutput out, - final Collection children) throws IOException { - out.writeInt(children.size()); - for (DataTreeCandidateNode child : children) { - writeNode(out, child); - } - } - - private static void writeNode(final NormalizedNodeDataOutput out, final DataTreeCandidateNode node) - throws IOException { - switch (node.getModificationType()) { - case APPEARED: - out.writeByte(APPEARED); - out.writePathArgument(node.getIdentifier()); - writeChildren(out, node.getChildNodes()); - break; - case DELETE: - out.writeByte(DELETE); - out.writePathArgument(node.getIdentifier()); - break; - case DISAPPEARED: - out.writeByte(DISAPPEARED); - out.writePathArgument(node.getIdentifier()); - writeChildren(out, node.getChildNodes()); - break; - case SUBTREE_MODIFIED: - out.writeByte(SUBTREE_MODIFIED); - out.writePathArgument(node.getIdentifier()); - writeChildren(out, node.getChildNodes()); - break; - case WRITE: - out.writeByte(WRITE); - out.writeNormalizedNode(node.getDataAfter().get()); - break; - case UNMODIFIED: - out.writeByte(UNMODIFIED); - break; - default: - throw new IllegalArgumentException("Unhandled node type " + node.getModificationType()); - } - } - static DataTreeCandidatePayload create(final DataTreeCandidate candidate) { final ByteArrayDataOutput out = ByteStreams.newDataOutput(); - try (final NormalizedNodeDataOutput writer = NormalizedNodeInputOutput.newDataOutput(out)) { - writer.writeYangInstanceIdentifier(candidate.getRootPath()); - - final DataTreeCandidateNode node = candidate.getRootNode(); - switch (node.getModificationType()) { - case APPEARED: - writer.writeByte(APPEARED); - writeChildren(writer, node.getChildNodes()); - break; - case DELETE: - writer.writeByte(DELETE); - break; - case DISAPPEARED: - writer.writeByte(DISAPPEARED); - writeChildren(writer, node.getChildNodes()); - break; - case SUBTREE_MODIFIED: - writer.writeByte(SUBTREE_MODIFIED); - writeChildren(writer, node.getChildNodes()); - break; - case UNMODIFIED: - writer.writeByte(UNMODIFIED); - break; - case WRITE: - writer.writeByte(WRITE); - writer.writeNormalizedNode(node.getDataAfter().get()); - break; - default: - throw new IllegalArgumentException("Unhandled node type " + node.getModificationType()); - } - + try { + DataTreeCandidateInputOutput.writeDataTreeCandidate(out, candidate); } catch (IOException e) { throw new IllegalArgumentException(String.format("Failed to serialize candidate %s", candidate), e); } @@ -135,80 +45,9 @@ final class DataTreeCandidatePayload extends Payload implements Externalizable { return new DataTreeCandidatePayload(out.toByteArray()); } - private static Collection readChildren(final NormalizedNodeDataInput in) throws IOException { - final int size = in.readInt(); - if (size != 0) { - final Collection ret = new ArrayList<>(size); - for (int i = 0; i < size; ++i) { - final DataTreeCandidateNode child = readNode(in); - if (child != null) { - ret.add(child); - } - } - return ret; - } else { - return Collections.emptyList(); - } - } - - private static DataTreeCandidateNode readModifiedNode(final ModificationType type, - final NormalizedNodeDataInput in) throws IOException { - - final PathArgument identifier = in.readPathArgument(); - final Collection children = readChildren(in); - if (children.isEmpty()) { - LOG.debug("Modified node {} does not have any children, not instantiating it", identifier); - return null; - } else { - return ModifiedDataTreeCandidateNode.create(identifier, type, children); - } - } - - private static DataTreeCandidateNode readNode(final NormalizedNodeDataInput in) throws IOException { - final byte type = in.readByte(); - switch (type) { - case APPEARED: - return readModifiedNode(ModificationType.APPEARED, in); - case DELETE: - return DeletedDataTreeCandidateNode.create(in.readPathArgument()); - case DISAPPEARED: - return readModifiedNode(ModificationType.DISAPPEARED, in); - case SUBTREE_MODIFIED: - return readModifiedNode(ModificationType.SUBTREE_MODIFIED, in); - case UNMODIFIED: - return null; - case WRITE: - return DataTreeCandidateNodes.fromNormalizedNode(in.readNormalizedNode()); - default: - throw new IllegalArgumentException("Unhandled node type " + type); - } - } - - private static DataTreeCandidate parseCandidate(final ByteArrayDataInput in) throws IOException { - final NormalizedNodeDataInput reader = new NormalizedNodeInputStreamReader(in); - final YangInstanceIdentifier rootPath = reader.readYangInstanceIdentifier(); - final byte type = reader.readByte(); - - final DataTreeCandidateNode rootNode; - switch (type) { - case DELETE: - rootNode = DeletedDataTreeCandidateNode.create(); - break; - case SUBTREE_MODIFIED: - rootNode = ModifiedDataTreeCandidateNode.create(readChildren(reader)); - break; - case WRITE: - rootNode = DataTreeCandidateNodes.fromNormalizedNode(reader.readNormalizedNode()); - break; - default: - throw new IllegalArgumentException("Unhandled node type " + type); - } - - return DataTreeCandidates.newDataTreeCandidate(rootPath, rootNode); - } DataTreeCandidate getCandidate() throws IOException { - return parseCandidate(ByteStreams.newDataInput(serialized)); + return DataTreeCandidateInputOutput.readDataTreeCandidate(ByteStreams.newDataInput(serialized)); } @Override @@ -217,14 +56,14 @@ final class DataTreeCandidatePayload extends Payload implements Externalizable { } @Override - public void writeExternal(ObjectOutput out) throws IOException { + public void writeExternal(final ObjectOutput out) throws IOException { out.writeByte((byte)serialVersionUID); out.writeInt(serialized.length); out.write(serialized); } @Override - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException { final long version = in.readByte(); Preconditions.checkArgument(version == serialVersionUID, "Unsupported serialization version %s", version); diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/AbstractDataTreeCandidateNode.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/persisted/AbstractDataTreeCandidateNode.java similarity index 97% rename from opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/AbstractDataTreeCandidateNode.java rename to opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/persisted/AbstractDataTreeCandidateNode.java index c3940e5256..85c5403b70 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/AbstractDataTreeCandidateNode.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/persisted/AbstractDataTreeCandidateNode.java @@ -5,7 +5,7 @@ * 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; +package org.opendaylight.controller.cluster.datastore.persisted; import com.google.common.base.Optional; import com.google.common.base.Preconditions; diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/persisted/DataTreeCandidateInputOutput.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/persisted/DataTreeCandidateInputOutput.java new file mode 100644 index 0000000000..9d0153f6b7 --- /dev/null +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/persisted/DataTreeCandidateInputOutput.java @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. 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.persisted; + +import com.google.common.annotations.Beta; +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import org.opendaylight.controller.cluster.datastore.node.utils.stream.NormalizedNodeDataInput; +import org.opendaylight.controller.cluster.datastore.node.utils.stream.NormalizedNodeDataOutput; +import org.opendaylight.controller.cluster.datastore.node.utils.stream.NormalizedNodeInputOutput; +import org.opendaylight.controller.cluster.datastore.node.utils.stream.NormalizedNodeInputStreamReader; +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.tree.DataTreeCandidate; +import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode; +import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNodes; +import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidates; +import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Utility serialization/deserialization for {@link DataTreeCandidate}. Note that this utility does not maintain + * before-image information across serialization. + * + * @author Robert Varga + */ +@Beta +public final class DataTreeCandidateInputOutput { + private static final Logger LOG = LoggerFactory.getLogger(DataTreeCandidateInputOutput.class); + private static final byte DELETE = 0; + private static final byte SUBTREE_MODIFIED = 1; + private static final byte UNMODIFIED = 2; + private static final byte WRITE = 3; + private static final byte APPEARED = 4; + private static final byte DISAPPEARED = 5; + + private DataTreeCandidateInputOutput() { + throw new UnsupportedOperationException(); + } + + private static DataTreeCandidateNode readModifiedNode(final ModificationType type, + final NormalizedNodeDataInput in) throws IOException { + + final PathArgument identifier = in.readPathArgument(); + final Collection children = readChildren(in); + if (children.isEmpty()) { + LOG.debug("Modified node {} does not have any children, not instantiating it", identifier); + return null; + } else { + return ModifiedDataTreeCandidateNode.create(identifier, type, children); + } + } + + private static Collection readChildren(final NormalizedNodeDataInput in) throws IOException { + final int size = in.readInt(); + if (size != 0) { + final Collection ret = new ArrayList<>(size); + for (int i = 0; i < size; ++i) { + final DataTreeCandidateNode child = readNode(in); + if (child != null) { + ret.add(child); + } + } + return ret; + } else { + return Collections.emptyList(); + } + } + + private static DataTreeCandidateNode readNode(final NormalizedNodeDataInput in) throws IOException { + final byte type = in.readByte(); + switch (type) { + case APPEARED: + return readModifiedNode(ModificationType.APPEARED, in); + case DELETE: + return DeletedDataTreeCandidateNode.create(in.readPathArgument()); + case DISAPPEARED: + return readModifiedNode(ModificationType.DISAPPEARED, in); + case SUBTREE_MODIFIED: + return readModifiedNode(ModificationType.SUBTREE_MODIFIED, in); + case UNMODIFIED: + return null; + case WRITE: + return DataTreeCandidateNodes.fromNormalizedNode(in.readNormalizedNode()); + default: + throw new IllegalArgumentException("Unhandled node type " + type); + } + } + + public static DataTreeCandidate readDataTreeCandidate(final DataInput in) throws IOException { + final NormalizedNodeDataInput reader = new NormalizedNodeInputStreamReader(in); + final YangInstanceIdentifier rootPath = reader.readYangInstanceIdentifier(); + final byte type = reader.readByte(); + + final DataTreeCandidateNode rootNode; + switch (type) { + case DELETE: + rootNode = DeletedDataTreeCandidateNode.create(); + break; + case SUBTREE_MODIFIED: + rootNode = ModifiedDataTreeCandidateNode.create(readChildren(reader)); + break; + case WRITE: + rootNode = DataTreeCandidateNodes.fromNormalizedNode(reader.readNormalizedNode()); + break; + default: + throw new IllegalArgumentException("Unhandled node type " + type); + } + + return DataTreeCandidates.newDataTreeCandidate(rootPath, rootNode); + } + + + private static void writeChildren(final NormalizedNodeDataOutput out, + final Collection children) throws IOException { + out.writeInt(children.size()); + for (DataTreeCandidateNode child : children) { + writeNode(out, child); + } + } + + private static void writeNode(final NormalizedNodeDataOutput out, final DataTreeCandidateNode node) + throws IOException { + switch (node.getModificationType()) { + case APPEARED: + out.writeByte(APPEARED); + out.writePathArgument(node.getIdentifier()); + writeChildren(out, node.getChildNodes()); + break; + case DELETE: + out.writeByte(DELETE); + out.writePathArgument(node.getIdentifier()); + break; + case DISAPPEARED: + out.writeByte(DISAPPEARED); + out.writePathArgument(node.getIdentifier()); + writeChildren(out, node.getChildNodes()); + break; + case SUBTREE_MODIFIED: + out.writeByte(SUBTREE_MODIFIED); + out.writePathArgument(node.getIdentifier()); + writeChildren(out, node.getChildNodes()); + break; + case WRITE: + out.writeByte(WRITE); + out.writeNormalizedNode(node.getDataAfter().get()); + break; + case UNMODIFIED: + out.writeByte(UNMODIFIED); + break; + default: + throw new IllegalArgumentException("Unhandled node type " + node.getModificationType()); + } + } + + public static void writeDataTreeCandidate(final DataOutput out, DataTreeCandidate candidate) throws IOException { + try (final NormalizedNodeDataOutput writer = NormalizedNodeInputOutput.newDataOutput(out)) { + writer.writeYangInstanceIdentifier(candidate.getRootPath()); + + final DataTreeCandidateNode node = candidate.getRootNode(); + switch (node.getModificationType()) { + case APPEARED: + writer.writeByte(APPEARED); + writeChildren(writer, node.getChildNodes()); + break; + case DELETE: + writer.writeByte(DELETE); + break; + case DISAPPEARED: + writer.writeByte(DISAPPEARED); + writeChildren(writer, node.getChildNodes()); + break; + case SUBTREE_MODIFIED: + writer.writeByte(SUBTREE_MODIFIED); + writeChildren(writer, node.getChildNodes()); + break; + case UNMODIFIED: + writer.writeByte(UNMODIFIED); + break; + case WRITE: + writer.writeByte(WRITE); + writer.writeNormalizedNode(node.getDataAfter().get()); + break; + default: + throw new IllegalArgumentException("Unhandled node type " + node.getModificationType()); + } + } + } +} diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DeletedDataTreeCandidateNode.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/persisted/DeletedDataTreeCandidateNode.java similarity index 96% rename from opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DeletedDataTreeCandidateNode.java rename to opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/persisted/DeletedDataTreeCandidateNode.java index 2df380b391..14397794ed 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DeletedDataTreeCandidateNode.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/persisted/DeletedDataTreeCandidateNode.java @@ -5,7 +5,7 @@ * 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; +package org.opendaylight.controller.cluster.datastore.persisted; import com.google.common.base.Optional; import java.util.Collection; diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ModifiedDataTreeCandidateNode.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/persisted/ModifiedDataTreeCandidateNode.java similarity index 97% rename from opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ModifiedDataTreeCandidateNode.java rename to opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/persisted/ModifiedDataTreeCandidateNode.java index 44038ecd0a..59d03d465e 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ModifiedDataTreeCandidateNode.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/persisted/ModifiedDataTreeCandidateNode.java @@ -5,7 +5,7 @@ * 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; +package org.opendaylight.controller.cluster.datastore.persisted; import com.google.common.base.Optional; import com.google.common.base.Preconditions; diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/persisted/package-info.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/persisted/package-info.java new file mode 100644 index 0000000000..f3905b9927 --- /dev/null +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/persisted/package-info.java @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. 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 + */ +/** + * Persisted backend structures. This includes various Payloads and Snapshots. + * + * @author Robert Varga + */ +package org.opendaylight.controller.cluster.datastore.persisted; \ No newline at end of file