You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by sl...@apache.org on 2015/07/22 18:05:42 UTC
[13/15] cassandra git commit: Simplify some 8099's implementations
http://git-wip-us.apache.org/repos/asf/cassandra/blob/24575994/src/java/org/apache/cassandra/db/LivenessInfo.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/LivenessInfo.java b/src/java/org/apache/cassandra/db/LivenessInfo.java
index 89971d1..8f7b1c2 100644
--- a/src/java/org/apache/cassandra/db/LivenessInfo.java
+++ b/src/java/org/apache/cassandra/db/LivenessInfo.java
@@ -17,128 +17,154 @@
*/
package org.apache.cassandra.db;
+import java.util.Objects;
import java.security.MessageDigest;
-import org.apache.cassandra.db.*;
+import org.apache.cassandra.config.CFMetaData;
+import org.apache.cassandra.serializers.MarshalException;
+import org.apache.cassandra.utils.FBUtilities;
/**
- * Groups the informations necessary to decide the liveness of a given piece of
- * column data.
+ * Stores the information relating to the liveness of the primary key columns of a row.
* <p>
- * In practice, a {@code LivenessInfo} groups 3 informations:
- * 1) the data timestamp. It is sometimes allowed for a given piece of data to have
- * no timestamp (for {@link Row#partitionKeyLivenessInfo} more precisely), but if that
- * is the case it means the data has no liveness info at all.
- * 2) the data ttl if relevant.
- * 2) the data local deletion time if relevant (that is, if either the data has a ttl or is deleted).
+ * A {@code LivenessInfo} can first be empty. If it isn't, it contains at least a timestamp,
+ * which is the timestamp for the row primary key columns. On top of that, the info can be
+ * ttl'ed, in which case the {@code LivenessInfo} also has both a ttl and a local expiration time.
*/
-public interface LivenessInfo extends Aliasable<LivenessInfo>
+public class LivenessInfo
{
public static final long NO_TIMESTAMP = Long.MIN_VALUE;
public static final int NO_TTL = 0;
- public static final int NO_DELETION_TIME = Integer.MAX_VALUE;
+ public static final int NO_EXPIRATION_TIME = Integer.MAX_VALUE;
- public static final LivenessInfo NONE = new SimpleLivenessInfo(NO_TIMESTAMP, NO_TTL, NO_DELETION_TIME);
+ public static final LivenessInfo EMPTY = new LivenessInfo(NO_TIMESTAMP);
- /**
- * The timestamp at which the data was inserted or {@link NO_TIMESTAMP}
- * if it has no timestamp (which may or may not be allowed).
- *
- * @return the liveness info timestamp.
- */
- public long timestamp();
+ protected final long timestamp;
- /**
- * Whether this liveness info has a timestamp or not.
- * <p>
- * Note that if this return {@code false}, then both {@link #hasTTL} and
- * {@link #hasLocalDeletionTime} must return {@code false} too.
- *
- * @return whether this liveness info has a timestamp or not.
- */
- public boolean hasTimestamp();
+ protected LivenessInfo(long timestamp)
+ {
+ this.timestamp = timestamp;
+ }
+
+ public static LivenessInfo create(CFMetaData metadata, long timestamp, int nowInSec)
+ {
+ int defaultTTL = metadata.getDefaultTimeToLive();
+ if (defaultTTL != NO_TTL)
+ return expiring(timestamp, defaultTTL, nowInSec);
+
+ return new LivenessInfo(timestamp);
+ }
+
+ public static LivenessInfo expiring(long timestamp, int ttl, int nowInSec)
+ {
+ return new ExpiringLivenessInfo(timestamp, ttl, nowInSec + ttl);
+ }
+
+ public static LivenessInfo create(CFMetaData metadata, long timestamp, int ttl, int nowInSec)
+ {
+ return ttl == NO_TTL
+ ? create(metadata, timestamp, nowInSec)
+ : expiring(timestamp, ttl, nowInSec);
+ }
+
+ // Note that this ctor ignores the default table ttl and takes the expiration time, not the current time.
+ // Use when you know that's what you want.
+ public static LivenessInfo create(long timestamp, int ttl, int localExpirationTime)
+ {
+ return ttl == NO_TTL ? new LivenessInfo(timestamp) : new ExpiringLivenessInfo(timestamp, ttl, localExpirationTime);
+ }
/**
- * The ttl (if any) on the data or {@link NO_TTL} if the data is not
- * expiring.
+ * Whether this liveness info is empty (has no timestamp).
*
- * Please note that this value is the TTL that was set originally and is thus not
- * changing. If you want to figure out how much time the data has before it expires,
- * then you should use {@link #remainingTTL}.
+ * @return whether this liveness info is empty or not.
*/
- public int ttl();
+ public boolean isEmpty()
+ {
+ return timestamp == NO_TIMESTAMP;
+ }
/**
- * Whether this liveness info has a TTL or not.
+ * The timestamp for this liveness info.
*
- * @return whether this liveness info has a TTL or not.
+ * @return the liveness info timestamp (or {@link #NO_TIMESTAMP} if the info is empty).
*/
- public boolean hasTTL();
+ public long timestamp()
+ {
+ return timestamp;
+ }
/**
- * The deletion time (in seconds) on the data if applicable ({@link NO_DELETION}
- * otherwise).
- *
- * There is 3 cases in practice:
- * 1) the data is neither deleted nor expiring: it then has neither {@code ttl()}
- * nor {@code localDeletionTime()}.
- * 2) the data is expiring/expired: it then has both a {@code ttl()} and a
- * {@code localDeletionTime()}. Whether it's still live or is expired depends
- * on the {@code localDeletionTime()}.
- * 3) the data is deleted: it has no {@code ttl()} but has a
- * {@code localDeletionTime()}.
+ * Whether the info has a ttl.
*/
- public int localDeletionTime();
+ public boolean isExpiring()
+ {
+ return false;
+ }
/**
- * Whether this liveness info has a local deletion time or not.
+ * The ttl (if any) on the row primary key columns or {@link #NO_TTL} if it is not
+ * expiring.
*
- * @return whether this liveness info has a local deletion time or not.
+ * Please note that this value is the TTL that was set originally and is thus not
+ * changing.
*/
- public boolean hasLocalDeletionTime();
+ public int ttl()
+ {
+ return NO_TTL;
+ }
/**
- * The actual remaining time to live (in seconds) for the data this is
- * the liveness information of.
- *
- * {@code #ttl} returns the initial TTL sets on the piece of data while this
- * method computes how much time the data actually has to live given the
- * current time.
+ * The expiration time (in seconds) if the info is expiring ({@link #NO_EXPIRATION_TIME} otherwise).
*
- * @param nowInSec the current time in seconds.
- * @return the remaining time to live (in seconds) the data has, or
- * {@code -1} if the data is either expired or not expiring.
*/
- public int remainingTTL(int nowInSec);
+ public int localExpirationTime()
+ {
+ return NO_EXPIRATION_TIME;
+ }
/**
- * Checks whether a given piece of data is live given the current time.
+ * Whether that info is still live.
+ *
+ * A {@code LivenessInfo} is live if it is either not expiring, or if its expiration time if after
+ * {@code nowInSec}.
*
* @param nowInSec the current time in seconds.
- * @return whether the data having this liveness info is live or not.
+ * @return whether this liveness info is live or not.
*/
- public boolean isLive(int nowInSec);
+ public boolean isLive(int nowInSec)
+ {
+ return !isEmpty();
+ }
/**
* Adds this liveness information to the provided digest.
*
* @param digest the digest to add this liveness information to.
*/
- public void digest(MessageDigest digest);
+ public void digest(MessageDigest digest)
+ {
+ FBUtilities.updateWithLong(digest, timestamp());
+ }
/**
* Validate the data contained by this liveness information.
*
* @throws MarshalException if some of the data is corrupted.
*/
- public void validate();
+ public void validate()
+ {
+ }
/**
* The size of the (useful) data this liveness information contains.
*
* @return the size of the data this liveness information contains.
*/
- public int dataSize();
+ public int dataSize()
+ {
+ return TypeSizes.sizeof(timestamp());
+ }
/**
* Whether this liveness information supersedes another one (that is
@@ -148,31 +174,10 @@ public interface LivenessInfo extends Aliasable<LivenessInfo>
*
* @return whether this {@code LivenessInfo} supersedes {@code other}.
*/
- public boolean supersedes(LivenessInfo other);
-
- /**
- * Returns the result of merging this info to another one (that is, it
- * return this info if it supersedes the other one, or the other one
- * otherwise).
- */
- public LivenessInfo mergeWith(LivenessInfo other);
-
- /**
- * Whether this liveness information can be purged.
- * <p>
- * A liveness info can be purged if it is not live and hasn't been so
- * for longer than gcGrace (or more precisely, it's local deletion time
- * is smaller than gcBefore, which is itself "now - gcGrace").
- *
- * @param maxPurgeableTimestamp the biggest timestamp that can be purged.
- * A liveness info will not be considered purgeable if its timestamp is
- * greater than this value, even if it mets the other criteria for purging.
- * @param gcBefore the local deletion time before which deleted/expired
- * liveness info can be purged.
- *
- * @return whether this liveness information can be purged.
- */
- public boolean isPurgeable(long maxPurgeableTimestamp, int gcBefore);
+ public boolean supersedes(LivenessInfo other)
+ {
+ return timestamp > other.timestamp;
+ }
/**
* Returns a copy of this liveness info updated with the provided timestamp.
@@ -182,5 +187,108 @@ public interface LivenessInfo extends Aliasable<LivenessInfo>
* as timestamp. If it has no timestamp however, this liveness info is returned
* unchanged.
*/
- public LivenessInfo withUpdatedTimestamp(long newTimestamp);
+ public LivenessInfo withUpdatedTimestamp(long newTimestamp)
+ {
+ return new LivenessInfo(newTimestamp);
+ }
+
+ @Override
+ public String toString()
+ {
+ return String.format("[ts=%d]", timestamp);
+ }
+
+ @Override
+ public boolean equals(Object other)
+ {
+ if(!(other instanceof LivenessInfo))
+ return false;
+
+ LivenessInfo that = (LivenessInfo)other;
+ return this.timestamp() == that.timestamp()
+ && this.ttl() == that.ttl()
+ && this.localExpirationTime() == that.localExpirationTime();
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return Objects.hash(timestamp(), ttl(), localExpirationTime());
+ }
+
+ private static class ExpiringLivenessInfo extends LivenessInfo
+ {
+ private final int ttl;
+ private final int localExpirationTime;
+
+ private ExpiringLivenessInfo(long timestamp, int ttl, int localExpirationTime)
+ {
+ super(timestamp);
+ assert ttl != NO_TTL && localExpirationTime != NO_EXPIRATION_TIME;
+ this.ttl = ttl;
+ this.localExpirationTime = localExpirationTime;
+ }
+
+ @Override
+ public int ttl()
+ {
+ return ttl;
+ }
+
+ @Override
+ public int localExpirationTime()
+ {
+ return localExpirationTime;
+ }
+
+ @Override
+ public boolean isExpiring()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean isLive(int nowInSec)
+ {
+ return nowInSec < localExpirationTime;
+ }
+
+ @Override
+ public void digest(MessageDigest digest)
+ {
+ super.digest(digest);
+ FBUtilities.updateWithInt(digest, localExpirationTime);
+ FBUtilities.updateWithInt(digest, ttl);
+ }
+
+ @Override
+ public void validate()
+ {
+ if (ttl < 0)
+ throw new MarshalException("A TTL should not be negative");
+ if (localExpirationTime < 0)
+ throw new MarshalException("A local expiration time should not be negative");
+ }
+
+ @Override
+ public int dataSize()
+ {
+ return super.dataSize()
+ + TypeSizes.sizeof(ttl)
+ + TypeSizes.sizeof(localExpirationTime);
+
+ }
+
+ @Override
+ public LivenessInfo withUpdatedTimestamp(long newTimestamp)
+ {
+ return new ExpiringLivenessInfo(newTimestamp, ttl, localExpirationTime);
+ }
+
+ @Override
+ public String toString()
+ {
+ return String.format("[ts=%d ttl=%d, let=%d]", timestamp, ttl, localExpirationTime);
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/24575994/src/java/org/apache/cassandra/db/LivenessInfoArray.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/LivenessInfoArray.java b/src/java/org/apache/cassandra/db/LivenessInfoArray.java
deleted file mode 100644
index 24026d8..0000000
--- a/src/java/org/apache/cassandra/db/LivenessInfoArray.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.cassandra.db;
-
-import java.util.Arrays;
-
-import org.apache.cassandra.utils.ObjectSizes;
-
-/**
- * Utility class to store an array of liveness info efficiently.
- */
-public class LivenessInfoArray
-{
- private long[] timestamps;
- private int[] delTimesAndTTLs;
-
- public LivenessInfoArray(int initialCapacity)
- {
- this.timestamps = new long[initialCapacity];
- this.delTimesAndTTLs = new int[initialCapacity * 2];
- clear();
- }
-
- public void clear(int i)
- {
- timestamps[i] = LivenessInfo.NO_TIMESTAMP;
- delTimesAndTTLs[2 * i] = LivenessInfo.NO_DELETION_TIME;
- delTimesAndTTLs[2 * i + 1] = LivenessInfo.NO_TTL;
- }
-
- public void set(int i, LivenessInfo info)
- {
- set(i, info.timestamp(), info.ttl(), info.localDeletionTime());
- }
-
- public void set(int i, long timestamp, int ttl, int localDeletionTime)
- {
- this.timestamps[i] = timestamp;
- this.delTimesAndTTLs[2 * i] = localDeletionTime;
- this.delTimesAndTTLs[2 * i + 1] = ttl;
- }
-
- public long timestamp(int i)
- {
- return timestamps[i];
- }
-
- public int localDeletionTime(int i)
- {
- return delTimesAndTTLs[2 * i];
- }
-
- public int ttl(int i)
- {
- return delTimesAndTTLs[2 * i + 1];
- }
-
- public boolean isLive(int i, int nowInSec)
- {
- // See AbstractLivenessInfo.isLive().
- return localDeletionTime(i) == LivenessInfo.NO_DELETION_TIME
- || (ttl(i) != LivenessInfo.NO_TTL && nowInSec < localDeletionTime(i));
- }
-
- public int size()
- {
- return timestamps.length;
- }
-
- public void resize(int newSize)
- {
- int prevSize = size();
-
- timestamps = Arrays.copyOf(timestamps, newSize);
- delTimesAndTTLs = Arrays.copyOf(delTimesAndTTLs, newSize * 2);
-
- clear(prevSize, newSize);
- }
-
- public void swap(int i, int j)
- {
- long ts = timestamps[j];
- int ldt = delTimesAndTTLs[2 * j];
- int ttl = delTimesAndTTLs[2 * j + 1];
-
- move(i, j);
-
- timestamps[i] = ts;
- delTimesAndTTLs[2 * i] = ldt;
- delTimesAndTTLs[2 * i + 1] = ttl;
- }
-
- public void move(int i, int j)
- {
- timestamps[j] = timestamps[i];
- delTimesAndTTLs[2 * j] = delTimesAndTTLs[2 * i];
- delTimesAndTTLs[2 * j + 1] = delTimesAndTTLs[2 * i + 1];
- }
-
- public void clear()
- {
- clear(0, size());
- }
-
- private void clear(int from, int to)
- {
- Arrays.fill(timestamps, from, to, LivenessInfo.NO_TIMESTAMP);
- for (int i = from; i < to; i++)
- {
- delTimesAndTTLs[2 * i] = LivenessInfo.NO_DELETION_TIME;
- delTimesAndTTLs[2 * i + 1] = LivenessInfo.NO_TTL;
- }
- }
-
- public int dataSize()
- {
- return 16 * size();
- }
-
- public long unsharedHeapSize()
- {
- return ObjectSizes.sizeOfArray(timestamps)
- + ObjectSizes.sizeOfArray(delTimesAndTTLs);
- }
-
- public static Cursor newCursor()
- {
- return new Cursor();
- }
-
- public static class Cursor extends AbstractLivenessInfo
- {
- private LivenessInfoArray array;
- private int i;
-
- public Cursor setTo(LivenessInfoArray array, int i)
- {
- this.array = array;
- this.i = i;
- return this;
- }
-
- public long timestamp()
- {
- return array.timestamps[i];
- }
-
- public int localDeletionTime()
- {
- return array.delTimesAndTTLs[2 * i];
- }
-
- public int ttl()
- {
- return array.delTimesAndTTLs[2 * i + 1];
- }
- }
-}
-
http://git-wip-us.apache.org/repos/asf/cassandra/blob/24575994/src/java/org/apache/cassandra/db/MutableDeletionInfo.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/MutableDeletionInfo.java b/src/java/org/apache/cassandra/db/MutableDeletionInfo.java
new file mode 100644
index 0000000..6b19283
--- /dev/null
+++ b/src/java/org/apache/cassandra/db/MutableDeletionInfo.java
@@ -0,0 +1,311 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cassandra.db;
+
+import java.util.Iterator;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.Iterators;
+
+import org.apache.cassandra.db.rows.*;
+import org.apache.cassandra.db.rows.RowStats;
+import org.apache.cassandra.utils.ObjectSizes;
+import org.apache.cassandra.utils.memory.AbstractAllocator;
+
+/**
+ * A mutable implementation of {@code DeletionInfo}.
+ */
+public class MutableDeletionInfo implements DeletionInfo
+{
+ private static final long EMPTY_SIZE = ObjectSizes.measure(new MutableDeletionInfo(0, 0));
+
+ /**
+ * This represents a deletion of the entire partition. We can't represent this within the RangeTombstoneList, so it's
+ * kept separately. This also slightly optimizes the common case of a full partition deletion.
+ */
+ private DeletionTime partitionDeletion;
+
+ /**
+ * A list of range tombstones within the partition. This is left as null if there are no range tombstones
+ * (to save an allocation (since it's a common case).
+ */
+ private RangeTombstoneList ranges;
+
+ /**
+ * Creates a DeletionInfo with only a top-level (row) tombstone.
+ * @param markedForDeleteAt the time after which the entire row should be considered deleted
+ * @param localDeletionTime what time the deletion write was applied locally (for purposes of
+ * purging the tombstone after gc_grace_seconds).
+ */
+ public MutableDeletionInfo(long markedForDeleteAt, int localDeletionTime)
+ {
+ // Pre-1.1 node may return MIN_VALUE for non-deleted container, but the new default is MAX_VALUE
+ // (see CASSANDRA-3872)
+ this(new DeletionTime(markedForDeleteAt, localDeletionTime == Integer.MIN_VALUE ? Integer.MAX_VALUE : localDeletionTime));
+ }
+
+ public MutableDeletionInfo(DeletionTime partitionDeletion)
+ {
+ this(partitionDeletion, null);
+ }
+
+ public MutableDeletionInfo(DeletionTime partitionDeletion, RangeTombstoneList ranges)
+ {
+ this.partitionDeletion = partitionDeletion;
+ this.ranges = ranges;
+ }
+
+ /**
+ * Returns a new DeletionInfo that has no top-level tombstone or any range tombstones.
+ */
+ public static MutableDeletionInfo live()
+ {
+ return new MutableDeletionInfo(DeletionTime.LIVE);
+ }
+
+ public MutableDeletionInfo mutableCopy()
+ {
+ return new MutableDeletionInfo(partitionDeletion, ranges == null ? null : ranges.copy());
+ }
+
+ public MutableDeletionInfo copy(AbstractAllocator allocator)
+ {
+ RangeTombstoneList rangesCopy = null;
+ if (ranges != null)
+ rangesCopy = ranges.copy(allocator);
+
+ return new MutableDeletionInfo(partitionDeletion, rangesCopy);
+ }
+
+ /**
+ * Returns whether this DeletionInfo is live, that is deletes no columns.
+ */
+ public boolean isLive()
+ {
+ return partitionDeletion.isLive() && (ranges == null || ranges.isEmpty());
+ }
+
+ /**
+ * Potentially replaces the top-level tombstone with another, keeping whichever has the higher markedForDeleteAt
+ * timestamp.
+ * @param newInfo the deletion time to add to this deletion info.
+ */
+ public void add(DeletionTime newInfo)
+ {
+ if (newInfo.supersedes(partitionDeletion))
+ partitionDeletion = newInfo;
+ }
+
+ public void add(RangeTombstone tombstone, ClusteringComparator comparator)
+ {
+ if (ranges == null)
+ ranges = new RangeTombstoneList(comparator, 1);
+
+ ranges.add(tombstone);
+ }
+
+ /**
+ * Combines another DeletionInfo with this one and returns the result. Whichever top-level tombstone
+ * has the higher markedForDeleteAt timestamp will be kept, along with its localDeletionTime. The
+ * range tombstones will be combined.
+ *
+ * @return this object.
+ */
+ public DeletionInfo add(DeletionInfo newInfo)
+ {
+ add(newInfo.getPartitionDeletion());
+
+ // We know MutableDeletionInfo is the only impelementation and we're not mutating it, it's just to get access to the
+ // RangeTombstoneList directly.
+ assert newInfo instanceof MutableDeletionInfo;
+ RangeTombstoneList newRanges = ((MutableDeletionInfo)newInfo).ranges;
+
+ if (ranges == null)
+ ranges = newRanges == null ? null : newRanges.copy();
+ else if (newRanges != null)
+ ranges.addAll(newRanges);
+
+ return this;
+ }
+
+ public DeletionTime getPartitionDeletion()
+ {
+ return partitionDeletion;
+ }
+
+ // Use sparingly, not the most efficient thing
+ public Iterator<RangeTombstone> rangeIterator(boolean reversed)
+ {
+ return ranges == null ? Iterators.<RangeTombstone>emptyIterator() : ranges.iterator(reversed);
+ }
+
+ public Iterator<RangeTombstone> rangeIterator(Slice slice, boolean reversed)
+ {
+ return ranges == null ? Iterators.<RangeTombstone>emptyIterator() : ranges.iterator(slice, reversed);
+ }
+
+ public RangeTombstone rangeCovering(Clustering name)
+ {
+ return ranges == null ? null : ranges.search(name);
+ }
+
+ public int dataSize()
+ {
+ int size = TypeSizes.sizeof(partitionDeletion.markedForDeleteAt());
+ return size + (ranges == null ? 0 : ranges.dataSize());
+ }
+
+ public boolean hasRanges()
+ {
+ return ranges != null && !ranges.isEmpty();
+ }
+
+ public int rangeCount()
+ {
+ return hasRanges() ? ranges.size() : 0;
+ }
+
+ public long maxTimestamp()
+ {
+ return ranges == null ? partitionDeletion.markedForDeleteAt() : Math.max(partitionDeletion.markedForDeleteAt(), ranges.maxMarkedAt());
+ }
+
+ /**
+ * Whether this deletion info may modify the provided one if added to it.
+ */
+ public boolean mayModify(DeletionInfo delInfo)
+ {
+ return partitionDeletion.compareTo(delInfo.getPartitionDeletion()) > 0 || hasRanges();
+ }
+
+ @Override
+ public String toString()
+ {
+ if (ranges == null || ranges.isEmpty())
+ return String.format("{%s}", partitionDeletion);
+ else
+ return String.format("{%s, ranges=%s}", partitionDeletion, rangesAsString());
+ }
+
+ private String rangesAsString()
+ {
+ assert !ranges.isEmpty();
+ StringBuilder sb = new StringBuilder();
+ ClusteringComparator cc = ranges.comparator();
+ Iterator<RangeTombstone> iter = rangeIterator(false);
+ while (iter.hasNext())
+ {
+ RangeTombstone i = iter.next();
+ sb.append(i.deletedSlice().toString(cc));
+ sb.append('@');
+ sb.append(i.deletionTime());
+ }
+ return sb.toString();
+ }
+
+ // Updates all the timestamp of the deletion contained in this DeletionInfo to be {@code timestamp}.
+ public DeletionInfo updateAllTimestamp(long timestamp)
+ {
+ if (partitionDeletion.markedForDeleteAt() != Long.MIN_VALUE)
+ partitionDeletion = new DeletionTime(timestamp, partitionDeletion.localDeletionTime());
+
+ if (ranges != null)
+ ranges.updateAllTimestamp(timestamp);
+ return this;
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if(!(o instanceof MutableDeletionInfo))
+ return false;
+ MutableDeletionInfo that = (MutableDeletionInfo)o;
+ return partitionDeletion.equals(that.partitionDeletion) && Objects.equal(ranges, that.ranges);
+ }
+
+ @Override
+ public final int hashCode()
+ {
+ return Objects.hashCode(partitionDeletion, ranges);
+ }
+
+ @Override
+ public long unsharedHeapSize()
+ {
+ return EMPTY_SIZE + partitionDeletion.unsharedHeapSize() + (ranges == null ? 0 : ranges.unsharedHeapSize());
+ }
+
+ public void collectStats(RowStats.Collector collector)
+ {
+ collector.update(partitionDeletion);
+ if (ranges != null)
+ ranges.collectStats(collector);
+ }
+
+ public static Builder builder(DeletionTime partitionLevelDeletion, ClusteringComparator comparator, boolean reversed)
+ {
+ return new Builder(partitionLevelDeletion, comparator, reversed);
+ }
+
+ /**
+ * Builds DeletionInfo object from (in order) range tombstone markers.
+ */
+ public static class Builder
+ {
+ private final MutableDeletionInfo deletion;
+ private final ClusteringComparator comparator;
+
+ private final boolean reversed;
+
+ private RangeTombstoneMarker openMarker;
+
+ private Builder(DeletionTime partitionLevelDeletion, ClusteringComparator comparator, boolean reversed)
+ {
+ this.deletion = new MutableDeletionInfo(partitionLevelDeletion);
+ this.comparator = comparator;
+ this.reversed = reversed;
+ }
+
+ public void add(RangeTombstoneMarker marker)
+ {
+ // We need to start by the close case in case that's a boundary
+
+ if (marker.isClose(reversed))
+ {
+ DeletionTime openDeletion = openMarker.openDeletionTime(reversed);
+ assert marker.closeDeletionTime(reversed).equals(openDeletion);
+
+ Slice.Bound open = openMarker.openBound(reversed);
+ Slice.Bound close = marker.closeBound(reversed);
+
+ Slice slice = reversed ? Slice.make(close, open) : Slice.make(open, close);
+ deletion.add(new RangeTombstone(slice, openDeletion), comparator);
+ }
+
+ if (marker.isOpen(reversed))
+ {
+ openMarker = marker;
+ }
+ }
+
+ public MutableDeletionInfo build()
+ {
+ return deletion;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/24575994/src/java/org/apache/cassandra/db/PartitionColumns.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/PartitionColumns.java b/src/java/org/apache/cassandra/db/PartitionColumns.java
index ef05760..5f1da8a 100644
--- a/src/java/org/apache/cassandra/db/PartitionColumns.java
+++ b/src/java/org/apache/cassandra/db/PartitionColumns.java
@@ -66,6 +66,11 @@ public class PartitionColumns implements Iterable<ColumnDefinition>
return statics.isEmpty() && regulars.isEmpty();
}
+ public Columns columns(boolean isStatic)
+ {
+ return isStatic ? statics : regulars;
+ }
+
public boolean contains(ColumnDefinition column)
{
return column.isStatic() ? statics.contains(column) : regulars.contains(column);
http://git-wip-us.apache.org/repos/asf/cassandra/blob/24575994/src/java/org/apache/cassandra/db/PartitionRangeReadCommand.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/PartitionRangeReadCommand.java b/src/java/org/apache/cassandra/db/PartitionRangeReadCommand.java
index 65e38d0..4a3704f 100644
--- a/src/java/org/apache/cassandra/db/PartitionRangeReadCommand.java
+++ b/src/java/org/apache/cassandra/db/PartitionRangeReadCommand.java
@@ -17,7 +17,6 @@
*/
package org.apache.cassandra.db;
-import java.io.DataInput;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@@ -32,6 +31,7 @@ import org.apache.cassandra.db.partitions.*;
import org.apache.cassandra.db.index.SecondaryIndexSearcher;
import org.apache.cassandra.dht.AbstractBounds;
import org.apache.cassandra.exceptions.RequestExecutionException;
+import org.apache.cassandra.io.util.DataInputPlus;
import org.apache.cassandra.io.util.DataOutputPlus;
import org.apache.cassandra.io.sstable.format.SSTableReader;
import org.apache.cassandra.metrics.TableMetrics;
@@ -278,11 +278,11 @@ public class PartitionRangeReadCommand extends ReadCommand
private static class Deserializer extends SelectionDeserializer
{
- public ReadCommand deserialize(DataInput in, int version, boolean isDigest, boolean isForThrift, CFMetaData metadata, int nowInSec, ColumnFilter columnFilter, RowFilter rowFilter, DataLimits limits)
+ public ReadCommand deserialize(DataInputPlus in, int version, boolean isDigest, boolean isForThrift, CFMetaData metadata, int nowInSec, ColumnFilter columnFilter, RowFilter rowFilter, DataLimits limits)
throws IOException
{
DataRange range = DataRange.serializer.deserialize(in, version, metadata);
return new PartitionRangeReadCommand(isDigest, isForThrift, metadata, nowInSec, columnFilter, rowFilter, limits, range);
}
- };
+ }
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/24575994/src/java/org/apache/cassandra/db/RangeTombstone.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/RangeTombstone.java b/src/java/org/apache/cassandra/db/RangeTombstone.java
index df60933..8865b0f 100644
--- a/src/java/org/apache/cassandra/db/RangeTombstone.java
+++ b/src/java/org/apache/cassandra/db/RangeTombstone.java
@@ -17,20 +17,15 @@
*/
package org.apache.cassandra.db;
-import java.io.DataInput;
import java.io.IOException;
import java.nio.ByteBuffer;
-import java.security.MessageDigest;
import java.util.*;
-import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.marshal.AbstractType;
-import org.apache.cassandra.io.ISSTableSerializer;
-import org.apache.cassandra.io.sstable.format.Version;
-import org.apache.cassandra.io.util.DataOutputBuffer;
+import org.apache.cassandra.db.rows.RangeTombstoneMarker;
+import org.apache.cassandra.io.util.DataInputPlus;
import org.apache.cassandra.io.util.DataOutputPlus;
-import org.apache.cassandra.serializers.MarshalException;
-import org.apache.cassandra.utils.Interval;
+import org.apache.cassandra.utils.memory.AbstractAllocator;
/**
* A range tombstone is a tombstone that covers a slice/range of rows.
@@ -48,7 +43,7 @@ public class RangeTombstone
public RangeTombstone(Slice slice, DeletionTime deletion)
{
this.slice = slice;
- this.deletion = deletion.takeAlias();
+ this.deletion = deletion;
}
/**
@@ -73,7 +68,7 @@ public class RangeTombstone
public String toString(ClusteringComparator comparator)
{
- return slice.toString(comparator) + "@" + deletion;
+ return slice.toString(comparator) + '@' + deletion;
}
@Override
@@ -108,9 +103,30 @@ public class RangeTombstone
{
public static final Serializer serializer = new Serializer();
+ /** The smallest start bound, i.e. the one that starts before any row. */
+ public static final Bound BOTTOM = new Bound(Kind.INCL_START_BOUND, EMPTY_VALUES_ARRAY);
+ /** The biggest end bound, i.e. the one that ends after any row. */
+ public static final Bound TOP = new Bound(Kind.INCL_END_BOUND, EMPTY_VALUES_ARRAY);
+
public Bound(Kind kind, ByteBuffer[] values)
{
super(kind, values);
+ assert values.length > 0 || !kind.isBoundary();
+ }
+
+ public boolean isBoundary()
+ {
+ return kind.isBoundary();
+ }
+
+ public boolean isOpen(boolean reversed)
+ {
+ return kind.isOpen(reversed);
+ }
+
+ public boolean isClose(boolean reversed)
+ {
+ return kind.isClose(reversed);
}
public static RangeTombstone.Bound inclusiveOpen(boolean reversed, ByteBuffer[] boundValues)
@@ -143,6 +159,19 @@ public class RangeTombstone
return new Bound(reversed ? Kind.INCL_END_EXCL_START_BOUNDARY : Kind.EXCL_END_INCL_START_BOUNDARY, boundValues);
}
+ public static RangeTombstone.Bound fromSliceBound(Slice.Bound sliceBound)
+ {
+ return new RangeTombstone.Bound(sliceBound.kind(), sliceBound.getRawValues());
+ }
+
+ public RangeTombstone.Bound copy(AbstractAllocator allocator)
+ {
+ ByteBuffer[] newValues = new ByteBuffer[size()];
+ for (int i = 0; i < size(); i++)
+ newValues[i] = allocator.clone(get(i));
+ return new Bound(kind(), newValues);
+ }
+
@Override
public Bound withNewKind(Kind kind)
{
@@ -165,13 +194,15 @@ public class RangeTombstone
+ ClusteringPrefix.serializer.valuesWithoutSizeSerializedSize(bound, version, types);
}
- public Kind deserialize(DataInput in, int version, List<AbstractType<?>> types, Writer writer) throws IOException
+ public RangeTombstone.Bound deserialize(DataInputPlus in, int version, List<AbstractType<?>> types) throws IOException
{
Kind kind = Kind.values()[in.readByte()];
- writer.writeBoundKind(kind);
int size = in.readUnsignedShort();
- ClusteringPrefix.serializer.deserializeValuesWithoutSize(in, size, version, types, writer);
- return kind;
+ if (size == 0)
+ return kind.isStart() ? BOTTOM : TOP;
+
+ ByteBuffer[] values = ClusteringPrefix.serializer.deserializeValuesWithoutSize(in, size, version, types);
+ return new RangeTombstone.Bound(kind, values);
}
}
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/24575994/src/java/org/apache/cassandra/db/RangeTombstoneList.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/RangeTombstoneList.java b/src/java/org/apache/cassandra/db/RangeTombstoneList.java
index 64f0978..96bcdb1 100644
--- a/src/java/org/apache/cassandra/db/RangeTombstoneList.java
+++ b/src/java/org/apache/cassandra/db/RangeTombstoneList.java
@@ -244,7 +244,7 @@ public class RangeTombstoneList implements Iterable<RangeTombstone>, IMeasurable
{
int idx = searchInternal(clustering, 0, size);
// No matter what the counter cell's timestamp is, a tombstone always takes precedence. See CASSANDRA-7346.
- return idx >= 0 && (cell.isCounterCell() || markedAts[idx] >= cell.livenessInfo().timestamp());
+ return idx >= 0 && (cell.isCounterCell() || markedAts[idx] >= cell.timestamp());
}
/**
@@ -254,7 +254,7 @@ public class RangeTombstoneList implements Iterable<RangeTombstone>, IMeasurable
public DeletionTime searchDeletionTime(Clustering name)
{
int idx = searchInternal(name, 0, size);
- return idx < 0 ? null : new SimpleDeletionTime(markedAts[idx], delTimes[idx]);
+ return idx < 0 ? null : new DeletionTime(markedAts[idx], delTimes[idx]);
}
public RangeTombstone search(Clustering name)
@@ -300,6 +300,23 @@ public class RangeTombstoneList implements Iterable<RangeTombstone>, IMeasurable
return dataSize;
}
+ public long maxMarkedAt()
+ {
+ long max = Long.MIN_VALUE;
+ for (int i = 0; i < size; i++)
+ max = Math.max(max, markedAts[i]);
+ return max;
+ }
+
+ public void collectStats(RowStats.Collector collector)
+ {
+ for (int i = 0; i < size; i++)
+ {
+ collector.updateTimestamp(markedAts[i]);
+ collector.updateLocalDeletionTime(delTimes[i]);
+ }
+ }
+
public void updateAllTimestamp(long timestamp)
{
for (int i = 0; i < size; i++)
@@ -308,22 +325,22 @@ public class RangeTombstoneList implements Iterable<RangeTombstone>, IMeasurable
private RangeTombstone rangeTombstone(int idx)
{
- return new RangeTombstone(Slice.make(starts[idx], ends[idx]), new SimpleDeletionTime(markedAts[idx], delTimes[idx]));
+ return new RangeTombstone(Slice.make(starts[idx], ends[idx]), new DeletionTime(markedAts[idx], delTimes[idx]));
}
private RangeTombstone rangeTombstoneWithNewStart(int idx, Slice.Bound newStart)
{
- return new RangeTombstone(Slice.make(newStart, ends[idx]), new SimpleDeletionTime(markedAts[idx], delTimes[idx]));
+ return new RangeTombstone(Slice.make(newStart, ends[idx]), new DeletionTime(markedAts[idx], delTimes[idx]));
}
private RangeTombstone rangeTombstoneWithNewEnd(int idx, Slice.Bound newEnd)
{
- return new RangeTombstone(Slice.make(starts[idx], newEnd), new SimpleDeletionTime(markedAts[idx], delTimes[idx]));
+ return new RangeTombstone(Slice.make(starts[idx], newEnd), new DeletionTime(markedAts[idx], delTimes[idx]));
}
private RangeTombstone rangeTombstoneWithNewBounds(int idx, Slice.Bound newStart, Slice.Bound newEnd)
{
- return new RangeTombstone(Slice.make(newStart, newEnd), new SimpleDeletionTime(markedAts[idx], delTimes[idx]));
+ return new RangeTombstone(Slice.make(newStart, newEnd), new DeletionTime(markedAts[idx], delTimes[idx]));
}
public Iterator<RangeTombstone> iterator()
http://git-wip-us.apache.org/repos/asf/cassandra/blob/24575994/src/java/org/apache/cassandra/db/ReadCommand.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/ReadCommand.java b/src/java/org/apache/cassandra/db/ReadCommand.java
index 99547f0..c3f036a 100644
--- a/src/java/org/apache/cassandra/db/ReadCommand.java
+++ b/src/java/org/apache/cassandra/db/ReadCommand.java
@@ -17,11 +17,12 @@
*/
package org.apache.cassandra.db;
-import java.io.DataInput;
import java.io.IOException;
+import java.util.Iterator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.config.Schema;
@@ -63,7 +64,7 @@ public abstract class ReadCommand implements ReadQuery
protected static abstract class SelectionDeserializer
{
- public abstract ReadCommand deserialize(DataInput in, int version, boolean isDigest, boolean isForThrift, CFMetaData metadata, int nowInSec, ColumnFilter columnFilter, RowFilter rowFilter, DataLimits limits) throws IOException;
+ public abstract ReadCommand deserialize(DataInputPlus in, int version, boolean isDigest, boolean isForThrift, CFMetaData metadata, int nowInSec, ColumnFilter columnFilter, RowFilter rowFilter, DataLimits limits) throws IOException;
}
protected enum Kind
@@ -268,22 +269,13 @@ public abstract class ReadCommand implements ReadQuery
try
{
- resultIterator = UnfilteredPartitionIterators.convertExpiredCellsToTombstones(resultIterator, nowInSec);
- resultIterator = withMetricsRecording(withoutExpiredTombstones(resultIterator, cfs), cfs.metric, startTimeNanos);
-
- // TODO: we should push the dropping of columns down the layers because
- // 1) it'll be more efficient
- // 2) it could help us solve #6276
- // But there is not reason not to do this as a followup so keeping it here for now (we'll have
- // to be wary of cached row if we move this down the layers)
- if (!metadata().getDroppedColumns().isEmpty())
- resultIterator = UnfilteredPartitionIterators.removeDroppedColumns(resultIterator, metadata().getDroppedColumns());
+ resultIterator = withMetricsRecording(withoutPurgeableTombstones(resultIterator, cfs), cfs.metric, startTimeNanos);
// If we've used a 2ndary index, we know the result already satisfy the primary expression used, so
// no point in checking it again.
RowFilter updatedFilter = searcher == null
- ? rowFilter()
- : rowFilter().without(searcher.primaryClause(this));
+ ? rowFilter()
+ : rowFilter().without(searcher.primaryClause(this));
// TODO: We'll currently do filtering by the rowFilter here because it's convenient. However,
// we'll probably want to optimize by pushing it down the layer (like for dropped columns) as it
@@ -333,26 +325,33 @@ public abstract class ReadCommand implements ReadQuery
{
currentKey = iter.partitionKey();
- return new WrappingUnfilteredRowIterator(iter)
+ return new AlteringUnfilteredRowIterator(iter)
{
- public Unfiltered next()
+ @Override
+ protected Row computeNextStatic(Row row)
{
- Unfiltered unfiltered = super.next();
- if (unfiltered.kind() == Unfiltered.Kind.ROW)
- {
- Row row = (Row) unfiltered;
- if (row.hasLiveData(ReadCommand.this.nowInSec()))
- ++liveRows;
- for (Cell cell : row)
- if (!cell.isLive(ReadCommand.this.nowInSec()))
- countTombstone(row.clustering());
- }
- else
+ return computeNext(row);
+ }
+
+ @Override
+ protected Row computeNext(Row row)
+ {
+ if (row.hasLiveData(ReadCommand.this.nowInSec()))
+ ++liveRows;
+
+ for (Cell cell : row.cells())
{
- countTombstone(unfiltered.clustering());
+ if (!cell.isLive(ReadCommand.this.nowInSec()))
+ countTombstone(row.clustering());
}
+ return row;
+ }
- return unfiltered;
+ @Override
+ protected RangeTombstoneMarker computeNext(RangeTombstoneMarker marker)
+ {
+ countTombstone(marker.clustering());
+ return marker;
}
private void countTombstone(ClusteringPrefix clustering)
@@ -407,12 +406,12 @@ public abstract class ReadCommand implements ReadQuery
protected abstract void appendCQLWhereClause(StringBuilder sb);
- // Skip expired tombstones. We do this because it's safe to do (post-merge of the memtable and sstable at least), it
- // can save us some bandwith, and avoid making us throw a TombstoneOverwhelmingException for expired tombstones (which
+ // Skip purgeable tombstones. We do this because it's safe to do (post-merge of the memtable and sstable at least), it
+ // can save us some bandwith, and avoid making us throw a TombstoneOverwhelmingException for purgeable tombstones (which
// are to some extend an artefact of compaction lagging behind and hence counting them is somewhat unintuitive).
- protected UnfilteredPartitionIterator withoutExpiredTombstones(UnfilteredPartitionIterator iterator, ColumnFamilyStore cfs)
+ protected UnfilteredPartitionIterator withoutPurgeableTombstones(UnfilteredPartitionIterator iterator, ColumnFamilyStore cfs)
{
- return new TombstonePurgingPartitionIterator(iterator, cfs.gcBefore(nowInSec()))
+ return new PurgingPartitionIterator(iterator, cfs.gcBefore(nowInSec()))
{
protected long getMaxPurgeableTimestamp()
{
http://git-wip-us.apache.org/repos/asf/cassandra/blob/24575994/src/java/org/apache/cassandra/db/ReusableClustering.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/ReusableClustering.java b/src/java/org/apache/cassandra/db/ReusableClustering.java
deleted file mode 100644
index e2760aa..0000000
--- a/src/java/org/apache/cassandra/db/ReusableClustering.java
+++ /dev/null
@@ -1,82 +0,0 @@
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.cassandra.db;
-
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-
-import org.apache.cassandra.utils.ObjectSizes;
-
-public class ReusableClustering extends Clustering
-{
- private static final long EMPTY_SIZE = ObjectSizes.measure(new ReusableClustering(0));
-
- protected final ByteBuffer[] values;
-
- protected ReusableWriter writer;
-
- public ReusableClustering(int size)
- {
- this.values = new ByteBuffer[size];
- }
-
- public int size()
- {
- return values.length;
- }
-
- public ByteBuffer get(int i)
- {
- return values[i];
- }
-
- public ByteBuffer[] getRawValues()
- {
- return values;
- }
-
- public Writer writer()
- {
- if (writer == null)
- writer = new ReusableWriter();
- return writer;
- }
-
- public void reset()
- {
- Arrays.fill(values, null);
- if (writer != null)
- writer.reset();
- }
-
- protected class ReusableWriter implements Writer
- {
- int idx;
-
- public void writeClusteringValue(ByteBuffer value)
- {
- values[idx++] = value;
- }
-
- private void reset()
- {
- idx = 0;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/24575994/src/java/org/apache/cassandra/db/ReusableClusteringPrefix.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/ReusableClusteringPrefix.java b/src/java/org/apache/cassandra/db/ReusableClusteringPrefix.java
deleted file mode 100644
index d2f19f7..0000000
--- a/src/java/org/apache/cassandra/db/ReusableClusteringPrefix.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.cassandra.db;
-
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-
-import org.apache.cassandra.utils.ObjectSizes;
-
-// Note that we abuse a bit ReusableClustering to store Slice.Bound infos, but it's convenient so ...
-public class ReusableClusteringPrefix extends ReusableClustering
-{
- private Kind kind;
- private int size;
-
- public ReusableClusteringPrefix(int size)
- {
- super(size);
- }
-
- public ClusteringPrefix get()
- {
- // We use ReusableClusteringPrefix when writing sstables (in ColumnIndex) and we
- // don't write static clustering there.
- assert kind != Kind.STATIC_CLUSTERING;
- if (kind == Kind.CLUSTERING)
- {
- assert values.length == size;
- return this;
- }
-
- return Slice.Bound.create(kind, Arrays.copyOfRange(values, 0, size));
- }
-
- public void copy(ClusteringPrefix clustering)
- {
- kind = clustering.kind();
- for (int i = 0; i < clustering.size(); i++)
- values[i] = clustering.get(i);
- size = clustering.size();
- }
-}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/24575994/src/java/org/apache/cassandra/db/ReusableLivenessInfo.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/ReusableLivenessInfo.java b/src/java/org/apache/cassandra/db/ReusableLivenessInfo.java
deleted file mode 100644
index 43530b0..0000000
--- a/src/java/org/apache/cassandra/db/ReusableLivenessInfo.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.cassandra.db;
-
-public class ReusableLivenessInfo extends AbstractLivenessInfo
-{
- private long timestamp;
- private int ttl;
- private int localDeletionTime;
-
- public ReusableLivenessInfo()
- {
- reset();
- }
-
- public LivenessInfo setTo(LivenessInfo info)
- {
- return setTo(info.timestamp(), info.ttl(), info.localDeletionTime());
- }
-
- public LivenessInfo setTo(long timestamp, int ttl, int localDeletionTime)
- {
- this.timestamp = timestamp;
- this.ttl = ttl;
- this.localDeletionTime = localDeletionTime;
- return this;
- }
-
- public long timestamp()
- {
- return timestamp;
- }
-
- public int ttl()
- {
- return ttl;
- }
-
- public int localDeletionTime()
- {
- return localDeletionTime;
- }
-
- public void reset()
- {
- this.timestamp = LivenessInfo.NO_TIMESTAMP;
- this.ttl = LivenessInfo.NO_TTL;
- this.localDeletionTime = LivenessInfo.NO_DELETION_TIME;
- }
-}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/24575994/src/java/org/apache/cassandra/db/RowUpdateBuilder.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/RowUpdateBuilder.java b/src/java/org/apache/cassandra/db/RowUpdateBuilder.java
index 627321e..7640512 100644
--- a/src/java/org/apache/cassandra/db/RowUpdateBuilder.java
+++ b/src/java/org/apache/cassandra/db/RowUpdateBuilder.java
@@ -43,25 +43,27 @@ public class RowUpdateBuilder
{
private final PartitionUpdate update;
- private final LivenessInfo defaultLiveness;
- private final LivenessInfo deletionLiveness;
+ private final long timestamp;
+ private final int ttl;
+ private final int localDeletionTime;
+
private final DeletionTime deletionTime;
private final Mutation mutation;
- private Row.Writer regularWriter;
- private Row.Writer staticWriter;
+ private Row.Builder regularBuilder;
+ private Row.Builder staticBuilder;
- private boolean hasSetClustering;
private boolean useRowMarker = true;
private RowUpdateBuilder(PartitionUpdate update, long timestamp, int ttl, int localDeletionTime, Mutation mutation)
{
this.update = update;
- this.defaultLiveness = SimpleLivenessInfo.forUpdate(timestamp, ttl, localDeletionTime, update.metadata());
- this.deletionLiveness = SimpleLivenessInfo.forDeletion(timestamp, localDeletionTime);
- this.deletionTime = new SimpleDeletionTime(timestamp, localDeletionTime);
+ this.timestamp = timestamp;
+ this.ttl = ttl;
+ this.localDeletionTime = localDeletionTime;
+ this.deletionTime = new DeletionTime(timestamp, localDeletionTime);
// note that the created mutation may get further update later on, so we don't use the ctor that create a singletonMap
// underneath (this class if for convenience, not performance)
@@ -73,31 +75,45 @@ public class RowUpdateBuilder
this(update, timestamp, ttl, FBUtilities.nowInSeconds(), mutation);
}
- private Row.Writer writer()
+ private void startRow(Clustering clustering)
{
- assert staticWriter == null : "Cannot update both static and non-static columns with the same RowUpdateBuilder object";
- if (regularWriter == null)
- {
- regularWriter = update.writer();
+ assert staticBuilder == null : "Cannot update both static and non-static columns with the same RowUpdateBuilder object";
+ assert regularBuilder == null : "Cannot add the clustering twice to the same row";
+
+ regularBuilder = ArrayBackedRow.unsortedBuilder(update.columns().regulars, FBUtilities.nowInSeconds());
+ regularBuilder.newRow(clustering);
+
+ // If a CQL table, add the "row marker"
+ if (update.metadata().isCQLTable() && useRowMarker)
+ regularBuilder.addPrimaryKeyLivenessInfo(LivenessInfo.create(update.metadata(), timestamp, ttl, localDeletionTime));
+ }
- // If a CQL table, add the "row marker"
- if (update.metadata().isCQLTable() && useRowMarker)
- regularWriter.writePartitionKeyLivenessInfo(defaultLiveness);
+ private Row.Builder builder()
+ {
+ assert staticBuilder == null : "Cannot update both static and non-static columns with the same RowUpdateBuilder object";
+ if (regularBuilder == null)
+ {
+ // we don't force people to call clustering() if the table has no clustering, so call it ourselves
+ assert update.metadata().comparator.size() == 0 : "Missing call to clustering()";
+ startRow(Clustering.EMPTY);
}
- return regularWriter;
+ return regularBuilder;
}
- private Row.Writer staticWriter()
+ private Row.Builder staticBuilder()
{
- assert regularWriter == null : "Cannot update both static and non-static columns with the same RowUpdateBuilder object";
- if (staticWriter == null)
- staticWriter = update.staticWriter();
- return staticWriter;
+ assert regularBuilder == null : "Cannot update both static and non-static columns with the same RowUpdateBuilder object";
+ if (staticBuilder == null)
+ {
+ staticBuilder = ArrayBackedRow.unsortedBuilder(update.columns().statics, FBUtilities.nowInSeconds());
+ staticBuilder.newRow(Clustering.STATIC_CLUSTERING);
+ }
+ return staticBuilder;
}
- private Row.Writer writer(ColumnDefinition c)
+ private Row.Builder builder(ColumnDefinition c)
{
- return c.isStatic() ? staticWriter() : writer();
+ return c.isStatic() ? staticBuilder() : builder();
}
public RowUpdateBuilder(CFMetaData metadata, long timestamp, Object partitionKey)
@@ -145,18 +161,17 @@ public class RowUpdateBuilder
public RowUpdateBuilder clustering(Object... clusteringValues)
{
assert clusteringValues.length == update.metadata().comparator.size()
- : "Invalid clustering values length. Expected: " + update.metadata().comparator.size() + " got: " + clusteringValues.length;
- hasSetClustering = true;
- if (clusteringValues.length > 0)
- Rows.writeClustering(update.metadata().comparator.make(clusteringValues), writer());
+ : "Invalid clustering values length. Expected: " + update.metadata().comparator.size() + " got: " + clusteringValues.length;
+
+ startRow(clusteringValues.length == 0 ? Clustering.EMPTY : update.metadata().comparator.make(clusteringValues));
return this;
}
public Mutation build()
{
- Row.Writer writer = regularWriter == null ? staticWriter : regularWriter;
- if (writer != null)
- writer.endOfRow();
+ Row.Builder builder = regularBuilder == null ? staticBuilder : regularBuilder;
+ if (builder != null)
+ update.add(builder.build());
return mutation;
}
@@ -170,14 +185,16 @@ public class RowUpdateBuilder
{
assert clusteringValues.length == update.metadata().comparator.size() || (clusteringValues.length == 0 && !update.columns().statics.isEmpty());
- Row.Writer writer = clusteringValues.length == update.metadata().comparator.size()
- ? update.writer()
- : update.staticWriter();
+ boolean isStatic = clusteringValues.length != update.metadata().comparator.size();
+ Row.Builder builder = ArrayBackedRow.sortedBuilder(isStatic ? update.columns().statics : update.columns().regulars);
- if (clusteringValues.length > 0)
- Rows.writeClustering(update.metadata().comparator.make(clusteringValues), writer);
- writer.writeRowDeletion(new SimpleDeletionTime(timestamp, FBUtilities.nowInSeconds()));
- writer.endOfRow();
+ if (isStatic)
+ builder.newRow(Clustering.STATIC_CLUSTERING);
+ else
+ builder.newRow(clusteringValues.length == 0 ? Clustering.EMPTY : update.metadata().comparator.make(clusteringValues));
+ builder.addRowDeletion(new DeletionTime(timestamp, FBUtilities.nowInSeconds()));
+
+ update.add(builder.build());
}
public static Mutation deleteRow(CFMetaData metadata, long timestamp, Mutation mutation, Object... clusteringValues)
@@ -219,22 +236,21 @@ public class RowUpdateBuilder
{
ColumnDefinition c = getDefinition(columnName);
assert c != null : "Cannot find column " + columnName;
- assert c.isStatic() || update.metadata().comparator.size() == 0 || hasSetClustering : "Cannot set non static column " + c + " since no clustering has been provided";
+ assert c.isStatic() || update.metadata().comparator.size() == 0 || regularBuilder != null : "Cannot set non static column " + c + " since no clustering has been provided";
assert c.type.isCollection() && c.type.isMultiCell();
- writer(c).writeComplexDeletion(c, new SimpleDeletionTime(defaultLiveness.timestamp() - 1, deletionTime.localDeletionTime()));
+ builder(c).addComplexDeletion(c, new DeletionTime(timestamp - 1, localDeletionTime));
return this;
}
public RowUpdateBuilder addRangeTombstone(RangeTombstone rt)
{
- update.addRangeTombstone(rt);
+ update.add(rt);
return this;
}
public RowUpdateBuilder addRangeTombstone(Slice slice)
{
- update.addRangeTombstone(slice, deletionTime);
- return this;
+ return addRangeTombstone(new RangeTombstone(slice, deletionTime));
}
public RowUpdateBuilder addRangeTombstone(Object start, Object end)
@@ -251,13 +267,17 @@ public class RowUpdateBuilder
return add(c, value);
}
+ private Cell makeCell(ColumnDefinition c, ByteBuffer value, CellPath path)
+ {
+ return value == null
+ ? BufferCell.tombstone(c, timestamp, localDeletionTime)
+ : (ttl == LivenessInfo.NO_TTL ? BufferCell.live(update.metadata(), c, timestamp, value, path) : BufferCell.expiring(c, timestamp, ttl, localDeletionTime, value, path));
+ }
+
public RowUpdateBuilder add(ColumnDefinition columnDefinition, Object value)
{
- assert columnDefinition.isStatic() || update.metadata().comparator.size() == 0 || hasSetClustering : "Cannot set non static column " + columnDefinition + " since no clustering hasn't been provided";
- if (value == null)
- writer(columnDefinition).writeCell(columnDefinition, false, ByteBufferUtil.EMPTY_BYTE_BUFFER, deletionLiveness, null);
- else
- writer(columnDefinition).writeCell(columnDefinition, false, bb(value, columnDefinition.type), defaultLiveness, null);
+ assert columnDefinition.isStatic() || update.metadata().comparator.size() == 0 || regularBuilder != null : "Cannot set non static column " + columnDefinition + " since no clustering hasn't been provided";
+ builder(columnDefinition).addCell(makeCell(columnDefinition, bb(value, columnDefinition.type), null));
return this;
}
@@ -273,8 +293,11 @@ public class RowUpdateBuilder
return add(columnDefinition, null);
}
- private ByteBuffer bb(Object value, AbstractType<?> type)
+ private static ByteBuffer bb(Object value, AbstractType<?> type)
{
+ if (value == null)
+ return null;
+
if (value instanceof ByteBuffer)
return (ByteBuffer)value;
@@ -306,30 +329,30 @@ public class RowUpdateBuilder
public RowUpdateBuilder addMapEntry(String columnName, Object key, Object value)
{
ColumnDefinition c = getDefinition(columnName);
- assert c.isStatic() || update.metadata().comparator.size() == 0 || hasSetClustering : "Cannot set non static column " + c + " since no clustering has been provided";
+ assert c.isStatic() || update.metadata().comparator.size() == 0 || regularBuilder != null : "Cannot set non static column " + c + " since no clustering has been provided";
assert c.type instanceof MapType && c.type.isMultiCell();
MapType mt = (MapType)c.type;
- writer(c).writeCell(c, false, bb(value, mt.getValuesType()), defaultLiveness, CellPath.create(bb(key, mt.getKeysType())));
+ builder(c).addCell(makeCell(c, bb(value, mt.getValuesType()), CellPath.create(bb(key, mt.getKeysType()))));
return this;
}
public RowUpdateBuilder addListEntry(String columnName, Object value)
{
ColumnDefinition c = getDefinition(columnName);
- assert c.isStatic() || hasSetClustering : "Cannot set non static column " + c + " since no clustering has been provided";
+ assert c.isStatic() || regularBuilder != null : "Cannot set non static column " + c + " since no clustering has been provided";
assert c.type instanceof ListType && c.type.isMultiCell();
ListType lt = (ListType)c.type;
- writer(c).writeCell(c, false, bb(value, lt.getElementsType()), defaultLiveness, CellPath.create(ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes())));
+ builder(c).addCell(makeCell(c, bb(value, lt.getElementsType()), CellPath.create(ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes()))));
return this;
}
public RowUpdateBuilder addSetEntry(String columnName, Object value)
{
ColumnDefinition c = getDefinition(columnName);
- assert c.isStatic() || hasSetClustering : "Cannot set non static column " + c + " since no clustering has been provided";
+ assert c.isStatic() || regularBuilder != null : "Cannot set non static column " + c + " since no clustering has been provided";
assert c.type instanceof SetType && c.type.isMultiCell();
SetType st = (SetType)c.type;
- writer(c).writeCell(c, false, ByteBufferUtil.EMPTY_BYTE_BUFFER, defaultLiveness, CellPath.create(bb(value, st.getElementsType())));
+ builder(c).addCell(makeCell(c, ByteBufferUtil.EMPTY_BYTE_BUFFER, CellPath.create(bb(value, st.getElementsType()))));
return this;
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/24575994/src/java/org/apache/cassandra/db/SerializationHeader.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/SerializationHeader.java b/src/java/org/apache/cassandra/db/SerializationHeader.java
index c720804..5784260 100644
--- a/src/java/org/apache/cassandra/db/SerializationHeader.java
+++ b/src/java/org/apache/cassandra/db/SerializationHeader.java
@@ -17,7 +17,6 @@
*/
package org.apache.cassandra.db;
-import java.io.DataInput;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.*;
@@ -97,7 +96,7 @@ public class SerializationHeader
// We always use a dense layout for the static row. Having very many static columns with only a few set at
// any given time doesn't feel very common at all (and we already optimize the case where no static at all
// are provided).
- return isStatic ? false : useSparseColumnLayout;
+ return !isStatic && useSparseColumnLayout;
}
public static SerializationHeader forKeyCache(CFMetaData metadata)
@@ -159,13 +158,7 @@ public class SerializationHeader
private static List<AbstractType<?>> typesOf(List<ColumnDefinition> columns)
{
- return ImmutableList.copyOf(Lists.transform(columns, new Function<ColumnDefinition, AbstractType<?>>()
- {
- public AbstractType<?> apply(ColumnDefinition column)
- {
- return column.type;
- }
- }));
+ return ImmutableList.copyOf(Lists.transform(columns, column -> column.type));
}
public PartitionColumns columns()
@@ -365,7 +358,7 @@ public class SerializationHeader
Columns.serializer.serialize(header.columns.regulars, out);
}
- public SerializationHeader deserializeForMessaging(DataInput in, CFMetaData metadata, boolean hasStatic) throws IOException
+ public SerializationHeader deserializeForMessaging(DataInputPlus in, CFMetaData metadata, boolean hasStatic) throws IOException
{
RowStats stats = RowStats.serializer.deserialize(in);
@@ -458,7 +451,7 @@ public class SerializationHeader
return size;
}
- private void readColumnsWithType(DataInput in, Map<ByteBuffer, AbstractType<?>> typeMap) throws IOException
+ private void readColumnsWithType(DataInputPlus in, Map<ByteBuffer, AbstractType<?>> typeMap) throws IOException
{
int length = in.readUnsignedShort();
for (int i = 0; i < length; i++)
@@ -474,7 +467,7 @@ public class SerializationHeader
ByteBufferUtil.writeWithLength(UTF8Type.instance.decompose(type.toString()), out);
}
- private AbstractType<?> readType(DataInput in) throws IOException
+ private AbstractType<?> readType(DataInputPlus in) throws IOException
{
ByteBuffer raw = ByteBufferUtil.readWithLength(in);
return TypeParser.parse(UTF8Type.instance.compose(raw));
http://git-wip-us.apache.org/repos/asf/cassandra/blob/24575994/src/java/org/apache/cassandra/db/SimpleClustering.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/SimpleClustering.java b/src/java/org/apache/cassandra/db/SimpleClustering.java
deleted file mode 100644
index 8b1cb7b..0000000
--- a/src/java/org/apache/cassandra/db/SimpleClustering.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.cassandra.db;
-
-import java.nio.ByteBuffer;
-
-import org.apache.cassandra.utils.ObjectSizes;
-
-public class SimpleClustering extends Clustering
-{
- private static final long EMPTY_SIZE = ObjectSizes.measure(new SimpleClustering(new ByteBuffer[0]));
-
- private final ByteBuffer[] values;
-
- public SimpleClustering(ByteBuffer... values)
- {
- this.values = values;
- }
-
- public SimpleClustering(ByteBuffer value)
- {
- this(new ByteBuffer[]{ value });
- }
-
- public int size()
- {
- return values.length;
- }
-
- public ByteBuffer get(int i)
- {
- return values[i];
- }
-
- public ByteBuffer[] getRawValues()
- {
- return values;
- }
-
- @Override
- public long unsharedHeapSize()
- {
- return EMPTY_SIZE + ObjectSizes.sizeOnHeapOf(values);
- }
-
- @Override
- public Clustering takeAlias()
- {
- return this;
- }
-
- public static Builder builder(int size)
- {
- return new Builder(size);
- }
-
- public static class Builder implements Writer
- {
- private final ByteBuffer[] values;
- private int idx;
-
- private Builder(int size)
- {
- this.values = new ByteBuffer[size];
- }
-
- public void writeClusteringValue(ByteBuffer value)
- {
- values[idx++] = value;
- }
-
- public SimpleClustering build()
- {
- assert idx == values.length;
- return new SimpleClustering(values);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/24575994/src/java/org/apache/cassandra/db/SimpleDeletionTime.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/SimpleDeletionTime.java b/src/java/org/apache/cassandra/db/SimpleDeletionTime.java
deleted file mode 100644
index 738c5e6..0000000
--- a/src/java/org/apache/cassandra/db/SimpleDeletionTime.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.cassandra.db;
-
-import java.io.DataInput;
-import java.io.IOException;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Objects;
-
-import org.apache.cassandra.cache.IMeasurableMemory;
-import org.apache.cassandra.io.ISerializer;
-import org.apache.cassandra.io.util.DataOutputPlus;
-import org.apache.cassandra.io.util.FileUtils;
-import org.apache.cassandra.utils.ObjectSizes;
-
-/**
- * Simple implementation of DeletionTime.
- */
-public class SimpleDeletionTime extends DeletionTime
-{
- public final long markedForDeleteAt;
- public final int localDeletionTime;
-
- @VisibleForTesting
- public SimpleDeletionTime(long markedForDeleteAt, int localDeletionTime)
- {
- this.markedForDeleteAt = markedForDeleteAt;
- this.localDeletionTime = localDeletionTime;
- }
-
- public long markedForDeleteAt()
- {
- return markedForDeleteAt;
- }
-
- public int localDeletionTime()
- {
- return localDeletionTime;
- }
-
- public DeletionTime takeAlias()
- {
- return this;
- }
-}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/24575994/src/java/org/apache/cassandra/db/SimpleLivenessInfo.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/SimpleLivenessInfo.java b/src/java/org/apache/cassandra/db/SimpleLivenessInfo.java
deleted file mode 100644
index fea1b86..0000000
--- a/src/java/org/apache/cassandra/db/SimpleLivenessInfo.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.cassandra.db;
-
-import java.util.Objects;
-import java.security.MessageDigest;
-
-import org.apache.cassandra.config.CFMetaData;
-import org.apache.cassandra.serializers.MarshalException;
-import org.apache.cassandra.utils.FBUtilities;
-
-public class SimpleLivenessInfo extends AbstractLivenessInfo
-{
- private final long timestamp;
- private final int ttl;
- private final int localDeletionTime;
-
- // Note that while some code use this ctor, the two following static creation methods
- // are usually less error prone.
- SimpleLivenessInfo(long timestamp, int ttl, int localDeletionTime)
- {
- this.timestamp = timestamp;
- this.ttl = ttl;
- this.localDeletionTime = localDeletionTime;
- }
-
- public static SimpleLivenessInfo forUpdate(long timestamp, int ttl, int nowInSec, CFMetaData metadata)
- {
- if (ttl == NO_TTL)
- ttl = metadata.getDefaultTimeToLive();
-
- return new SimpleLivenessInfo(timestamp, ttl, ttl == NO_TTL ? NO_DELETION_TIME : nowInSec + ttl);
- }
-
- public static SimpleLivenessInfo forDeletion(long timestamp, int localDeletionTime)
- {
- return new SimpleLivenessInfo(timestamp, NO_TTL, localDeletionTime);
- }
-
- public long timestamp()
- {
- return timestamp;
- }
-
- public int ttl()
- {
- return ttl;
- }
-
- public int localDeletionTime()
- {
- return localDeletionTime;
- }
-
- @Override
- public LivenessInfo takeAlias()
- {
- return this;
- }
-}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/24575994/src/java/org/apache/cassandra/db/SinglePartitionNamesCommand.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/SinglePartitionNamesCommand.java b/src/java/org/apache/cassandra/db/SinglePartitionNamesCommand.java
index cb43cd3..53ead14 100644
--- a/src/java/org/apache/cassandra/db/SinglePartitionNamesCommand.java
+++ b/src/java/org/apache/cassandra/db/SinglePartitionNamesCommand.java
@@ -146,7 +146,7 @@ public class SinglePartitionNamesCommand extends SinglePartitionReadCommand<Clus
try (UnfilteredRowIterator iter = result.unfilteredIterator(columnFilter(), Slices.ALL, false))
{
- final Mutation mutation = new Mutation(UnfilteredRowIterators.toUpdate(iter));
+ final Mutation mutation = new Mutation(PartitionUpdate.fromIterator(iter));
StageManager.getStage(Stage.MUTATION).execute(new Runnable()
{
public void run()
@@ -232,7 +232,7 @@ public class SinglePartitionNamesCommand extends SinglePartitionReadCommand<Clus
// We can remove a row if it has data that is more recent that the next sstable to consider for the data that the query
// cares about. And the data we care about is 1) the row timestamp (since every query cares if the row exists or not)
// and 2) the requested columns.
- if (!row.primaryKeyLivenessInfo().hasTimestamp() || row.primaryKeyLivenessInfo().timestamp() <= sstableTimestamp)
+ if (row.primaryKeyLivenessInfo().isEmpty() || row.primaryKeyLivenessInfo().timestamp() <= sstableTimestamp)
return false;
for (ColumnDefinition column : requestedColumns)
@@ -242,7 +242,7 @@ public class SinglePartitionNamesCommand extends SinglePartitionReadCommand<Clus
return false;
Cell cell = row.getCell(column);
- if (cell == null || cell.livenessInfo().timestamp() <= sstableTimestamp)
+ if (cell == null || cell.timestamp() <= sstableTimestamp)
return false;
}
return true;
http://git-wip-us.apache.org/repos/asf/cassandra/blob/24575994/src/java/org/apache/cassandra/db/SinglePartitionReadCommand.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/SinglePartitionReadCommand.java b/src/java/org/apache/cassandra/db/SinglePartitionReadCommand.java
index f9f583f..80711d6 100644
--- a/src/java/org/apache/cassandra/db/SinglePartitionReadCommand.java
+++ b/src/java/org/apache/cassandra/db/SinglePartitionReadCommand.java
@@ -17,7 +17,6 @@
*/
package org.apache.cassandra.db;
-import java.io.DataInput;
import java.io.IOException;
import java.util.*;
@@ -29,6 +28,7 @@ import org.apache.cassandra.db.rows.*;
import org.apache.cassandra.db.filter.*;
import org.apache.cassandra.db.partitions.*;
import org.apache.cassandra.exceptions.RequestExecutionException;
+import org.apache.cassandra.io.util.DataInputPlus;
import org.apache.cassandra.io.util.DataOutputPlus;
import org.apache.cassandra.metrics.TableMetrics;
import org.apache.cassandra.service.*;
@@ -483,7 +483,7 @@ public abstract class SinglePartitionReadCommand<F extends ClusteringIndexFilter
private static class Deserializer extends SelectionDeserializer
{
- public ReadCommand deserialize(DataInput in, int version, boolean isDigest, boolean isForThrift, CFMetaData metadata, int nowInSec, ColumnFilter columnFilter, RowFilter rowFilter, DataLimits limits)
+ public ReadCommand deserialize(DataInputPlus in, int version, boolean isDigest, boolean isForThrift, CFMetaData metadata, int nowInSec, ColumnFilter columnFilter, RowFilter rowFilter, DataLimits limits)
throws IOException
{
DecoratedKey key = StorageService.getPartitioner().decorateKey(metadata.getKeyValidator().readValue(in));