Allow AbstractClientActor generation to start from non-zero 09/85509/1
authorRobert Varga <robert.varga@pantheon.tech>
Fri, 25 Oct 2019 13:50:59 +0000 (15:50 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Sun, 3 Nov 2019 07:30:43 +0000 (08:30 +0100)
This adds the ability to override the initial generation seeded
into persistence. The requested generation is controlled via
system properties on a per-client-type basis:

org.opendaylight.controller.cluster.access.client.initial.generation.datastore-operational = 500

This is useful during bringup of a zombie node, which lost all
of its persistence, for example during recovery from backup.

JIRA: CONTROLLER-1626
Change-Id: If32487fedcb5b6b39551a3359c069df940a6a725
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
(cherry picked from commit 2be60a19ed99fe7d33a24f7db8af3510f7ea835f)
(cherry picked from commit 67afa21bc175d7a6ebd3df7607644d4c9326710e)

opendaylight/md-sal/cds-access-client/src/main/java/org/opendaylight/controller/cluster/access/client/RecoveringClientActorBehavior.java
opendaylight/md-sal/sal-cluster-admin-impl/src/main/java/org/opendaylight/controller/cluster/datastore/admin/ClusterAdminRpcService.java

index 795c98d7215cb7d3548d2c8b85ca37dea38958a4..f40deab30d5bed8bbf1a7eed8da3e76653ce27bf 100644 (file)
@@ -23,6 +23,14 @@ import org.slf4j.LoggerFactory;
  */
 final class RecoveringClientActorBehavior extends AbstractClientActorBehavior<InitialClientActorContext> {
     private static final Logger LOG = LoggerFactory.getLogger(RecoveringClientActorBehavior.class);
+
+    /*
+     * Base for the property name which overrides the initial generation when we fail to find anything from persistence.
+     * The actual property name has the frontend type name appended.
+     */
+    private static final String GENERATION_OVERRIDE_PROP_BASE =
+            "org.opendaylight.controller.cluster.access.client.initial.generation.";
+
     private final FrontendIdentifier currentFrontend;
     private ClientIdentifier lastId = null;
 
@@ -49,7 +57,7 @@ final class RecoveringClientActorBehavior extends AbstractClientActorBehavior<In
 
                 nextId = ClientIdentifier.create(currentFrontend, lastId.getGeneration() + 1);
             } else {
-                nextId = ClientIdentifier.create(currentFrontend, 0);
+                nextId = ClientIdentifier.create(currentFrontend, initialGeneration());
             }
 
             LOG.debug("{}: persisting new identifier {}", persistenceId(), nextId);
@@ -64,4 +72,25 @@ final class RecoveringClientActorBehavior extends AbstractClientActorBehavior<In
 
         return this;
     }
-}
\ No newline at end of file
+
+    private long initialGeneration() {
+        final String propName = GENERATION_OVERRIDE_PROP_BASE + currentFrontend.getClientType().getName();
+        final String propValue = System.getProperty(propName);
+        if (propValue == null) {
+            LOG.debug("{}: no initial generation override, starting from 0", persistenceId());
+            return 0;
+        }
+
+        final long ret;
+        try {
+            ret = Long.parseUnsignedLong(propValue);
+        } catch (NumberFormatException e) {
+            LOG.warn("{}: failed to parse initial generation override '{}', starting from 0", persistenceId(),
+                propValue, e);
+            return 0;
+        }
+
+        LOG.info("{}: initial generation set to {}", persistenceId(), ret);
+        return ret;
+    }
+}
index fa6d5283a4c6dcdeaebd71e594f720532eeeba66..d27d615eb635f74b49b72d469a7bb86f91a72ed5 100644 (file)
@@ -815,15 +815,15 @@ public class ClusterAdminRpcService implements ClusterAdminService {
         final ImmutableMap.Builder<ShardIdentifier, ListenableFuture<GetKnownClientsReply>> builder =
                 ImmutableMap.builder();
 
-        addAllShardsClients(builder, DataStoreType.Config, configDataStore.getActorUtils());
-        addAllShardsClients(builder, DataStoreType.Operational, operDataStore.getActorUtils());
+        addAllShardsClients(builder, DataStoreType.Config, configDataStore.getActorContext());
+        addAllShardsClients(builder, DataStoreType.Operational, operDataStore.getActorContext());
 
         return builder.build();
     }
 
     private static void addAllShardsClients(
             final ImmutableMap.Builder<ShardIdentifier, ListenableFuture<GetKnownClientsReply>> builder,
-            final DataStoreType type, final ActorUtils utils) {
+            final DataStoreType type, final ActorContext utils) {
         for (String shardName : utils.getConfiguration().getAllShardNames()) {
             final SettableFuture<GetKnownClientsReply> future = SettableFuture.create();
             builder.put(new ShardIdentifier(type, shardName), future);