adelapena commented on code in PR #1739:
URL: https://github.com/apache/cassandra/pull/1739#discussion_r931183451


##########
src/java/org/apache/cassandra/cql3/selection/ColumnTimestamps.java:
##########
@@ -0,0 +1,381 @@
+/*
+ * 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.cql3.selection;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import com.google.common.collect.BoundType;
+import com.google.common.collect.Range;
+
+import org.apache.cassandra.db.marshal.AbstractType;
+import org.apache.cassandra.db.marshal.UserType;
+import org.apache.cassandra.db.rows.Cell;
+import org.apache.cassandra.serializers.CollectionSerializer;
+import org.apache.cassandra.transport.ProtocolVersion;
+import org.apache.cassandra.utils.ByteBufferUtil;
+
+/**
+ * Represents a list of timestamps associated to a CQL column. Those 
timestamps can either be writetimes or TTLs,
+ * according to {@link TimestampsType}.
+ */
+abstract class ColumnTimestamps
+{
+    /**
+     * The timestamps type.
+     */
+    protected final TimestampsType type;
+
+    protected ColumnTimestamps(TimestampsType type)
+    {
+        this.type = type;
+    }
+
+    /**
+     * @return the timestamps type
+     */
+    public TimestampsType type()
+    {
+        return type;
+    }
+
+    /**
+     * Retrieves the timestamps at the specified position.
+     *
+     * @param index the timestamps position
+     * @return the timestamps at the specified position or a {@link 
#NO_TIMESTAMP}
+     */
+    public abstract ColumnTimestamps get(int index);
+
+    public abstract ColumnTimestamps max();
+
+    /**
+     * Returns a view of the portion of the timestamps within the specified 
range.
+     *
+     * @param range the indexes range
+     * @return a view of the specified range within this {@link 
ColumnTimestamps}
+     */
+    public abstract ColumnTimestamps slice(Range<Integer> range);
+
+    /**
+     * Converts the timestamps into their serialized form.
+     *
+     * @param protocolVersion the protocol version to use for the serialization
+     * @return the serialized timestamps
+     */
+    public abstract ByteBuffer toByteBuffer(ProtocolVersion protocolVersion);
+
+    /**
+     * Appends an empty timestamp at the end of this list.
+     */
+    public abstract void addNoTimestamp();
+
+    /**
+     * Appends the timestamp of the specified cell at the end of this list.
+     */
+    public abstract void addTimestampFrom(Cell<?> cell, int nowInSecond);
+
+    /**
+     * Creates a new {@link ColumnTimestamps} instance for the specified 
column type.
+     *
+     * @param timestampType the timestamps type
+     * @param columnType    the column type
+     * @return a {@link ColumnTimestamps} instance for the specified column 
type
+     */
+    static ColumnTimestamps newTimestamps(TimestampsType timestampType, 
AbstractType<?> columnType)
+    {
+        if (!columnType.isMultiCell())
+            return new SingleTimestamps(timestampType);
+
+        // For UserType we know that the size will not change, so we can 
initialize the array with the proper capacity.
+        if (columnType instanceof UserType)
+            return new MultipleTimestamps(timestampType, ((UserType) 
columnType).size());
+
+        return new MultipleTimestamps(timestampType, 0);
+    }
+
+    /**
+     * The type of represented timestamps.
+     */
+    public enum TimestampsType
+    {
+        WRITETIMES
+        {
+            @Override
+            long getTimestamp(Cell<?> cell, int nowInSecond)
+            {
+                return cell.timestamp();
+            }
+
+            @Override
+            long defaultValue()
+            {
+                return Long.MIN_VALUE;
+            }
+
+            @Override
+            ByteBuffer toByteBuffer(long timestamp)
+            {
+                return timestamp == defaultValue() ? null : 
ByteBufferUtil.bytes(timestamp);
+            }
+        },
+        TTLS
+        {
+            @Override
+            long getTimestamp(Cell<?> cell, int nowInSecond)
+            {
+                if (!cell.isExpiring())
+                    return defaultValue();
+
+                int remaining = cell.localDeletionTime() - nowInSecond;
+                return remaining >= 0 ? remaining : defaultValue();
+            }
+
+            @Override
+            long defaultValue()
+            {
+                return -1;
+            }
+
+            @Override
+            ByteBuffer toByteBuffer(long timestamp)
+            {
+                return timestamp == defaultValue() ? null : 
ByteBufferUtil.bytes((int) timestamp);
+            }
+        };
+
+        /**
+         * Extracts the timestamp from the specified cell.
+         *
+         * @param cell        the cell
+         * @param nowInSecond the query timestamp insecond
+         * @return the timestamp corresponding to this type
+         */
+        abstract long getTimestamp(Cell<?> cell, int nowInSecond);
+
+        /**
+         * Returns the value to use when there is no timestamp.
+         *
+         * @return the value to use when there is no timestamp
+         */
+        abstract long defaultValue();
+
+        /**
+         * Serializes the specified timestamp.
+         *
+         * @param timestamp the timestamp to serialize
+         * @return the bytes corresponding to the specified timestamp
+         */
+        abstract ByteBuffer toByteBuffer(long timestamp);
+    }
+
+    /**
+     * A {@link ColumnTimestamps} that doesn't contain any timestamps.
+     */
+    static final ColumnTimestamps NO_TIMESTAMP = new ColumnTimestamps(null)
+    {
+        @Override
+        public ColumnTimestamps get(int index)
+        {
+            return this;
+        }
+
+        @Override
+        public ColumnTimestamps max()
+        {
+            return this;
+        }
+
+        @Override
+        public ColumnTimestamps slice(Range<Integer> range)
+        {
+            return this;
+        }
+
+        @Override
+        public ByteBuffer toByteBuffer(ProtocolVersion protocolVersion)
+        {
+            return null;
+        }
+
+        @Override
+        public void addNoTimestamp()
+        {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void addTimestampFrom(Cell<?> cell, int nowInSecond)
+        {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public String toString()
+        {
+            return "no timestamp";
+        }
+    };
+
+    /**
+     * A {@link ColumnTimestamps} that can contains a single timestamp (for 
columns that aren't multicell).
+     */
+    private static class SingleTimestamps extends ColumnTimestamps
+    {
+        protected long timestamp;
+
+        public SingleTimestamps(TimestampsType type)
+        {
+            this(type, type.defaultValue());
+        }
+
+        public SingleTimestamps(TimestampsType type, long timestamp)
+        {
+            super(type);
+            this.timestamp = timestamp;
+        }
+
+        @Override
+        public void addNoTimestamp()
+        {
+            timestamp = type.defaultValue();
+        }
+
+        @Override
+        public void addTimestampFrom(Cell<?> cell, int nowInSecond)
+        {
+            timestamp = type.getTimestamp(cell, nowInSecond);
+        }
+
+        @Override
+        public ColumnTimestamps get(int index)
+        {
+            // If this method is called it means that it is an element 
selection on a frozen collection/UDT,
+            // so we can safely return this Timestamps as all the elements 
also share that timestamp
+            return this;
+        }
+
+        @Override
+        public ColumnTimestamps max()
+        {
+            return this;
+        }
+
+        @Override
+        public ColumnTimestamps slice(Range<Integer> range)
+        {
+            return range.isEmpty() ? NO_TIMESTAMP : this;
+        }
+
+        @Override
+        public ByteBuffer toByteBuffer(ProtocolVersion protocolVersion)
+        {
+            return timestamp == type.defaultValue() ? null : 
type.toByteBuffer(timestamp);
+        }
+
+        @Override
+        public String toString()
+        {
+            return type + ": " + timestamp;
+        }
+    }
+
+    /**
+     * A {@link ColumnTimestamps} that can contain multiple timestamps (for 
unfrozen collections or UDTs).
+     */
+    private static final class MultipleTimestamps extends ColumnTimestamps
+    {
+        private final List<Long> timestamps;
+
+        public MultipleTimestamps(TimestampsType type, int initialCapacity)
+        {
+            this(type, new ArrayList<>(initialCapacity));
+        }
+
+        public MultipleTimestamps(TimestampsType type, List<Long> timestamps)
+        {
+            super(type);
+            this.timestamps = timestamps;
+        }
+
+        @Override
+        public void addNoTimestamp()
+        {
+            timestamps.add(type.defaultValue());
+        }
+
+        @Override
+        public void addTimestampFrom(Cell<?> cell, int nowInSecond)
+        {
+            timestamps.add(type.getTimestamp(cell, nowInSecond));
+        }
+
+        @Override
+        public ColumnTimestamps get(int index)
+        {
+            return timestamps.isEmpty()
+                   ? NO_TIMESTAMP
+                   : new SingleTimestamps(type, timestamps.get(index));
+        }
+
+        @Override
+        public ColumnTimestamps max()
+        {
+            return timestamps.isEmpty()
+                   ? NO_TIMESTAMP
+                   : new SingleTimestamps(type, Collections.max(timestamps));
+        }
+
+        @Override
+        public ColumnTimestamps slice(Range<Integer> range)
+        {
+            if (range.isEmpty())
+                return NO_TIMESTAMP;
+
+            int from = !range.hasLowerBound() ? 0
+                                              : range.lowerBoundType() == 
BoundType.CLOSED ? range.lowerEndpoint()
+                                                                               
            : range.lowerEndpoint() + 1;
+            int to = !range.hasUpperBound() ? timestamps.size()
+                                            : range.upperBoundType() == 
BoundType.CLOSED ? range.upperEndpoint() + 1
+                                                                               
          : range.upperEndpoint();

Review Comment:
   Changed to the proposed format and added some comments about the 
calculations.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to