Migrate nullness annotations
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / main / java / org / opendaylight / controller / cluster / datastore / FrontendClientMetadataBuilder.java
index ec2cdb6daa209a9f7ad2b2474ccf454166f9da57..763b2e92cda777107789faa13489fcc1d9ed1c03 100644 (file)
@@ -7,22 +7,21 @@
  */
 package org.opendaylight.controller.cluster.datastore;
 
-import com.google.common.base.Preconditions;
-import com.google.common.base.Verify;
+import static com.google.common.base.Verify.verify;
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.base.MoreObjects;
 import com.google.common.collect.Collections2;
-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 javax.annotation.concurrent.NotThreadSafe;
+import org.eclipse.jdt.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;
 import org.opendaylight.controller.cluster.datastore.persisted.FrontendClientMetadata;
 import org.opendaylight.controller.cluster.datastore.persisted.FrontendHistoryMetadata;
+import org.opendaylight.controller.cluster.datastore.utils.UnsignedLongRangeSet;
 import org.opendaylight.yangtools.concepts.Builder;
 import org.opendaylight.yangtools.concepts.Identifiable;
 import org.slf4j.Logger;
@@ -33,21 +32,25 @@ final class FrontendClientMetadataBuilder implements Builder<FrontendClientMetad
     private static final Logger LOG = LoggerFactory.getLogger(FrontendClientMetadataBuilder.class);
 
     private final Map<LocalHistoryIdentifier, FrontendHistoryMetadataBuilder> currentHistories = new HashMap<>();
-    private final RangeSet<UnsignedLong> purgedHistories;
+    private final UnsignedLongRangeSet purgedHistories;
+    private final LocalHistoryIdentifier standaloneId;
     private final ClientIdentifier identifier;
+    private final String shardName;
 
-    FrontendClientMetadataBuilder(final ClientIdentifier identifier) {
-        this.identifier = Preconditions.checkNotNull(identifier);
-        purgedHistories = TreeRangeSet.create();
+    FrontendClientMetadataBuilder(final String shardName, final ClientIdentifier identifier) {
+        this.shardName = requireNonNull(shardName);
+        this.identifier = requireNonNull(identifier);
+        purgedHistories = UnsignedLongRangeSet.create();
 
         // History for stand-alone transactions is always present
-        final LocalHistoryIdentifier standaloneId = standaloneHistoryId();
+        standaloneId = standaloneHistoryId();
         currentHistories.put(standaloneId, new FrontendHistoryMetadataBuilder(standaloneId));
     }
 
-    FrontendClientMetadataBuilder(final FrontendClientMetadata meta) {
-        this.identifier = Preconditions.checkNotNull(meta.getIdentifier());
-        purgedHistories = TreeRangeSet.create(meta.getPurgedHistories());
+    FrontendClientMetadataBuilder(final String shardName, final FrontendClientMetadata meta) {
+        this.shardName = requireNonNull(shardName);
+        this.identifier = meta.getIdentifier();
+        purgedHistories = UnsignedLongRangeSet.create(meta.getPurgedHistories());
 
         for (FrontendHistoryMetadata h : meta.getCurrentHistories()) {
             final FrontendHistoryMetadataBuilder b = new FrontendHistoryMetadataBuilder(identifier, h);
@@ -55,10 +58,10 @@ final class FrontendClientMetadataBuilder implements Builder<FrontendClientMetad
         }
 
         // Sanity check and recovery
-        final LocalHistoryIdentifier standaloneId = standaloneHistoryId();
+        standaloneId = standaloneHistoryId();
         if (!currentHistories.containsKey(standaloneId)) {
-            LOG.warn("Client {} recovered histories {} do not contain stand-alone history, attempting recovery",
-                identifier, currentHistories);
+            LOG.warn("{}: Client {} recovered histories {} do not contain stand-alone history, attempting recovery",
+                shardName, identifier, currentHistories);
             currentHistories.put(standaloneId, new FrontendHistoryMetadataBuilder(standaloneId));
         }
     }
@@ -69,7 +72,7 @@ final class FrontendClientMetadataBuilder implements Builder<FrontendClientMetad
 
     @Override
     public FrontendClientMetadata build() {
-        return new FrontendClientMetadata(identifier, purgedHistories,
+        return new FrontendClientMetadata(identifier, purgedHistories.toImmutable(),
             Collections2.transform(currentHistories.values(), FrontendHistoryMetadataBuilder::build));
     }
 
@@ -83,9 +86,9 @@ final class FrontendClientMetadataBuilder implements Builder<FrontendClientMetad
         final FrontendHistoryMetadataBuilder oldMeta = currentHistories.putIfAbsent(historyId, newMeta);
         if (oldMeta != null) {
             // This should not be happening, warn about it
-            LOG.warn("Reused local history {}", historyId);
+            LOG.warn("{}: Reused local history {}", shardName, historyId);
         } else {
-            LOG.debug("Created local history {}", historyId);
+            LOG.debug("{}: Created local history {}", shardName, historyId);
         }
     }
 
@@ -93,30 +96,35 @@ final class FrontendClientMetadataBuilder implements Builder<FrontendClientMetad
         final FrontendHistoryMetadataBuilder builder = currentHistories.get(historyId);
         if (builder != null) {
             builder.onHistoryClosed();
-            LOG.debug("Closed history {}", historyId);
+            LOG.debug("{}: Closed history {}", shardName, historyId);
         } else {
-            LOG.warn("Closed unknown history {}, ignoring", historyId);
+            LOG.warn("{}: Closed unknown history {}, ignoring", shardName, historyId);
         }
     }
 
     void onHistoryPurged(final LocalHistoryIdentifier historyId) {
         final FrontendHistoryMetadataBuilder history = currentHistories.remove(historyId);
+        final long historyBits = historyId.getHistoryId();
         if (history == null) {
-            LOG.warn("Purging unknown history {}", historyId);
+            if (!purgedHistories.contains(historyBits)) {
+                purgedHistories.add(historyBits);
+                LOG.warn("{}: Purging unknown history {}", shardName, historyId);
+            } else {
+                LOG.warn("{}: Duplicate purge of history {}", shardName, historyId);
+            }
+        } else {
+            purgedHistories.add(historyBits);
+            LOG.debug("{}: Purged history {}", shardName, historyId);
         }
-
-        // XXX: do we need to account for cookies?
-        purgedHistories.add(Range.singleton(UnsignedLong.fromLongBits(historyId.getHistoryId())));
-        LOG.debug("Purged history {}", historyId);
     }
 
     void onTransactionAborted(final TransactionIdentifier txId) {
         final FrontendHistoryMetadataBuilder history = getHistory(txId);
         if (history != null) {
             history.onTransactionAborted(txId);
-            LOG.debug("Committed transaction {}", txId);
+            LOG.debug("{}: Aborted transaction {}", shardName, txId);
         } else {
-            LOG.warn("Unknown history for aborted transaction {}, ignoring", txId);
+            LOG.warn("{}: Unknown history for aborted transaction {}, ignoring", shardName, txId);
         }
     }
 
@@ -124,9 +132,9 @@ final class FrontendClientMetadataBuilder implements Builder<FrontendClientMetad
         final FrontendHistoryMetadataBuilder history = getHistory(txId);
         if (history != null) {
             history.onTransactionCommitted(txId);
-            LOG.debug("Aborted transaction {}", txId);
+            LOG.debug("{}: Committed transaction {}", shardName, txId);
         } else {
-            LOG.warn("Unknown history for commited transaction {}, ignoring", txId);
+            LOG.warn("{}: Unknown history for commited transaction {}, ignoring", shardName, txId);
         }
     }
 
