From: Robert Varga Date: Thu, 29 Jun 2017 16:47:14 +0000 (+0200) Subject: BUG-8676: add UnsignedLongRangeSet X-Git-Tag: release/nitrogen~52 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=a7aab5b8d7692d12928944a0d3da818571e324cc BUG-8676: add UnsignedLongRangeSet This patch adds the wrapper class and updates users to use it directly. The implementation itself is not changed, that will be done in a follow-up patch. Change-Id: Ie240ca5c3c9fc1448629bb5db6ecfa1029f66b8f Signed-off-by: Robert Varga --- diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/FrontendClientMetadataBuilder.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/FrontendClientMetadataBuilder.java index 519a360b06..4ffa27c60d 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/FrontendClientMetadataBuilder.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/FrontendClientMetadataBuilder.java @@ -11,10 +11,6 @@ import com.google.common.base.MoreObjects; import com.google.common.base.Preconditions; import com.google.common.base.Verify; 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; @@ -24,6 +20,7 @@ import org.opendaylight.controller.cluster.access.concepts.LocalHistoryIdentifie 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; @@ -34,14 +31,14 @@ final class FrontendClientMetadataBuilder implements Builder currentHistories = new HashMap<>(); - private final RangeSet purgedHistories; + private final UnsignedLongRangeSet purgedHistories; private final ClientIdentifier identifier; private final String shardName; FrontendClientMetadataBuilder(final String shardName, final ClientIdentifier identifier) { this.shardName = Preconditions.checkNotNull(shardName); this.identifier = Preconditions.checkNotNull(identifier); - purgedHistories = TreeRangeSet.create(); + purgedHistories = UnsignedLongRangeSet.create(); // History for stand-alone transactions is always present final LocalHistoryIdentifier standaloneId = standaloneHistoryId(); @@ -51,7 +48,7 @@ final class FrontendClientMetadataBuilder implements Builder { private final Map localHistories; // RangeSet performs automatic merging, hence we keep minimal state tracking information - private final RangeSet purgedHistories; + private final UnsignedLongRangeSet purgedHistories; // Used for all standalone transactions private final AbstractFrontendHistory standaloneHistory; @@ -71,12 +68,12 @@ final class LeaderFrontendState implements Identifiable { // - per-RequestException throw counters LeaderFrontendState(final String persistenceId, final ClientIdentifier clientId, final ShardDataTree tree) { - this(persistenceId, clientId, tree, TreeRangeSet.create(), StandaloneFrontendHistory.create(persistenceId, - clientId, tree), new HashMap<>()); + this(persistenceId, clientId, tree, UnsignedLongRangeSet.create(), + StandaloneFrontendHistory.create(persistenceId, clientId, tree), new HashMap<>()); } LeaderFrontendState(final String persistenceId, final ClientIdentifier clientId, final ShardDataTree tree, - final RangeSet purgedHistories, final AbstractFrontendHistory standaloneHistory, + final UnsignedLongRangeSet purgedHistories, final AbstractFrontendHistory standaloneHistory, final Map localHistories) { this.persistenceId = Preconditions.checkNotNull(persistenceId); this.clientId = Preconditions.checkNotNull(clientId); @@ -133,9 +130,9 @@ final class LeaderFrontendState implements Identifiable { // We have not found the history. Before we create it we need to check history ID sequencing so that we do not // end up resurrecting a purged history. - if (purgedHistories.contains(UnsignedLong.fromLongBits(historyId.getHistoryId()))) { + if (purgedHistories.contains(historyId.getHistoryId())) { LOG.debug("{}: rejecting purged request {}", persistenceId, request); - throw new DeadHistoryException(purgedHistories); + throw new DeadHistoryException(purgedHistories.toImmutable()); } // Update last history we have seen @@ -179,8 +176,7 @@ final class LeaderFrontendState implements Identifiable { } LOG.debug("{}: purging history {}", persistenceId, id); - final UnsignedLong ul = UnsignedLong.fromLongBits(id.getHistoryId()); - purgedHistories.add(Range.closedOpen(ul, UnsignedLong.ONE.plus(ul))); + purgedHistories.add(id.getHistoryId()); existing.purge(request.getSequence(), envelope, now); return null; } @@ -196,9 +192,9 @@ final class LeaderFrontendState implements Identifiable { if (lhId.getHistoryId() != 0) { history = localHistories.get(lhId); if (history == null) { - if (purgedHistories.contains(UnsignedLong.fromLongBits(lhId.getHistoryId()))) { + if (purgedHistories.contains(lhId.getHistoryId())) { LOG.warn("{}: rejecting request {} to purged history", persistenceId, request); - throw new DeadHistoryException(purgedHistories); + throw new DeadHistoryException(purgedHistories.toImmutable()); } LOG.warn("{}: rejecting unknown history request {}", persistenceId, request); diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/utils/UnsignedLongRangeSet.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/utils/UnsignedLongRangeSet.java new file mode 100644 index 0000000000..eeb39eaef5 --- /dev/null +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/utils/UnsignedLongRangeSet.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017 Pantheon Technologies, s.r.o. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.cluster.datastore.utils; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableRangeSet; +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 org.opendaylight.yangtools.concepts.Mutable; + +/** + * Utility {@link RangeSet}-like class, specialized for holding {@link UnsignedLong}. It does not directly implement + * the {@link RangeSet} interface, but allows converting to and from it. Internal implementation takes advantage of + * knowing that {@link UnsignedLong} is a discrete type and that it can be stored in a long. + * + * @author Robert Varga + */ +@Beta +public final class UnsignedLongRangeSet implements Mutable { + // FIXME: this is just to get us started + private final RangeSet rangeset; + + private UnsignedLongRangeSet(final RangeSet rangeset) { + this.rangeset = Preconditions.checkNotNull(rangeset); + } + + public static UnsignedLongRangeSet create() { + return new UnsignedLongRangeSet(TreeRangeSet.create()); + } + + public static UnsignedLongRangeSet create(final RangeSet input) { + return new UnsignedLongRangeSet(TreeRangeSet.create(input)); + } + + public RangeSet toImmutable() { + return ImmutableRangeSet.copyOf(rangeset); + } + + public void add(final long longBits) { + add(UnsignedLong.fromLongBits(longBits)); + } + + public void add(final UnsignedLong value) { + rangeset.add(Range.closedOpen(value, UnsignedLong.ONE.plus(value))); + } + + public boolean contains(final UnsignedLong value) { + return rangeset.contains(value); + } + + public boolean contains(final long longBits) { + return contains(UnsignedLong.fromLongBits(longBits)); + } + + public UnsignedLongRangeSet copy() { + return new UnsignedLongRangeSet(TreeRangeSet.create(rangeset)); + } +}