BUG-5280: add frontend state lifecycle
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / main / java / org / opendaylight / controller / cluster / datastore / FrontendHistoryMetadataBuilder.java
index 6b901b4fa85988cc14ce4557d865a09d4a28d034..beed765a690590bd8174210861a06c7a2b78f09c 100644 (file)
@@ -8,6 +8,13 @@
 package org.opendaylight.controller.cluster.datastore;
 
 import com.google.common.base.Preconditions;
+import com.google.common.collect.Range;
+import com.google.common.collect.RangeSet;
+import com.google.common.collect.TreeRangeSet;
+import com.google.common.primitives.UnsignedLong;
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.Nonnull;
 import org.opendaylight.controller.cluster.access.concepts.ClientIdentifier;
 import org.opendaylight.controller.cluster.access.concepts.LocalHistoryIdentifier;
 import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
@@ -17,18 +24,23 @@ import org.opendaylight.yangtools.concepts.Identifiable;
 
 final class FrontendHistoryMetadataBuilder implements Builder<FrontendHistoryMetadata>,
         Identifiable<LocalHistoryIdentifier> {
+
+    private final Map<UnsignedLong, Boolean> closedTransactions;
+    private final RangeSet<UnsignedLong> purgedTransactions;
     private final LocalHistoryIdentifier identifier;
 
-    private long nextTransaction;
     private boolean closed;
 
     FrontendHistoryMetadataBuilder(final LocalHistoryIdentifier identifier) {
         this.identifier = Preconditions.checkNotNull(identifier);
+        this.purgedTransactions = TreeRangeSet.create();
+        this.closedTransactions = new HashMap<>(2);
     }
 
     FrontendHistoryMetadataBuilder(final ClientIdentifier clientId, final FrontendHistoryMetadata meta) {
         identifier = new LocalHistoryIdentifier(clientId, meta.getHistoryId(), meta.getCookie());
-        nextTransaction = meta.getNextTransaction();
+        closedTransactions = new HashMap<>(meta.getClosedTransactions());
+        purgedTransactions = TreeRangeSet.create(meta.getPurgedTransactions());
         closed = meta.isClosed();
     }
 
@@ -39,14 +51,42 @@ final class FrontendHistoryMetadataBuilder implements Builder<FrontendHistoryMet
 
     @Override
     public FrontendHistoryMetadata build() {
-        return new FrontendHistoryMetadata(identifier.getHistoryId(), identifier.getCookie(), nextTransaction, closed);
+        return new FrontendHistoryMetadata(identifier.getHistoryId(), identifier.getCookie(), closed,
+            closedTransactions, purgedTransactions);
     }
 
     void onHistoryClosed() {
+        Preconditions.checkState(identifier.getHistoryId() != 0);
         closed = true;
     }
 
+    void onTransactionAborted(final TransactionIdentifier txId) {
+        closedTransactions.put(UnsignedLong.fromLongBits(txId.getTransactionId()), Boolean.FALSE);
+    }
+
     void onTransactionCommitted(final TransactionIdentifier txId) {
-        nextTransaction = txId.getTransactionId() + 1;
+        closedTransactions.put(UnsignedLong.fromLongBits(txId.getTransactionId()), Boolean.TRUE);
+    }
+
+    void onTransactionPurged(final TransactionIdentifier txId) {
+        final UnsignedLong id = UnsignedLong.fromLongBits(txId.getTransactionId());
+        closedTransactions.remove(id);
+        purgedTransactions.add(Range.singleton(id));
+    }
+
+    /**
+     * Transform frontend metadata for a particular client history into its {@link LocalFrontendHistory} counterpart.
+     *
+     * @param shard parent shard
+     * @return Leader history state
+     */
+    @Nonnull AbstractFrontendHistory toLeaderState(@Nonnull final Shard shard) {
+        if (identifier.getHistoryId() == 0) {
+            return StandaloneFrontendHistory.recreate(shard.persistenceId(), identifier.getClientId(),
+                shard.getDataStore(), closedTransactions, purgedTransactions);
+        }
+
+        return LocalFrontendHistory.recreate(shard.persistenceId(), shard.getDataStore(),
+            shard.getDataStore().recreateTransactionChain(identifier, closed), closedTransactions, purgedTransactions);
     }
 }