@@ -134,9 +142,9 @@ final class FrontendClientMetadataBuilder implements Builder<FrontendClientMetad
         final FrontendHistoryMetadataBuilder history = getHistory(txId);
         if (history != null) {
             history.onTransactionPurged(txId);
-            LOG.debug("Purged transaction {}", txId);
+            LOG.debug("{}: Purged transaction {}", shardName, txId);
         } else {
-            LOG.warn("Unknown history for purged transaction {}, ignoring", txId);
+            LOG.warn("{}: Unknown history for purged transaction {}, ignoring", shardName, txId);
         }
     }
 
@@ -146,14 +154,14 @@ final class FrontendClientMetadataBuilder implements Builder<FrontendClientMetad
      * @param shard parent shard
      * @return Leader frontend state
      */
-    @Nonnull LeaderFrontendState toLeaderState(@Nonnull final Shard shard) {
+    @NonNull LeaderFrontendState toLeaderState(final @NonNull Shard shard) {
         // Note: we have to make sure to *copy* all current state and not leak any views, otherwise leader/follower
         //       interactions would get intertwined leading to inconsistencies.
         final Map<LocalHistoryIdentifier, LocalFrontendHistory> histories = new HashMap<>();
         for (FrontendHistoryMetadataBuilder e : currentHistories.values()) {
             if (e.getIdentifier().getHistoryId() != 0) {
                 final AbstractFrontendHistory state = e.toLeaderState(shard);
-                Verify.verify(state instanceof LocalFrontendHistory);
+                verify(state instanceof LocalFrontendHistory, "Unexpected state %s", state);
                 histories.put(e.getIdentifier(), (LocalFrontendHistory) state);
             }
         }
@@ -169,10 +177,24 @@ final class FrontendClientMetadataBuilder implements Builder<FrontendClientMetad
         }
 
         return new LeaderFrontendState(shard.persistenceId(), getIdentifier(), shard.getDataStore(),
-            TreeRangeSet.create(purgedHistories), singleHistory, histories);
+            purgedHistories.copy(), singleHistory, histories);
     }
 
     private FrontendHistoryMetadataBuilder getHistory(final TransactionIdentifier txId) {
-        return currentHistories.get(txId.getHistoryId());
+        LocalHistoryIdentifier historyId = txId.getHistoryId();
+        if (historyId.getHistoryId() == 0 && historyId.getCookie() != 0) {
+            // We are pre-creating the history for free-standing transactions with a zero cookie, hence our lookup
+            // needs to account for that.
+            LOG.debug("{}: looking up {} instead of {}", shardName, standaloneId, historyId);
+            historyId = standaloneId;
+        }
+
+        return currentHistories.get(historyId);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this).add("identifier", identifier).add("current", currentHistories)
+                .add("purged", purgedHistories).toString();
     }
 }