From 104ce145c9cd637c9b1caecfe0fe02c4ce4f343c Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Wed, 11 May 2016 16:42:32 +0200 Subject: [PATCH] BUG-5280: add cds-access-api identifiers This patch adds a new component, which will hold the API exposed by the CDS backend and used by the CDS frontend. Change-Id: If0a2a6372b6cbbe898d2413bcd35259f7900a90a Signed-off-by: Robert Varga --- features/mdsal/src/main/features/features.xml | 1 + opendaylight/md-sal/cds-access-api/pom.xml | 55 +++++++++ .../access/concepts/ClientIdentifier.java | 108 +++++++++++++++++ .../access/concepts/FrontendIdentifier.java | 107 +++++++++++++++++ .../cluster/access/concepts/FrontendType.java | 35 ++++++ .../concepts/LocalHistoryIdentifier.java | 102 ++++++++++++++++ .../cluster/access/concepts/MemberName.java | 112 ++++++++++++++++++ .../concepts/TransactionIdentifier.java | 105 ++++++++++++++++ .../cluster/access/concepts/package-info.java | 13 ++ .../concepts/AbstractIdentifierTest.java | 58 +++++++++ .../access/concepts/ClientIdentifierTest.java | 32 +++++ .../concepts/FrontendIdentifierTest.java | 55 +++++++++ .../access/concepts/MemberNameTest.java | 47 ++++++++ opendaylight/md-sal/mdsal-artifacts/pom.xml | 5 + opendaylight/md-sal/pom.xml | 2 +- .../md-sal/sal-distributed-datastore/pom.xml | 4 + 16 files changed, 840 insertions(+), 1 deletion(-) create mode 100644 opendaylight/md-sal/cds-access-api/pom.xml create mode 100644 opendaylight/md-sal/cds-access-api/src/main/java/org/opendaylight/controller/cluster/access/concepts/ClientIdentifier.java create mode 100644 opendaylight/md-sal/cds-access-api/src/main/java/org/opendaylight/controller/cluster/access/concepts/FrontendIdentifier.java create mode 100644 opendaylight/md-sal/cds-access-api/src/main/java/org/opendaylight/controller/cluster/access/concepts/FrontendType.java create mode 100644 opendaylight/md-sal/cds-access-api/src/main/java/org/opendaylight/controller/cluster/access/concepts/LocalHistoryIdentifier.java create mode 100644 opendaylight/md-sal/cds-access-api/src/main/java/org/opendaylight/controller/cluster/access/concepts/MemberName.java create mode 100644 opendaylight/md-sal/cds-access-api/src/main/java/org/opendaylight/controller/cluster/access/concepts/TransactionIdentifier.java create mode 100644 opendaylight/md-sal/cds-access-api/src/main/java/org/opendaylight/controller/cluster/access/concepts/package-info.java create mode 100644 opendaylight/md-sal/cds-access-api/src/test/java/org/opendaylight/controller/cluster/access/concepts/AbstractIdentifierTest.java create mode 100644 opendaylight/md-sal/cds-access-api/src/test/java/org/opendaylight/controller/cluster/access/concepts/ClientIdentifierTest.java create mode 100644 opendaylight/md-sal/cds-access-api/src/test/java/org/opendaylight/controller/cluster/access/concepts/FrontendIdentifierTest.java create mode 100644 opendaylight/md-sal/cds-access-api/src/test/java/org/opendaylight/controller/cluster/access/concepts/MemberNameTest.java diff --git a/features/mdsal/src/main/features/features.xml b/features/mdsal/src/main/features/features.xml index d5d06f69e4..ca04823373 100644 --- a/features/mdsal/src/main/features/features.xml +++ b/features/mdsal/src/main/features/features.xml @@ -81,6 +81,7 @@ odl-mdsal-broker-local odl-mdsal-clustering-commons + mvn:org.opendaylight.controller/cds-access-api/{{VERSION}} mvn:org.opendaylight.controller/sal-distributed-datastore/{{VERSION}} mvn:org.opendaylight.controller/sal-cluster-admin/{{VERSION}} diff --git a/opendaylight/md-sal/cds-access-api/pom.xml b/opendaylight/md-sal/cds-access-api/pom.xml new file mode 100644 index 0000000000..05f3c8aa46 --- /dev/null +++ b/opendaylight/md-sal/cds-access-api/pom.xml @@ -0,0 +1,55 @@ + + + 4.0.0 + + + org.opendaylight.odlparent + bundle-parent + 1.7.0-SNAPSHOT + + + + org.opendaylight.controller + cds-access-api + 1.0.0-SNAPSHOT + bundle + + + + + org.opendaylight.yangtools + yangtools-artifacts + 1.0.0-SNAPSHOT + pom + import + + + + + + + com.google.guava + guava + + + com.typesafe.akka + akka-actor_${scala.version} + + + + org.opendaylight.yangtools + concepts + + + org.opendaylight.yangtools + yang-data-api + + + + + scm:git:http://git.opendaylight.org/gerrit/controller.git + scm:git:ssh://git.opendaylight.org:29418/controller.git + HEAD + https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:Architecture:Clustering + + diff --git a/opendaylight/md-sal/cds-access-api/src/main/java/org/opendaylight/controller/cluster/access/concepts/ClientIdentifier.java b/opendaylight/md-sal/cds-access-api/src/main/java/org/opendaylight/controller/cluster/access/concepts/ClientIdentifier.java new file mode 100644 index 0000000000..b2016d806c --- /dev/null +++ b/opendaylight/md-sal/cds-access-api/src/main/java/org/opendaylight/controller/cluster/access/concepts/ClientIdentifier.java @@ -0,0 +1,108 @@ +/* + * 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.access.concepts; + +import com.google.common.annotations.Beta; +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import org.opendaylight.yangtools.concepts.Identifier; + +/** + * A cluster-wide unique identifier of a frontend instance. This identifier discerns between individual incarnations + * of a particular frontend. + * + * @author Robert Varga + */ +@Beta +public final class ClientIdentifier implements Identifier { + private static final class Proxy implements Externalizable { + private static final long serialVersionUID = 1L; + private FrontendIdentifier frontendId; + private long generation; + + public Proxy() { + // Needed for Externalizable + } + + Proxy(final FrontendIdentifier frontendId, final long generation) { + this.frontendId = Preconditions.checkNotNull(frontendId); + this.generation = generation; + } + + @Override + public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(frontendId); + out.writeLong(generation); + } + + @SuppressWarnings("unchecked") + @Override + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + frontendId = (FrontendIdentifier) in.readObject(); + generation = in.readLong(); + } + + private Object readResolve() { + return new ClientIdentifier<>(frontendId, generation); + } + } + + private static final long serialVersionUID = 1L; + private final FrontendIdentifier frontendId; + private final long generation; + + ClientIdentifier(final FrontendIdentifier frontendId, final long generation) { + this.frontendId = Preconditions.checkNotNull(frontendId); + this.generation = generation; + } + + public static ClientIdentifier create(final FrontendIdentifier frontendId, + final long generation) { + return new ClientIdentifier<>(frontendId, generation); + } + + public FrontendIdentifier getFrontendId() { + return frontendId; + } + + public long getGeneration() { + return generation; + } + + @Override + public int hashCode() { + return frontendId.hashCode() * 31 + Long.hashCode(generation); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (!(o instanceof ClientIdentifier)) { + return false; + } + + final ClientIdentifier other = (ClientIdentifier) o; + return generation == other.generation && frontendId.equals(other.frontendId); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(ClientIdentifier.class).add("frontend", frontendId) + .add("generation", Long.toUnsignedString(generation)).toString(); + } + + private Object writeReplace() { + return new Proxy<>(frontendId, generation); + } +} diff --git a/opendaylight/md-sal/cds-access-api/src/main/java/org/opendaylight/controller/cluster/access/concepts/FrontendIdentifier.java b/opendaylight/md-sal/cds-access-api/src/main/java/org/opendaylight/controller/cluster/access/concepts/FrontendIdentifier.java new file mode 100644 index 0000000000..bd16e4b28e --- /dev/null +++ b/opendaylight/md-sal/cds-access-api/src/main/java/org/opendaylight/controller/cluster/access/concepts/FrontendIdentifier.java @@ -0,0 +1,107 @@ +/* + * 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.access.concepts; + +import com.google.common.annotations.Beta; +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.Objects; +import org.opendaylight.yangtools.concepts.Identifier; + +/** + * A cluster-wide unique identifier of a frontend type located at a cluster member. + * + * @author Robert Varga + */ +@Beta +public final class FrontendIdentifier implements Identifier { + private static final class Proxy implements Externalizable { + private static final long serialVersionUID = 1L; + private MemberName memberName; + private T clientType; + + public Proxy() { + // Needed for Externalizable + } + + Proxy(final MemberName memberName, final T clientType) { + this.memberName = Preconditions.checkNotNull(memberName); + this.clientType = Preconditions.checkNotNull(clientType); + } + + @Override + public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(memberName); + out.writeObject(clientType); + } + + @SuppressWarnings("unchecked") + @Override + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + memberName = (MemberName) in.readObject(); + clientType = (T) in.readObject(); + } + + private Object readResolve() { + return new FrontendIdentifier<>(memberName, clientType); + } + } + + private static final long serialVersionUID = 1L; + private final MemberName memberName; + private final T clientType; + + FrontendIdentifier(final MemberName memberName, final T clientType) { + this.clientType = Preconditions.checkNotNull(clientType); + this.memberName = Preconditions.checkNotNull(memberName); + } + + public static FrontendIdentifier create(MemberName memberName, final T clientType) { + return new FrontendIdentifier<>(memberName, clientType); + } + + public T getClientType() { + return clientType; + } + + public MemberName getMemberName() { + return memberName; + } + + @Override + public int hashCode() { + return Objects.hash(memberName, clientType); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (!(o instanceof FrontendIdentifier)) { + return false; + } + + final FrontendIdentifier other = (FrontendIdentifier) o; + return memberName.equals(other.memberName) && clientType.equals(other.clientType); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(FrontendIdentifier.class).add("member", memberName) + .add("clientType", clientType).toString(); + } + + private Object writeReplace() { + return new Proxy<>(memberName, clientType); + } +} diff --git a/opendaylight/md-sal/cds-access-api/src/main/java/org/opendaylight/controller/cluster/access/concepts/FrontendType.java b/opendaylight/md-sal/cds-access-api/src/main/java/org/opendaylight/controller/cluster/access/concepts/FrontendType.java new file mode 100644 index 0000000000..27db82068d --- /dev/null +++ b/opendaylight/md-sal/cds-access-api/src/main/java/org/opendaylight/controller/cluster/access/concepts/FrontendType.java @@ -0,0 +1,35 @@ +/* + * 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.access.concepts; + +import com.google.common.annotations.Beta; +import java.util.regex.Pattern; +import javax.annotation.Nonnull; +import org.opendaylight.yangtools.concepts.Identifier; + +/** + * An {@link Identifier} identifying a data store frontend type, which is able to access the data store backend. + * Frontend implementations need to define this identifier so that multiple clients existing on a member node can be + * discerned. + * + * @author Robert Varga + */ +@Beta +public interface FrontendType extends Identifier { + Pattern SIMPLE_STRING_PATTERN = Pattern.compile("[a-zA-Z-_.*+:=,!~';]+"); + + /** + * Return a string representation of this frontend type. Unlike {@link #toString()}, returned string has + * restricted rules on what it can contain: + * - US-ASCII letters + * - special characters: -_.*+:=,!~'; + * + * A validation pattern for this string is available as {@link #SIMPLE_STRING_PATTERN}. + */ + @Nonnull String toSimpleString(); +} diff --git a/opendaylight/md-sal/cds-access-api/src/main/java/org/opendaylight/controller/cluster/access/concepts/LocalHistoryIdentifier.java b/opendaylight/md-sal/cds-access-api/src/main/java/org/opendaylight/controller/cluster/access/concepts/LocalHistoryIdentifier.java new file mode 100644 index 0000000000..330362e6ae --- /dev/null +++ b/opendaylight/md-sal/cds-access-api/src/main/java/org/opendaylight/controller/cluster/access/concepts/LocalHistoryIdentifier.java @@ -0,0 +1,102 @@ +/* + * 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.access.concepts; + +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import org.opendaylight.yangtools.concepts.Identifier; + +/** + * Globally-unique identifier of a local history. + * + * @param Frontend type + * + * @author Robert Varga + */ +public final class LocalHistoryIdentifier implements Identifier { + private static final class Proxy implements Externalizable { + private static final long serialVersionUID = 1L; + private ClientIdentifier clientId; + private long historyId; + + public Proxy() { + // For Externalizable + } + + Proxy(final ClientIdentifier frontendId, final long historyId) { + this.clientId = Preconditions.checkNotNull(frontendId); + this.historyId = historyId; + } + + @Override + public void writeExternal(final ObjectOutput out) throws IOException { + out.writeObject(clientId); + out.writeLong(historyId); + } + + @SuppressWarnings("unchecked") + @Override + public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException { + clientId = (ClientIdentifier) in.readObject(); + historyId = in.readLong(); + } + + private Object readResolve() { + return new LocalHistoryIdentifier<>(clientId, historyId); + } + } + + private static final long serialVersionUID = 1L; + private final ClientIdentifier clientId; + private final long historyId; + + public LocalHistoryIdentifier(final ClientIdentifier frontendId, final long historyId) { + this.clientId = Preconditions.checkNotNull(frontendId); + this.historyId = historyId; + } + + public ClientIdentifier getClienId() { + return clientId; + } + + public long getHistoryId() { + return historyId; + } + + @Override + public int hashCode() { + return clientId.hashCode() * 31 + Long.hashCode(historyId); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (!(o instanceof LocalHistoryIdentifier)) { + return false; + } + + final LocalHistoryIdentifier other = (LocalHistoryIdentifier) o; + return historyId == other.historyId && clientId.equals(other.clientId); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(LocalHistoryIdentifier.class).add("client", clientId) + .add("history", Long.toUnsignedString(historyId)).toString(); + } + + private Object writeReplace() { + return new Proxy<>(clientId, historyId); + } +} diff --git a/opendaylight/md-sal/cds-access-api/src/main/java/org/opendaylight/controller/cluster/access/concepts/MemberName.java b/opendaylight/md-sal/cds-access-api/src/main/java/org/opendaylight/controller/cluster/access/concepts/MemberName.java new file mode 100644 index 0000000000..ceec55555f --- /dev/null +++ b/opendaylight/md-sal/cds-access-api/src/main/java/org/opendaylight/controller/cluster/access/concepts/MemberName.java @@ -0,0 +1,112 @@ +/* + * 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.access.concepts; + +import com.google.common.annotations.Beta; +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; +import com.google.common.base.Verify; +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.nio.charset.StandardCharsets; +import org.opendaylight.yangtools.concepts.Identifier; + +/** + * Type-safe encapsulation of a cluster member name. + * + * @author Robert Varga + */ +@Beta +public final class MemberName implements Comparable, Identifier { + private static final class Proxy implements Externalizable { + private static final long serialVersionUID = 1L; + private byte[] serialized; + + public Proxy() { + // For Externalizable + } + + Proxy(final String name) { + serialized = name.getBytes(StandardCharsets.UTF_8); + } + + @Override + public void writeExternal(ObjectOutput out) throws IOException { + out.writeInt(serialized.length); + out.write(serialized); + } + + @Override + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + serialized = new byte[in.readInt()]; + in.readFully(serialized); + } + + private Object readResolve() { + // TODO: consider caching instances here + return new MemberName(new String(serialized, StandardCharsets.UTF_8), this); + } + } + + private static final long serialVersionUID = 1L; + private final String name; + private volatile Proxy proxy; + + MemberName(final String name) { + this.name = Preconditions.checkNotNull(name); + } + + MemberName(final String name, final Proxy proxy) { + this.name = Preconditions.checkNotNull(name); + this.proxy = Verify.verifyNotNull(proxy); + } + + public static MemberName forName(final String name) { + Preconditions.checkArgument(!Strings.isNullOrEmpty(name)); + // TODO: consider caching instances here + return new MemberName(name); + } + + public String getName() { + return name; + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + @Override + public boolean equals(final Object o) { + return this == o || (o instanceof MemberName && name.equals(((MemberName)o).name)); + } + + @Override + public int compareTo(final MemberName o) { + return this == o ? 0 : name.compareTo(o.name); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(MemberName.class).add("name", name).toString(); + } + + Object writeReplace() { + Proxy ret = proxy; + if (ret == null) { + // We do not really care if multiple threads race here + ret = new Proxy(name); + proxy = ret; + } + + return ret; + } +} diff --git a/opendaylight/md-sal/cds-access-api/src/main/java/org/opendaylight/controller/cluster/access/concepts/TransactionIdentifier.java b/opendaylight/md-sal/cds-access-api/src/main/java/org/opendaylight/controller/cluster/access/concepts/TransactionIdentifier.java new file mode 100644 index 0000000000..2aaf8264aa --- /dev/null +++ b/opendaylight/md-sal/cds-access-api/src/main/java/org/opendaylight/controller/cluster/access/concepts/TransactionIdentifier.java @@ -0,0 +1,105 @@ +/* + * 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.access.concepts; + +import com.google.common.annotations.Beta; +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import javax.annotation.Nonnull; +import org.opendaylight.yangtools.concepts.Identifier; + +/** + * Globally-unique identifier of a transaction. + * + * @param Frontend type + * + * @author Robert Varga + */ +@Beta +public final class TransactionIdentifier implements Identifier { + private static final class Proxy implements Externalizable { + private static final long serialVersionUID = 1L; + private LocalHistoryIdentifier historyId; + private long transactionId; + + public Proxy() { + // For Externalizable + } + + Proxy(final LocalHistoryIdentifier historyId, final long transactionId) { + this.historyId = Preconditions.checkNotNull(historyId); + this.transactionId = transactionId; + } + + @Override + public void writeExternal(final ObjectOutput out) throws IOException { + out.writeObject(historyId); + out.writeLong(transactionId); + } + + @SuppressWarnings("unchecked") + @Override + public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException { + historyId = (LocalHistoryIdentifier) in.readObject(); + transactionId = in.readLong(); + } + + private Object readResolve() { + return new TransactionIdentifier<>(historyId, transactionId); + } + } + + private static final long serialVersionUID = 1L; + private final LocalHistoryIdentifier historyId; + private final long transactionId; + + public TransactionIdentifier(final @Nonnull LocalHistoryIdentifier historyId, final long transactionId) { + this.historyId = Preconditions.checkNotNull(historyId); + this.transactionId = transactionId; + } + + public LocalHistoryIdentifier getHistoryId() { + return historyId; + } + + public long getTransactionId() { + return transactionId; + } + + @Override + public int hashCode() { + return historyId.hashCode() * 31 + Long.hashCode(transactionId); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (!(o instanceof TransactionIdentifier)) { + return false; + } + + final TransactionIdentifier other = (TransactionIdentifier) o; + return transactionId == other.transactionId && historyId.equals(other.historyId); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(TransactionIdentifier.class).add("history", historyId) + .add("transaction", transactionId).toString(); + } + + private Object writeReplace() { + return new Proxy<>(historyId, transactionId); + } +} diff --git a/opendaylight/md-sal/cds-access-api/src/main/java/org/opendaylight/controller/cluster/access/concepts/package-info.java b/opendaylight/md-sal/cds-access-api/src/main/java/org/opendaylight/controller/cluster/access/concepts/package-info.java new file mode 100644 index 0000000000..3184e074e8 --- /dev/null +++ b/opendaylight/md-sal/cds-access-api/src/main/java/org/opendaylight/controller/cluster/access/concepts/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 + */ +/** + * This package defines basic concepts used to interact with the CDS backend implementation. + * + * @author Robert Varga + */ +package org.opendaylight.controller.cluster.access.concepts; diff --git a/opendaylight/md-sal/cds-access-api/src/test/java/org/opendaylight/controller/cluster/access/concepts/AbstractIdentifierTest.java b/opendaylight/md-sal/cds-access-api/src/test/java/org/opendaylight/controller/cluster/access/concepts/AbstractIdentifierTest.java new file mode 100644 index 0000000000..34ce489793 --- /dev/null +++ b/opendaylight/md-sal/cds-access-api/src/test/java/org/opendaylight/controller/cluster/access/concepts/AbstractIdentifierTest.java @@ -0,0 +1,58 @@ +/* + * 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.access.concepts; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import org.junit.Test; +import org.opendaylight.yangtools.concepts.Identifier; + +public abstract class AbstractIdentifierTest { + abstract T object(); + abstract T differentObject(); + abstract T equalObject(); + + @Test + public final void testEquals() { + assertTrue(object().equals(object())); + assertTrue(object().equals(equalObject())); + assertFalse(object().equals(null)); + assertFalse(object().equals("dummy")); + assertFalse(object().equals(differentObject())); + } + + @Test + public final void testHashCode() { + assertEquals(object().hashCode(), equalObject().hashCode()); + } + + @SuppressWarnings("unchecked") + private static T copy(T o) throws IOException, ClassNotFoundException { + final ByteArrayOutputStream bos = new ByteArrayOutputStream(); + try (ObjectOutputStream oos = new ObjectOutputStream(bos)) { + oos.writeObject(o); + } + + try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()))) { + return (T) ois.readObject(); + } + } + + @Test + public final void testSerialization() throws Exception { + assertTrue(object().equals(copy(object()))); + assertTrue(object().equals(copy(equalObject()))); + assertFalse(differentObject().equals(copy(object()))); + } +} diff --git a/opendaylight/md-sal/cds-access-api/src/test/java/org/opendaylight/controller/cluster/access/concepts/ClientIdentifierTest.java b/opendaylight/md-sal/cds-access-api/src/test/java/org/opendaylight/controller/cluster/access/concepts/ClientIdentifierTest.java new file mode 100644 index 0000000000..666c2b088a --- /dev/null +++ b/opendaylight/md-sal/cds-access-api/src/test/java/org/opendaylight/controller/cluster/access/concepts/ClientIdentifierTest.java @@ -0,0 +1,32 @@ +/* + * 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.access.concepts; + +public class ClientIdentifierTest extends AbstractIdentifierTest> { + private static final FrontendIdentifier FRONTEND = + new FrontendIdentifier<>(MemberName.forName("test"), FrontendIdentifierTest.ONE_FRONTEND_TYPE); + + private static final ClientIdentifier OBJECT = new ClientIdentifier<>(FRONTEND, 0); + private static final ClientIdentifier DIFFERENT_OBJECT = new ClientIdentifier<>(FRONTEND, 1); + private static final ClientIdentifier EQUAL_OBJECT = new ClientIdentifier<>(FRONTEND, 0); + + @Override + ClientIdentifier object() { + return OBJECT; + } + + @Override + ClientIdentifier differentObject() { + return DIFFERENT_OBJECT; + } + + @Override + ClientIdentifier equalObject() { + return EQUAL_OBJECT; + } +} diff --git a/opendaylight/md-sal/cds-access-api/src/test/java/org/opendaylight/controller/cluster/access/concepts/FrontendIdentifierTest.java b/opendaylight/md-sal/cds-access-api/src/test/java/org/opendaylight/controller/cluster/access/concepts/FrontendIdentifierTest.java new file mode 100644 index 0000000000..5611bb5b16 --- /dev/null +++ b/opendaylight/md-sal/cds-access-api/src/test/java/org/opendaylight/controller/cluster/access/concepts/FrontendIdentifierTest.java @@ -0,0 +1,55 @@ +/* + * 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.access.concepts; + +public class FrontendIdentifierTest extends AbstractIdentifierTest> { + static final FrontendType ONE_FRONTEND_TYPE = new FrontendType() { + private static final long serialVersionUID = 1L; + + @Override + public String toSimpleString() { + return "one"; + } + + private Object readResolve() { + return ONE_FRONTEND_TYPE; + } + }; + static final FrontendType OTHER_FRONTEND_TYPE = new FrontendType() { + private static final long serialVersionUID = 1L; + + @Override + public String toSimpleString() { + return "two"; + } + + private Object readResolve() { + return OTHER_FRONTEND_TYPE; + } + }; + + private static final MemberName MEMBER = MemberName.forName("test"); + private static final FrontendIdentifier OBJECT = new FrontendIdentifier<>(MEMBER, ONE_FRONTEND_TYPE); + private static final FrontendIdentifier DIFFERENT_OBJECT = new FrontendIdentifier<>(MEMBER, OTHER_FRONTEND_TYPE); + private static final FrontendIdentifier EQUAL_OBJECT = new FrontendIdentifier<>(MEMBER, ONE_FRONTEND_TYPE); + + @Override + FrontendIdentifier object() { + return OBJECT; + } + + @Override + FrontendIdentifier differentObject() { + return DIFFERENT_OBJECT; + } + + @Override + FrontendIdentifier equalObject() { + return EQUAL_OBJECT; + } +} diff --git a/opendaylight/md-sal/cds-access-api/src/test/java/org/opendaylight/controller/cluster/access/concepts/MemberNameTest.java b/opendaylight/md-sal/cds-access-api/src/test/java/org/opendaylight/controller/cluster/access/concepts/MemberNameTest.java new file mode 100644 index 0000000000..e5031fc15a --- /dev/null +++ b/opendaylight/md-sal/cds-access-api/src/test/java/org/opendaylight/controller/cluster/access/concepts/MemberNameTest.java @@ -0,0 +1,47 @@ +/* + * 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.access.concepts; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import org.junit.Test; + +public class MemberNameTest extends AbstractIdentifierTest { + private static final MemberName OBJECT = MemberName.forName("test1"); + private static final MemberName DIFFERENT_OBJECT = MemberName.forName("test2"); + private static final MemberName EQUAL_OBJECT = MemberName.forName("test1"); + + @Override + MemberName object() { + return OBJECT; + } + + @Override + MemberName differentObject() { + return DIFFERENT_OBJECT; + } + + @Override + MemberName equalObject() { + return EQUAL_OBJECT; + } + + + @Test + public void testCompareTo() { + assertEquals(0, object().compareTo(object())); + assertEquals(0, object().compareTo(equalObject())); + assertTrue(object().compareTo(differentObject()) < 0); + assertTrue(differentObject().compareTo(object()) > 0); + } + + @Test + public void testGetName() { + assertEquals("test1", OBJECT.getName()); + } +} diff --git a/opendaylight/md-sal/mdsal-artifacts/pom.xml b/opendaylight/md-sal/mdsal-artifacts/pom.xml index e94b962629..5a3b1bf9b0 100644 --- a/opendaylight/md-sal/mdsal-artifacts/pom.xml +++ b/opendaylight/md-sal/mdsal-artifacts/pom.xml @@ -183,6 +183,11 @@ sal-akka-raft-example ${project.version} + + org.opendaylight.controller + cds-access-api + 1.0.0-SNAPSHOT + diff --git a/opendaylight/md-sal/pom.xml b/opendaylight/md-sal/pom.xml index 03aa18cf69..489ec7bdc3 100644 --- a/opendaylight/md-sal/pom.xml +++ b/opendaylight/md-sal/pom.xml @@ -55,8 +55,8 @@ sal-inmemory-datastore - sal-clustering-commons + cds-access-api sal-clustering-config diff --git a/opendaylight/md-sal/sal-distributed-datastore/pom.xml b/opendaylight/md-sal/sal-distributed-datastore/pom.xml index 8ce090e702..b138574add 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/pom.xml +++ b/opendaylight/md-sal/sal-distributed-datastore/pom.xml @@ -93,6 +93,10 @@ org.opendaylight.controller sal-akka-raft + + org.opendaylight.controller + cds-access-api + org.opendaylight.controller sal-akka-raft-example -- 2.36.6