CDS Frontend client actor should delete prior snapshots 72/42272/4
authorTom Pantelis <tpanteli@brocade.com>
Thu, 21 Jul 2016 19:57:35 +0000 (15:57 -0400)
committerTom Pantelis <tpanteli@brocade.com>
Fri, 29 Jul 2016 02:05:23 +0000 (02:05 +0000)
The RecoveringClientActorBehavior increments the last generation id and
saves a new snapshot. However the prior snapshots remain in akka
persistence - every time the controller is restarted a new snapshot file
is created. We should delete the prior snaphsots.

The snapshot file names were very long with escape chars b/c
FrontendIdentifier.toString is used for the frontend client actor's
persistence ID. We should use a shorter, more readable ID, so I changed
it to the form:

  member-1-frontend-datastore-config
  member-1-frontend-datastore-operational

Change-Id: I1c77c826729ca1a36497a1236ac99f7cc77efb72
Signed-off-by: Tom Pantelis <tpanteli@brocade.com>
opendaylight/md-sal/cds-access-api/src/main/java/org/opendaylight/controller/cluster/access/concepts/FrontendIdentifier.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/databroker/actors/dds/DistributedDataStoreClientActor.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/actors/client/AbstractClientActor.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/actors/client/InitialClientActorContext.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/actors/client/SavingClientActorBehavior.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/TransactionProxyTest.java

index fe85ef6e52e6eaf773356123f068bd5bae95ba5b..fc728130e644f91a13462c9fd7ecbb789964d7ad 100644 (file)
@@ -8,7 +8,6 @@
 package org.opendaylight.controller.cluster.access.concepts;
 
 import com.google.common.annotations.Beta;
 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.DataInput;
 import java.io.DataOutput;
 import com.google.common.base.Preconditions;
 import java.io.DataInput;
 import java.io.DataOutput;
@@ -108,10 +107,13 @@ public final class FrontendIdentifier implements WritableIdentifier {
         return memberName.equals(other.memberName) && clientType.equals(other.clientType);
     }
 
         return memberName.equals(other.memberName) && clientType.equals(other.clientType);
     }
 
