BUG-5280: fix invalid local transaction replay
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / main / java / org / opendaylight / controller / cluster / datastore / FrontendClientMetadataBuilder.java
index 8a0ce605dfd18bb7bcd205c8cdebce9b6691f356..a13899c354b165526674469bbe02f8c9ad90cc12 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.controller.cluster.datastore;
 
+import com.google.common.base.MoreObjects;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Verify;
 import com.google.common.collect.Collections2;
@@ -39,6 +40,10 @@ final class FrontendClientMetadataBuilder implements Builder<FrontendClientMetad
     FrontendClientMetadataBuilder(final ClientIdentifier identifier) {
         this.identifier = Preconditions.checkNotNull(identifier);
         purgedHistories = TreeRangeSet.create();
+
+        // History for stand-alone transactions is always present
+        final LocalHistoryIdentifier standaloneId = standaloneHistoryId();
+        currentHistories.put(standaloneId, new FrontendHistoryMetadataBuilder(standaloneId));
     }
 
     FrontendClientMetadataBuilder(final FrontendClientMetadata meta) {
@@ -49,6 +54,18 @@ final class FrontendClientMetadataBuilder implements Builder<FrontendClientMetad
             final FrontendHistoryMetadataBuilder b = new FrontendHistoryMetadataBuilder(identifier, h);
             currentHistories.put(b.getIdentifier(), b);
         }
+
+        // Sanity check and recovery
+        final LocalHistoryIdentifier standaloneId = standaloneHistoryId();
+        if (!currentHistories.containsKey(standaloneId)) {
+            LOG.warn("Client {} recovered histories {} do not contain stand-alone history, attempting recovery",
+                identifier, currentHistories);
+            currentHistories.put(standaloneId, new FrontendHistoryMetadataBuilder(standaloneId));
+        }
+    }
+
+    private LocalHistoryIdentifier standaloneHistoryId() {
+        return new LocalHistoryIdentifier(identifier, 0);
     }
 
     @Override
@@ -159,4 +176,10 @@ final class FrontendClientMetadataBuilder implements Builder<FrontendClientMetad
     private FrontendHistoryMetadataBuilder getHistory(final TransactionIdentifier txId) {
         return currentHistories.get(txId.getHistoryId());
     }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this).add("identifier", identifier).add("current", currentHistories)
+                .add("purged", purgedHistories).toString();
+    }
 }