*/
package org.opendaylight.controller.cluster.datastore.persisted;
+import static java.util.Objects.requireNonNull;
+
import com.google.common.annotations.Beta;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableList;
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.eclipse.jdt.annotation.NonNullByDefault;
+import org.opendaylight.yangtools.concepts.Immutable;
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.opendaylight.yangtools.yang.data.api.schema.stream.ReusableStreamReceiver;
+import org.opendaylight.yangtools.yang.data.codec.binfmt.NormalizedNodeDataInput;
+import org.opendaylight.yangtools.yang.data.codec.binfmt.NormalizedNodeDataOutput;
+import org.opendaylight.yangtools.yang.data.codec.binfmt.NormalizedNodeStreamVersion;
+import org.opendaylight.yangtools.yang.data.tree.api.DataTreeCandidate;
+import org.opendaylight.yangtools.yang.data.tree.api.DataTreeCandidateNode;
+import org.opendaylight.yangtools.yang.data.tree.api.ModificationType;
+import org.opendaylight.yangtools.yang.data.tree.spi.DataTreeCandidateNodes;
+import org.opendaylight.yangtools.yang.data.tree.spi.DataTreeCandidates;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
throw new UnsupportedOperationException();
}
- private static DataTreeCandidateNode readModifiedNode(final ModificationType type,
- final NormalizedNodeDataInput in) throws IOException {
-
+ private static DataTreeCandidateNode readModifiedNode(final ModificationType type, final NormalizedNodeDataInput in,
+ final ReusableStreamReceiver receiver) throws IOException {
final PathArgument identifier = in.readPathArgument();
- final Collection<DataTreeCandidateNode> children = readChildren(in);
+ final Collection<DataTreeCandidateNode> children = readChildren(in, receiver);
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);
}
+
+ return ModifiedDataTreeCandidateNode.create(identifier, type, children);
}
- private static Collection<DataTreeCandidateNode> readChildren(final NormalizedNodeDataInput in) throws IOException {
+ private static Collection<DataTreeCandidateNode> readChildren(final NormalizedNodeDataInput in,
+ final ReusableStreamReceiver receiver) throws IOException {
final int size = in.readInt();
- if (size != 0) {
- final Collection<DataTreeCandidateNode> ret = new ArrayList<>(size);
- for (int i = 0; i < size; ++i) {
- final DataTreeCandidateNode child = readNode(in);
- if (child != null) {
- ret.add(child);
- }
+ if (size == 0) {
+ return ImmutableList.of();
+ }
+
+ final Collection<DataTreeCandidateNode> ret = new ArrayList<>(size);
+ for (int i = 0; i < size; ++i) {
+ final DataTreeCandidateNode child = readNode(in, receiver);
+ if (child != null) {
+ ret.add(child);
}
- return ret;
- } else {
- return Collections.emptyList();
}
+ return ret;
}
- private static DataTreeCandidateNode readNode(final NormalizedNodeDataInput in) throws IOException {
+ private static DataTreeCandidateNode readNode(final NormalizedNodeDataInput in,
+ final ReusableStreamReceiver receiver) 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);
+ case APPEARED:
+ return readModifiedNode(ModificationType.APPEARED, in, receiver);
+ case DELETE:
+ return DeletedDataTreeCandidateNode.create(in.readPathArgument());
+ case DISAPPEARED:
+ return readModifiedNode(ModificationType.DISAPPEARED, in, receiver);
+ case SUBTREE_MODIFIED:
+ return readModifiedNode(ModificationType.SUBTREE_MODIFIED, in, receiver);
+ case UNMODIFIED:
+ return null;
+ case WRITE:
+ return DataTreeCandidateNodes.written(in.readNormalizedNode(receiver));
+ default:
+ throw new IllegalArgumentException("Unhandled node type " + type);
}
}
- public static DataTreeCandidate readDataTreeCandidate(final DataInput in) throws IOException {
- final NormalizedNodeDataInput reader = new NormalizedNodeInputStreamReader(in);
+ @NonNullByDefault
+ public static final class DataTreeCandidateWithVersion implements Immutable {
+ private final DataTreeCandidate candidate;
+ private final NormalizedNodeStreamVersion version;
+
+ public DataTreeCandidateWithVersion(final DataTreeCandidate candidate,
+ final NormalizedNodeStreamVersion version) {
+ this.candidate = requireNonNull(candidate);
+ this.version = requireNonNull(version);
+ }
+
+ public DataTreeCandidate getCandidate() {
+ return candidate;
+ }
+
+ public NormalizedNodeStreamVersion getVersion() {
+ return version;
+ }
+ }
+
+ public static DataTreeCandidateWithVersion readDataTreeCandidate(final DataInput in,
+ final ReusableStreamReceiver receiver) throws IOException {
+ final NormalizedNodeDataInput reader = NormalizedNodeDataInput.newDataInput(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);
+ case APPEARED:
+ rootNode = ModifiedDataTreeCandidateNode.create(ModificationType.APPEARED,
+ readChildren(reader, receiver));
+ break;
+ case DELETE:
+ rootNode = DeletedDataTreeCandidateNode.create();
+ break;
+ case DISAPPEARED:
+ rootNode = ModifiedDataTreeCandidateNode.create(ModificationType.DISAPPEARED,
+ readChildren(reader, receiver));
+ break;
+ case SUBTREE_MODIFIED:
+ rootNode = ModifiedDataTreeCandidateNode.create(ModificationType.SUBTREE_MODIFIED,
+ readChildren(reader, receiver));
+ break;
+ case WRITE:
+ rootNode = DataTreeCandidateNodes.written(reader.readNormalizedNode(receiver));
+ break;
+ case UNMODIFIED:
+ rootNode = AbstractDataTreeCandidateNode.createUnmodified();
+ break;
+ default:
+ throw new IllegalArgumentException("Unhandled node type " + type);
}
- return DataTreeCandidates.newDataTreeCandidate(rootPath, rootNode);
+ return new DataTreeCandidateWithVersion(DataTreeCandidates.newDataTreeCandidate(rootPath, rootNode),
+ reader.getVersion());
}
-
private static void writeChildren(final NormalizedNodeDataOutput out,
final Collection<DataTreeCandidateNode> children) throws IOException {
out.writeInt(children.size());
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());
+ out.writeByte(APPEARED);
+ out.writePathArgument(node.getIdentifier());
+ writeChildren(out, node.getChildNodes());
break;
case DELETE:
- writer.writeByte(DELETE);
+ out.writeByte(DELETE);
+ out.writePathArgument(node.getIdentifier());
break;
case DISAPPEARED:
- writer.writeByte(DISAPPEARED);
- writeChildren(writer, node.getChildNodes());
+ out.writeByte(DISAPPEARED);
+ out.writePathArgument(node.getIdentifier());
+ writeChildren(out, node.getChildNodes());
break;
case SUBTREE_MODIFIED:
- writer.writeByte(SUBTREE_MODIFIED);
- writeChildren(writer, node.getChildNodes());
- break;
- case UNMODIFIED:
- writer.writeByte(UNMODIFIED);
+ out.writeByte(SUBTREE_MODIFIED);
+ out.writePathArgument(node.getIdentifier());
+ writeChildren(out, node.getChildNodes());
break;
case WRITE:
- writer.writeByte(WRITE);
- writer.writeNormalizedNode(node.getDataAfter().get());
+ out.writeByte(WRITE);
+ out.writeNormalizedNode(node.getDataAfter().get());
+ break;
+ case UNMODIFIED:
+ out.writeByte(UNMODIFIED);
break;
default:
- throw new IllegalArgumentException("Unhandled node type " + node.getModificationType());
+ throwUnhandledNodeType(node);
+ }
+ }
+
+ @VisibleForTesting
+ public static void writeDataTreeCandidate(final DataOutput out, final PayloadVersion version,
+ final DataTreeCandidate candidate) throws IOException {
+ try (NormalizedNodeDataOutput writer = version.getStreamVersion().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:
+ throwUnhandledNodeType(node);
}
}
}
+
+ public static void writeDataTreeCandidate(final DataOutput out, final DataTreeCandidate candidate)
+ throws IOException {
+ writeDataTreeCandidate(out, PayloadVersion.current(), candidate);
+ }
+
+ private static void throwUnhandledNodeType(final DataTreeCandidateNode node) {
+ throw new IllegalArgumentException("Unhandled node type " + node.getModificationType());
+ }
}