+    public String toPersistentId() {
+        return memberName.getName() + "-frontend-" + clientType.getName();
+    }
+
     @Override
     public String toString() {
     @Override
     public String toString() {
-        return MoreObjects.toStringHelper(FrontendIdentifier.class).add("member", memberName)
-                .add("clientType", clientType).toString();
+        return toPersistentId();
     }
 
     private Object writeReplace() {
     }
 
     private Object writeReplace() {
index dd40f1e589b7a0f3034d83c7d64729566b11f6d2..11aeae4f9212a09e7f2030392930cee85678b4e6 100644 (file)
@@ -56,7 +56,7 @@ public final class DistributedDataStoreClientActor extends AbstractClientActor {
     }
 
     public static Props props(final @Nonnull MemberName memberName, @Nonnull final String storeName, final ActorContext ctx) {
     }
 
     public static Props props(final @Nonnull MemberName memberName, @Nonnull final String storeName, final ActorContext ctx) {
-        final String name = "DistributedDataStore:storeName='" + storeName + "'";
+        final String name = "datastore-" + storeName;
         final FrontendIdentifier frontendId = FrontendIdentifier.create(memberName, FrontendType.forName(name));
         return Props.create(DistributedDataStoreClientActor.class,
             () -> new DistributedDataStoreClientActor(frontendId, ctx));
         final FrontendIdentifier frontendId = FrontendIdentifier.create(memberName, FrontendType.forName(name));
         return Props.create(DistributedDataStoreClientActor.class,
             () -> new DistributedDataStoreClientActor(frontendId, ctx));
index 5f940842faac489d436cd9499194d5e884c02788..e8d93958e9ede1386fa78f5a844401c36aeb7056 100644 (file)
@@ -27,7 +27,7 @@ public abstract class AbstractClientActor extends UntypedPersistentActor {
 
     protected AbstractClientActor(final FrontendIdentifier frontendId) {
         currentBehavior = new RecoveringClientActorBehavior(
 
     protected AbstractClientActor(final FrontendIdentifier frontendId) {
         currentBehavior = new RecoveringClientActorBehavior(
-                new InitialClientActorContext(this, frontendId.toString()), frontendId);
+                new InitialClientActorContext(this, frontendId.toPersistentId()), frontendId);
     }
 
     @Override
     }
 
     @Override
index 5dce1cd3f13214df8efcfc1ffd6da65e0ada92c2..92b3d807ddc3c5d63e627366780b699bf0ac1688 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.controller.cluster.datastore.actors.client;
 
 import akka.actor.ActorSystem;
 package org.opendaylight.controller.cluster.datastore.actors.client;
 
 import akka.actor.ActorSystem;
+import akka.persistence.SnapshotSelectionCriteria;
 import com.google.common.base.Preconditions;
 import org.opendaylight.controller.cluster.access.concepts.ClientIdentifier;
 
 import com.google.common.base.Preconditions;
 import org.opendaylight.controller.cluster.access.concepts.ClientIdentifier;
 
@@ -27,6 +28,10 @@ final class InitialClientActorContext extends AbstractClientActorContext {
         actor.saveSnapshot(snapshot);
     }
 
         actor.saveSnapshot(snapshot);
     }
 
+    void deleteSnapshots(SnapshotSelectionCriteria criteria) {
+        actor.deleteSnapshots(criteria);
+    }
+
     ClientActorBehavior createBehavior(final ClientIdentifier clientId) {
         final ActorSystem system = actor.getContext().system();
         final ClientActorContext context = new ClientActorContext(self(), system.scheduler(), system.dispatcher(),
     ClientActorBehavior createBehavior(final ClientIdentifier clientId) {
         final ActorSystem system = actor.getContext().system();
         final ClientActorContext context = new ClientActorContext(self(), system.scheduler(), system.dispatcher(),
index f8977344c3ab9190397964d03f25fe4fdbaaad71..fc8b0056890e34eca5a1121cfafbdba41e25e961 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.controller.cluster.datastore.actors.client;
 
 import akka.persistence.SaveSnapshotFailure;
 import akka.persistence.SaveSnapshotSuccess;
 
 import akka.persistence.SaveSnapshotFailure;
 import akka.persistence.SaveSnapshotSuccess;
+import akka.persistence.SnapshotSelectionCriteria;
 import com.google.common.base.Preconditions;
 import org.opendaylight.controller.cluster.access.concepts.ClientIdentifier;
 import org.slf4j.Logger;
 import com.google.common.base.Preconditions;
 import org.opendaylight.controller.cluster.access.concepts.ClientIdentifier;
 import org.slf4j.Logger;
@@ -33,6 +34,11 @@ final class SavingClientActorBehavior extends RecoveredClientActorBehavior<Initi
             return null;
         } else if (command instanceof SaveSnapshotSuccess) {
             context().unstash();
             return null;
         } else if (command instanceof SaveSnapshotSuccess) {
             context().unstash();
+
+            SaveSnapshotSuccess saved = (SaveSnapshotSuccess)command;
+            context().deleteSnapshots(new SnapshotSelectionCriteria(saved.metadata().sequenceNr(),
+                    saved.metadata().timestamp() - 1, 0L, 0L));
+
             return context().createBehavior(myId);
         } else {
             LOG.debug("{}: stashing command {}", persistenceId(), command);
             return context().createBehavior(myId);
         } else {
             LOG.debug("{}: stashing command {}", persistenceId(), command);
index 2c36ca5cfae54b63797a1ac10fe8ca15fac5ccb6..f9ae1bbd0ff6dcb3524762b45c440eb7780eeb9d 100644 (file)
@@ -755,7 +755,7 @@ public class TransactionProxyTest extends AbstractTransactionProxyTest {
 
         Object id = transactionProxy.getIdentifier();
         assertNotNull("getIdentifier returned null", id);
 
         Object id = transactionProxy.getIdentifier();
         assertNotNull("getIdentifier returned null", id);
-        assertTrue("Invalid identifier: " + id, id.toString().contains(MemberName.forName(memberName).toString()));
+        assertTrue("Invalid identifier: " + id, id.toString().contains(memberName));
     }
 
     @Test
     }
 
     @Test