From d0b3c4b291e1f13a286a8979db7ef41560155c86 Mon Sep 17 00:00:00 2001 From: Tom Pantelis Date: Sun, 29 Mar 2015 08:57:40 -0400 Subject: [PATCH] Add new DeleteEntries class wih long "fromIndex" field Added a new DeleteEntries message class that defines the fromIndex field as a long. The previous DeleteEntries class (inner class of RaftActor) defined it as an int which could cause rollover. The previous DeleteEntries must be kept for the time being for backwards compatibility as instances are persisted. Change-Id: I774128d9a1af2410a23d2739c37484a508c8a80f Signed-off-by: Tom Pantelis --- .../controller/cluster/raft/RaftActor.java | 6 ++++ .../raft/RaftActorRecoverySupport.java | 5 ++- .../cluster/raft/ReplicatedLogImpl.java | 6 ++-- .../raft/base/messages/DeleteEntries.java | 36 +++++++++++++++++++ .../raft/RaftActorRecoverySupportTest.java | 20 ++++++++++- .../cluster/raft/RaftActorTest.java | 7 +++- .../raft/base/messages/DeleteEntriesTest.java | 30 ++++++++++++++++ 7 files changed, 104 insertions(+), 6 deletions(-) create mode 100644 opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/DeleteEntries.java create mode 100644 opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/base/messages/DeleteEntriesTest.java diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActor.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActor.java index e98b1f74c4..2185ffdef3 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActor.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActor.java @@ -571,6 +571,12 @@ public abstract class RaftActor extends AbstractUntypedPersistentActor { return getRaftActorContext().hasFollowers(); } + /** + * @deprecated Deprecated in favor of {@link org.opendaylight.controller.cluster.raft.base.messages.DeleteEntriesTest} + * whose type for fromIndex is long instead of int. This class was kept for backwards + * compatibility with Helium. + */ + @Deprecated static class DeleteEntries implements Serializable { private static final long serialVersionUID = 1L; private final int fromIndex; diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActorRecoverySupport.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActorRecoverySupport.java index d2c14de73d..5dc8361cc4 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActorRecoverySupport.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActorRecoverySupport.java @@ -11,10 +11,10 @@ import akka.persistence.RecoveryCompleted; import akka.persistence.SnapshotOffer; import com.google.common.base.Stopwatch; import org.opendaylight.controller.cluster.DataPersistenceProvider; -import org.opendaylight.controller.cluster.raft.RaftActor.DeleteEntries; import org.opendaylight.controller.cluster.raft.RaftActor.UpdateElectionTerm; import org.opendaylight.controller.cluster.raft.base.messages.ApplyJournalEntries; import org.opendaylight.controller.cluster.raft.base.messages.ApplyLogEntries; +import org.opendaylight.controller.cluster.raft.base.messages.DeleteEntries; import org.opendaylight.controller.cluster.raft.behaviors.RaftActorBehavior; import org.slf4j.Logger; @@ -57,6 +57,9 @@ class RaftActorRecoverySupport { onRecoveredApplyLogEntries(((ApplyJournalEntries) message).getToIndex()); } else if (message instanceof DeleteEntries) { replicatedLog().removeFrom(((DeleteEntries) message).getFromIndex()); + } else if (message instanceof org.opendaylight.controller.cluster.raft.RaftActor.DeleteEntries) { + // Handle this message for backwards compatibility with pre-Lithium versions. + replicatedLog().removeFrom(((org.opendaylight.controller.cluster.raft.RaftActor.DeleteEntries) message).getFromIndex()); } else if (message instanceof UpdateElectionTerm) { context.getTermInformation().update(((UpdateElectionTerm) message).getCurrentTerm(), ((UpdateElectionTerm) message).getVotedFor()); diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLogImpl.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLogImpl.java index 5a77b9aea3..1cfe153869 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLogImpl.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLogImpl.java @@ -11,7 +11,7 @@ import akka.japi.Procedure; import java.util.Collections; import java.util.List; import org.opendaylight.controller.cluster.DataPersistenceProvider; -import org.opendaylight.controller.cluster.raft.RaftActor.DeleteEntries; +import org.opendaylight.controller.cluster.raft.base.messages.DeleteEntries; import org.opendaylight.controller.cluster.raft.behaviors.RaftActorBehavior; /** @@ -27,7 +27,7 @@ class ReplicatedLogImpl extends AbstractReplicatedLogImpl { private final Procedure deleteProcedure = new Procedure() { @Override - public void apply(DeleteEntries param) { + public void apply(DeleteEntries notUsed) { } }; @@ -56,7 +56,7 @@ class ReplicatedLogImpl extends AbstractReplicatedLogImpl { // FIXME: Maybe this should be done after the command is saved long adjustedIndex = removeFrom(logEntryIndex); if(adjustedIndex >= 0) { - persistence.persist(new DeleteEntries((int)adjustedIndex), deleteProcedure); + persistence.persist(new DeleteEntries(adjustedIndex), deleteProcedure); } } diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/DeleteEntries.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/DeleteEntries.java new file mode 100644 index 0000000000..97742c0457 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/DeleteEntries.java @@ -0,0 +1,36 @@ +/* + * 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.base.messages; + +import java.io.Serializable; + +/** + * Internal message that is stored in the akka's persistent journal to delete journal entries. + * + * @author Thomas Pantelis + */ +public class DeleteEntries implements Serializable { + private static final long serialVersionUID = 1L; + + private final long fromIndex; + + public DeleteEntries(long fromIndex) { + this.fromIndex = fromIndex; + } + + public long getFromIndex() { + return fromIndex; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("DeleteEntries [fromIndex=").append(fromIndex).append("]"); + return builder.toString(); + } +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/RaftActorRecoverySupportTest.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/RaftActorRecoverySupportTest.java index c30de5e7f2..7420fc4e6c 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/RaftActorRecoverySupportTest.java +++ b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/RaftActorRecoverySupportTest.java @@ -24,10 +24,10 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.opendaylight.controller.cluster.DataPersistenceProvider; -import org.opendaylight.controller.cluster.raft.RaftActor.DeleteEntries; import org.opendaylight.controller.cluster.raft.RaftActor.UpdateElectionTerm; import org.opendaylight.controller.cluster.raft.base.messages.ApplyJournalEntries; import org.opendaylight.controller.cluster.raft.base.messages.ApplyLogEntries; +import org.opendaylight.controller.cluster.raft.base.messages.DeleteEntries; import org.opendaylight.controller.cluster.raft.behaviors.RaftActorBehavior; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -231,6 +231,22 @@ public class RaftActorRecoverySupportTest { verifyNoMoreInteractions(mockCohort); } + @Test + public void testOnDeprecatedDeleteEntries() { + ReplicatedLog replicatedLog = context.getReplicatedLog(); + replicatedLog.append(new MockRaftActorContext.MockReplicatedLogEntry(1, + 0, new MockRaftActorContext.MockPayload("0"))); + replicatedLog.append(new MockRaftActorContext.MockReplicatedLogEntry(1, + 1, new MockRaftActorContext.MockPayload("1"))); + replicatedLog.append(new MockRaftActorContext.MockReplicatedLogEntry(1, + 2, new MockRaftActorContext.MockPayload("2"))); + + sendMessageToSupport(new org.opendaylight.controller.cluster.raft.RaftActor.DeleteEntries(1)); + + assertEquals("Journal log size", 1, context.getReplicatedLog().size()); + assertEquals("Last index", 0, context.getReplicatedLog().lastIndex()); + } + @Test public void testOnDeleteEntries() { ReplicatedLog replicatedLog = context.getReplicatedLog(); @@ -274,6 +290,8 @@ public class RaftActorRecoverySupportTest { sendMessageToSupport(new DeleteEntries(5)); + sendMessageToSupport(new org.opendaylight.controller.cluster.raft.RaftActor.DeleteEntries(5)); + assertEquals("Journal log size", 0, context.getReplicatedLog().size()); assertEquals("Last index", -1, context.getReplicatedLog().lastIndex()); assertEquals("Last applied", -1, context.getLastApplied()); diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/RaftActorTest.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/RaftActorTest.java index 9187f36954..d2b65db85b 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/RaftActorTest.java +++ b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/RaftActorTest.java @@ -45,7 +45,6 @@ import org.opendaylight.controller.cluster.NonPersistentDataProvider; import org.opendaylight.controller.cluster.datastore.DataPersistenceProviderMonitor; import org.opendaylight.controller.cluster.notifications.LeaderStateChanged; import org.opendaylight.controller.cluster.notifications.RoleChanged; -import org.opendaylight.controller.cluster.raft.RaftActor.DeleteEntries; import org.opendaylight.controller.cluster.raft.RaftActor.UpdateElectionTerm; import org.opendaylight.controller.cluster.raft.base.messages.ApplyJournalEntries; import org.opendaylight.controller.cluster.raft.base.messages.ApplyLogEntries; @@ -53,6 +52,7 @@ import org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot; import org.opendaylight.controller.cluster.raft.base.messages.ApplyState; import org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshot; import org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshotReply; +import org.opendaylight.controller.cluster.raft.base.messages.DeleteEntries; import org.opendaylight.controller.cluster.raft.base.messages.SendHeartBeat; import org.opendaylight.controller.cluster.raft.behaviors.Follower; import org.opendaylight.controller.cluster.raft.behaviors.Leader; @@ -240,6 +240,10 @@ public class RaftActorTest extends AbstractActorTest { DeleteEntries deleteEntries = new DeleteEntries(1); mockRaftActor.handleRecover(deleteEntries); + org.opendaylight.controller.cluster.raft.RaftActor.DeleteEntries deprecatedDeleteEntries = + new org.opendaylight.controller.cluster.raft.RaftActor.DeleteEntries(1); + mockRaftActor.handleRecover(deprecatedDeleteEntries); + UpdateElectionTerm updateElectionTerm = new UpdateElectionTerm(5, "member2"); mockRaftActor.handleRecover(updateElectionTerm); @@ -248,6 +252,7 @@ public class RaftActorTest extends AbstractActorTest { verify(mockSupport).handleRecoveryMessage(same(applyJournalEntries)); verify(mockSupport).handleRecoveryMessage(same(applyLogEntries)); verify(mockSupport).handleRecoveryMessage(same(deleteEntries)); + verify(mockSupport).handleRecoveryMessage(same(deprecatedDeleteEntries)); verify(mockSupport).handleRecoveryMessage(same(updateElectionTerm)); } diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/base/messages/DeleteEntriesTest.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/base/messages/DeleteEntriesTest.java new file mode 100644 index 0000000000..55d2bcc688 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/base/messages/DeleteEntriesTest.java @@ -0,0 +1,30 @@ +/* + * 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.base.messages; + +import org.apache.commons.lang.SerializationUtils; +import org.junit.Assert; +import org.junit.Test; + +/** + * Unit tests for DeleteEntries. + * + * @author Thomas Pantelis + */ +public class DeleteEntriesTest { + + @Test + public void testSerialization() { + + DeleteEntries deleteEntries = new DeleteEntries(11); + + DeleteEntries clone = (DeleteEntries) SerializationUtils.clone(deleteEntries); + + Assert.assertEquals("getFromIndex", 11, clone.getFromIndex()); + } +} -- 2.36.6