Merge "Bug 2268: Serialize ApppendEntries"
authorMoiz Raja <moraja@cisco.com>
Tue, 3 Feb 2015 18:50:27 +0000 (18:50 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Tue, 3 Feb 2015 18:50:27 +0000 (18:50 +0000)
12 files changed:
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftVersions.java [new file with mode: 0644]
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLogImplEntry.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/SerializationUtils.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/AbstractRaftRPC.java
opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/AppendEntries.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/MockRaftActorContext.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/ReplicatedLogImplEntryTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/LeaderTest.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/messages/AppendEntriesTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-akka-raft/src/test/resources/helium-serialized-ReplicatedLogImplEntry [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/CompositeModificationPayloadTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/programs/appendentries/Server.java

diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftVersions.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftVersions.java
new file mode 100644 (file)
index 0000000..4330a4c
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2015 Brocade Communications 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.raft;
+
+/**
+ * @author Thomas Pantelis
+ */
+public interface RaftVersions {
+    short HELIUM_VERSION = 0;
+    short LITHIUM_VERSION = 1;
+    short CURRENT_VERSION = LITHIUM_VERSION;
+}
index 986c7f382c44f00405abb7d62394cda548e2a66c..799e75ebfaffd4bba7b40974291680a5d9cf0f21 100644 (file)
@@ -11,9 +11,8 @@ package org.opendaylight.controller.cluster.raft;
 import java.io.Serializable;
 import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
 
-public class ReplicatedLogImplEntry implements ReplicatedLogEntry,
-    Serializable {
-    private static final long serialVersionUID = 1L;
+public class ReplicatedLogImplEntry implements ReplicatedLogEntry, Serializable {
+    private static final long serialVersionUID = -9085798014576489130L;
 
     private final long index;
     private final long term;
@@ -26,15 +25,18 @@ public class ReplicatedLogImplEntry implements ReplicatedLogEntry,
         this.payload = payload;
     }
 
-    @Override public Payload getData() {
+    @Override
+    public Payload getData() {
         return payload;
     }
 
-    @Override public long getTerm() {
+    @Override
+    public long getTerm() {
         return term;
     }
 
-    @Override public long getIndex() {
+    @Override
+    public long getIndex() {
         return index;
     }
 
@@ -43,7 +45,8 @@ public class ReplicatedLogImplEntry implements ReplicatedLogEntry,
         return getData().size();
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
         return "Entry{" +
             "index=" + index +
             ", term=" + term +
index 2f5ba48f9258d9a47ebf62ac98966db5d1055d99..7ec32440e7fdfcbe24e2a252f9859860de634ff1 100644 (file)
@@ -14,7 +14,7 @@ import org.opendaylight.controller.cluster.raft.messages.InstallSnapshot;
 public class SerializationUtils {
 
     public static Object fromSerializable(Object serializable){
-        if(serializable.getClass().equals(AppendEntries.SERIALIZABLE_CLASS)){
+        if(AppendEntries.isSerializedType(serializable)){
             return AppendEntries.fromSerializable(serializable);
 
         } else if (serializable.getClass().equals(InstallSnapshot.SERIALIZABLE_CLASS)) {
index 0122d45c3095962161712643e6c3c4fb0fbf6e7b..3c9ebf47fd7178eca126ce962504153ca7f8ad21 100644 (file)
@@ -9,7 +9,8 @@
 package org.opendaylight.controller.cluster.raft.messages;
 
 public class AbstractRaftRPC implements RaftRPC {
-    private static final long serialVersionUID = 1L;
+    private static final long serialVersionUID = -6061342433962854822L;
+
     // term
     protected long term;
 
@@ -21,6 +22,7 @@ public class AbstractRaftRPC implements RaftRPC {
     public AbstractRaftRPC() {
     }
 
+    @Override
     public long getTerm() {
         return term;
     }
index e5aebaa6be9f01e4dd46bd7a38db2e210fd39773..81981062177510641c08edb243016075f388ae0f 100644 (file)
@@ -9,25 +9,30 @@
 package org.opendaylight.controller.cluster.raft.messages;
 
 import com.google.protobuf.GeneratedMessage;
-import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
-import org.opendaylight.controller.cluster.raft.ReplicatedLogImplEntry;
-import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
-import org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages;
-
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import org.opendaylight.controller.cluster.raft.RaftVersions;
+import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
+import org.opendaylight.controller.cluster.raft.ReplicatedLogImplEntry;
+import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
+import org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages;
 
 /**
  * Invoked by leader to replicate log entries (§5.3); also used as
  * heartbeat (§5.2).
  */
 public class AppendEntries extends AbstractRaftRPC {
-    public static final Class<AppendEntriesMessages.AppendEntries> SERIALIZABLE_CLASS = AppendEntriesMessages.AppendEntries.class;
+    private static final long serialVersionUID = 1L;
+
+    public static final Class<AppendEntriesMessages.AppendEntries> LEGACY_SERIALIZABLE_CLASS =
+            AppendEntriesMessages.AppendEntries.class;
 
     private static final org.slf4j.Logger LOG = org.slf4j.LoggerFactory.getLogger(AppendEntries.class);
-    private static final long serialVersionUID = 1L;
 
     // So that follower can redirect clients
     private final String leaderId;
@@ -40,7 +45,7 @@ public class AppendEntries extends AbstractRaftRPC {
 
     // log entries to store (empty for heartbeat;
     // may send more than one for efficiency)
-    private final List<ReplicatedLogEntry> entries;
+    private transient List<ReplicatedLogEntry> entries;
 
     // leader's commitIndex
     private final long leaderCommit;
@@ -55,6 +60,28 @@ public class AppendEntries extends AbstractRaftRPC {
         this.leaderCommit = leaderCommit;
     }
 
+    private void writeObject(ObjectOutputStream out) throws IOException {
+        out.writeShort(RaftVersions.CURRENT_VERSION);
+        out.defaultWriteObject();
+
+        out.writeInt(entries.size());
+        for(ReplicatedLogEntry e: entries) {
+            out.writeObject(e);
+        }
+    }
+
+    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+        in.readShort(); // version
+
+        in.defaultReadObject();
+
+        int size = in.readInt();
+        entries = new ArrayList<>(size);
+        for(int i = 0; i < size; i++) {
+            entries.add((ReplicatedLogEntry) in.readObject());
+        }
+    }
+
     public String getLeaderId() {
         return leaderId;
     }
@@ -75,7 +102,8 @@ public class AppendEntries extends AbstractRaftRPC {
         return leaderCommit;
     }
 
-    @Override public String toString() {
+    @Override
+    public String toString() {
         final StringBuilder sb =
             new StringBuilder("AppendEntries{");
         sb.append("term=").append(getTerm());
@@ -88,7 +116,20 @@ public class AppendEntries extends AbstractRaftRPC {
         return sb.toString();
     }
 
-    public <T extends Object> Object toSerializable(){
+    public <T extends Object> Object toSerializable() {
+        return toSerializable(RaftVersions.CURRENT_VERSION);
+    }
+
+    public <T extends Object> Object toSerializable(short version) {
+        if(version < RaftVersions.LITHIUM_VERSION) {
+            return toLegacySerializable();
+        } else {
+            return this;
+        }
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    private <T> Object toLegacySerializable() {
         AppendEntriesMessages.AppendEntries.Builder to = AppendEntriesMessages.AppendEntries.newBuilder();
         to.setTerm(this.getTerm())
             .setLeaderId(this.getLeaderId())
@@ -122,9 +163,16 @@ public class AppendEntries extends AbstractRaftRPC {
         return to.build();
     }
 
-    public static AppendEntries fromSerializable(Object o){
-        AppendEntriesMessages.AppendEntries from = (AppendEntriesMessages.AppendEntries) o;
+    public static AppendEntries fromSerializable(Object serialized) {
+        if(serialized instanceof AppendEntries) {
+            return (AppendEntries)serialized;
+        }
+        else {
+            return fromLegacySerializable((AppendEntriesMessages.AppendEntries) serialized);
+        }
+    }
 
+    private static AppendEntries fromLegacySerializable(AppendEntriesMessages.AppendEntries from) {
         List<ReplicatedLogEntry> logEntryList = new ArrayList<>();
         for (AppendEntriesMessages.AppendEntries.ReplicatedLogEntry leProtoBuff : from.getLogEntriesList()) {
 
@@ -134,7 +182,6 @@ public class AppendEntries extends AbstractRaftRPC {
                     String clientPayloadClassName = leProtoBuff.getData().getClientPayloadClassName();
                     payload = (Payload) Class.forName(clientPayloadClassName).newInstance();
                     payload = payload.decode(leProtoBuff.getData());
-                    payload.setClientPayloadClassName(clientPayloadClassName);
                 } else {
                     LOG.error("Payload is null or payload does not have client payload class name");
                 }
@@ -160,4 +207,8 @@ public class AppendEntries extends AbstractRaftRPC {
 
         return to;
     }
+
+    public static boolean isSerializedType(Object message) {
+        return message instanceof AppendEntries || LEGACY_SERIALIZABLE_CLASS.isInstance(message);
+    }
 }
index 2424d4d557f7f1dc58e65a1718e44a6a84db501f..cd852eaae2d247f8b484f435b54e73fd0b97f1c9 100644 (file)
@@ -55,14 +55,17 @@ public class MockRaftActorContext implements RaftActorContext {
             private long currentTerm = 0;
             private String votedFor = "";
 
+            @Override
             public long getCurrentTerm() {
                 return currentTerm;
             }
 
+            @Override
             public String getVotedFor() {
                 return votedFor;
             }
 
+            @Override
             public void update(long currentTerm, String votedFor){
                 this.currentTerm = currentTerm;
                 this.votedFor = votedFor;
@@ -127,6 +130,7 @@ public class MockRaftActorContext implements RaftActorContext {
         return lastApplied;
     }
 
+    @Override
     public void setReplicatedLog(ReplicatedLog replicatedLog) {
         this.replicatedLog = replicatedLog;
     }
@@ -202,7 +206,7 @@ public class MockRaftActorContext implements RaftActorContext {
     }
 
     public static class MockPayload extends Payload implements Serializable {
-        private static final long serialVersionUID = 1L;
+        private static final long serialVersionUID = 3121380393130864247L;
         private String value = "";
 
         public MockPayload(){
@@ -235,6 +239,7 @@ public class MockRaftActorContext implements RaftActorContext {
             return MockPayload.class.getName();
         }
 
+        @Override
         public String toString() {
             return value;
         }
@@ -273,7 +278,7 @@ public class MockRaftActorContext implements RaftActorContext {
     }
 
     public static class MockReplicatedLogBuilder {
-        private ReplicatedLog mockLog = new SimpleReplicatedLog();
+        private final ReplicatedLog mockLog = new SimpleReplicatedLog();
 
         public  MockReplicatedLogBuilder createEntries(int start, int end, int term) {
             for (int i=start; i<end; i++) {
diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/ReplicatedLogImplEntryTest.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/ReplicatedLogImplEntryTest.java
new file mode 100644 (file)
index 0000000..1fe22bc
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2015 Brocade Communications 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.raft;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Unit tests for ReplicatedLogImplEntry.
+ *
+ * @author Thomas Pantelis
+ */
+public class ReplicatedLogImplEntryTest {
+
+    @Test
+    public void testBackwardsCompatibleDeserializationFromHelium() throws Exception {
+        String expPayloadData = "This is a test";
+        int expIndex = 1;
+        int expTerm = 2;
+
+        try(FileInputStream fis = new FileInputStream("src/test/resources/helium-serialized-ReplicatedLogImplEntry")) {
+            ObjectInputStream ois = new ObjectInputStream(fis);
+
+            ReplicatedLogImplEntry entry = (ReplicatedLogImplEntry) ois.readObject();
+            ois.close();
+
+            Assert.assertEquals("getIndex", expIndex, entry.getIndex());
+            Assert.assertEquals("getTerm", expTerm, entry.getTerm());
+
+            MockRaftActorContext.MockPayload payload = (MockRaftActorContext.MockPayload) entry.getData();
+            Assert.assertEquals("data", expPayloadData, payload.toString());
+        }
+    }
+
+    /**
+     * Use this method to generate a file with a serialized ReplicatedLogImplEntry instance to be
+     * used in tests that verify backwards compatible de-serialization.
+     */
+    private void generateSerializedFile() throws IOException {
+        String expPayloadData = "This is a test";
+        int expIndex = 1;
+        int expTerm = 2;
+
+        ReplicatedLogImplEntry entry = new ReplicatedLogImplEntry(expIndex, expTerm,
+                new MockRaftActorContext.MockPayload(expPayloadData));
+        FileOutputStream fos = new FileOutputStream("src/test/resources/serialized-ReplicatedLogImplEntry");
+        ObjectOutputStream oos = new ObjectOutputStream(fos);
+        oos.writeObject(entry);
+        fos.close();
+    }
+}
index 151015e97ec785277beaf51b0bdb4fe0681f6582..b31cb621b3576b1a9bcbaff321465d4bd186674e 100644 (file)
@@ -43,15 +43,14 @@ import org.opendaylight.controller.cluster.raft.messages.InstallSnapshotReply;
 import org.opendaylight.controller.cluster.raft.messages.RequestVoteReply;
 import org.opendaylight.controller.cluster.raft.utils.DoNothingActor;
 import org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor;
-import org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages;
 import org.opendaylight.controller.protobuff.messages.cluster.raft.InstallSnapshotMessages;
 import scala.concurrent.duration.FiniteDuration;
 
 public class LeaderTest extends AbstractRaftActorBehaviorTest {
 
-    private ActorRef leaderActor =
+    private final ActorRef leaderActor =
         getSystem().actorOf(Props.create(DoNothingActor.class));
-    private ActorRef senderActor =
+    private final ActorRef senderActor =
         getSystem().actorOf(Props.create(DoNothingActor.class));
 
     @Test
@@ -273,8 +272,8 @@ public class LeaderTest extends AbstractRaftActorBehaviorTest {
 
             leader.handleMessage(leaderActor, new SendHeartBeat());
 
-            AppendEntriesMessages.AppendEntries aeproto = (AppendEntriesMessages.AppendEntries)MessageCollectorActor.getFirstMatching(
-                followerActor, AppendEntries.SERIALIZABLE_CLASS);
+            AppendEntries aeproto = (AppendEntries)MessageCollectorActor.getFirstMatching(
+                followerActor, AppendEntries.class);
 
             assertNotNull("AppendEntries should be sent even if InstallSnapshotReply is not " +
                 "received", aeproto);
@@ -877,14 +876,13 @@ public class LeaderTest extends AbstractRaftActorBehaviorTest {
 
             leader.handleMessage(leaderActor, new SendHeartBeat());
 
-            AppendEntriesMessages.AppendEntries appendEntries =
-                (AppendEntriesMessages.AppendEntries) MessageCollectorActor
-                    .getFirstMatching(followerActor, AppendEntriesMessages.AppendEntries.class);
+            AppendEntries appendEntries = (AppendEntries) MessageCollectorActor
+                    .getFirstMatching(followerActor, AppendEntries.class);
 
             assertNotNull(appendEntries);
 
             assertEquals(1, appendEntries.getLeaderCommit());
-            assertEquals(1, appendEntries.getLogEntries(0).getIndex());
+            assertEquals(1, appendEntries.getEntries().get(0).getIndex());
             assertEquals(0, appendEntries.getPrevLogIndex());
 
             AppendEntriesReply appendEntriesReply =
@@ -946,14 +944,13 @@ public class LeaderTest extends AbstractRaftActorBehaviorTest {
 
             leader.handleMessage(leaderActor, new SendHeartBeat());
 
-            AppendEntriesMessages.AppendEntries appendEntries =
-                (AppendEntriesMessages.AppendEntries) MessageCollectorActor
-                    .getFirstMatching(followerActor, AppendEntriesMessages.AppendEntries.class);
+            AppendEntries appendEntries = (AppendEntries) MessageCollectorActor
+                    .getFirstMatching(followerActor, AppendEntries.class);
 
             assertNotNull(appendEntries);
 
             assertEquals(1, appendEntries.getLeaderCommit());
-            assertEquals(1, appendEntries.getLogEntries(0).getIndex());
+            assertEquals(1, appendEntries.getEntries().get(0).getIndex());
             assertEquals(0, appendEntries.getPrevLogIndex());
 
             AppendEntriesReply appendEntriesReply =
@@ -1193,8 +1190,8 @@ public class LeaderTest extends AbstractRaftActorBehaviorTest {
 
     private class MockConfigParamsImpl extends DefaultConfigParamsImpl {
 
-        private long electionTimeOutIntervalMillis;
-        private int snapshotChunkSize;
+        private final long electionTimeOutIntervalMillis;
+        private final int snapshotChunkSize;
 
         public MockConfigParamsImpl(long electionTimeOutIntervalMillis, int snapshotChunkSize) {
             super();
diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/messages/AppendEntriesTest.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/messages/AppendEntriesTest.java
new file mode 100644 (file)
index 0000000..abde51b
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2015 Brocade Communications 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.raft.messages;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import org.apache.commons.lang.SerializationUtils;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockPayload;
+import org.opendaylight.controller.cluster.raft.RaftVersions;
+import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
+import org.opendaylight.controller.cluster.raft.ReplicatedLogImplEntry;
+import org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages;
+
+/**
+ * Unit tests for AppendEntries.
+ *
+ * @author Thomas Pantelis
+ */
+public class AppendEntriesTest {
+
+    @Test
+    public void testSerialization() {
+        ReplicatedLogEntry entry1 = new ReplicatedLogImplEntry(1, 2, new MockPayload("payload1"));
+
+        ReplicatedLogEntry entry2 = new ReplicatedLogImplEntry(3, 4, new MockPayload("payload2"));
+
+        AppendEntries expected = new AppendEntries(5L, "node1", 7L, 8L, Arrays.asList(entry1, entry2), 10L);
+
+        AppendEntries cloned = (AppendEntries) SerializationUtils.clone(expected);
+
+        verifyAppendEntries(expected, cloned);
+    }
+
+    @Test
+    public void testToAndFromSerializable() {
+        AppendEntries entries = new AppendEntries(5L, "node1", 7L, 8L,
+                Collections.<ReplicatedLogEntry>emptyList(), 10L);
+
+        assertSame("toSerializable", entries, entries.toSerializable());
+        assertSame("fromSerializable", entries,
+                org.opendaylight.controller.cluster.raft.SerializationUtils.fromSerializable(entries));
+    }
+
+    @Test
+    public void testToAndFromLegacySerializable() {
+        ReplicatedLogEntry entry = new ReplicatedLogImplEntry(3, 4, new MockPayload("payload"));
+        AppendEntries entries = new AppendEntries(5L, "node1", 7L, 8L, Arrays.asList(entry), 10L);
+
+        Object serializable = entries.toSerializable(RaftVersions.HELIUM_VERSION);
+        Assert.assertTrue(serializable instanceof AppendEntriesMessages.AppendEntries);
+
+        AppendEntries entries2 = (AppendEntries)
+                org.opendaylight.controller.cluster.raft.SerializationUtils.fromSerializable(serializable);
+
+        verifyAppendEntries(entries, entries2);
+    }
+
+    private void verifyAppendEntries(AppendEntries expected, AppendEntries actual) {
+        assertEquals("getLeaderId", expected.getLeaderId(), actual.getLeaderId());
+        assertEquals("getTerm", expected.getTerm(), actual.getTerm());
+        assertEquals("getLeaderCommit", expected.getLeaderCommit(), actual.getLeaderCommit());
+        assertEquals("getPrevLogIndex", expected.getPrevLogIndex(), actual.getPrevLogIndex());
+        assertEquals("getPrevLogTerm", expected.getPrevLogTerm(), actual.getPrevLogTerm());
+
+        assertEquals("getEntries size", expected.getEntries().size(), actual.getEntries().size());
+        Iterator<ReplicatedLogEntry> iter = expected.getEntries().iterator();
+        for(ReplicatedLogEntry e: actual.getEntries()) {
+            verifyReplicatedLogEntry(iter.next(), e);
+        }
+    }
+
+    private void verifyReplicatedLogEntry(ReplicatedLogEntry expected, ReplicatedLogEntry actual) {
+        assertEquals("getIndex", expected.getIndex(), actual.getIndex());
+        assertEquals("getTerm", expected.getTerm(), actual.getTerm());
+        assertEquals("getData", expected.getData().toString(), actual.getData().toString());
+    }
+}
diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/resources/helium-serialized-ReplicatedLogImplEntry b/opendaylight/md-sal/sal-akka-raft/src/test/resources/helium-serialized-ReplicatedLogImplEntry
new file mode 100644 (file)
index 0000000..3e87f66
Binary files /dev/null and b/opendaylight/md-sal/sal-akka-raft/src/test/resources/helium-serialized-ReplicatedLogImplEntry differ
index 9e02223f54e18d4d844f8b2be9af188df261a901..cd741672592928553fa8c463d8de7954bd2f8d78 100644 (file)
@@ -11,6 +11,7 @@ import org.junit.Assert;
 import org.junit.Test;
 import org.opendaylight.controller.cluster.datastore.modification.MutableCompositeModification;
 import org.opendaylight.controller.cluster.datastore.modification.WriteModification;
+import org.opendaylight.controller.cluster.raft.RaftVersions;
 import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
 import org.opendaylight.controller.cluster.raft.messages.AppendEntries;
 import org.opendaylight.controller.cluster.raft.protobuff.client.messages.CompositeModificationPayload;
@@ -69,7 +70,8 @@ public class CompositeModificationPayloadTest {
         AppendEntries appendEntries =
             new AppendEntries(1, "member-1", 0, 100, entries, 1);
 
-        AppendEntriesMessages.AppendEntries o = (AppendEntriesMessages.AppendEntries) appendEntries.toSerializable();
+        AppendEntriesMessages.AppendEntries o = (AppendEntriesMessages.AppendEntries)
+                appendEntries.toSerializable(RaftVersions.HELIUM_VERSION);
 
         o.writeDelimitedTo(new FileOutputStream(SERIALIZE_OUT));
 
index e6bdf5aac379571ba0b130c1b3076e9c25f75299..6b6cf326be240421f44591d3a0b7bcc7591d3fef 100644 (file)
@@ -24,7 +24,7 @@ public class Server {
     public static class ServerActor extends UntypedActor {
 
         @Override public void onReceive(Object message) throws Exception {
-            if(AppendEntries.SERIALIZABLE_CLASS.equals(message.getClass())){
+            if(AppendEntries.LEGACY_SERIALIZABLE_CLASS.equals(message.getClass())){
                 AppendEntries appendEntries =
                     AppendEntries.fromSerializable(message);