All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.palantir.atlasdb.keyvalue.cassandra.RowColumnRangeExtractor Maven / Gradle / Ivy

The newest version!
/*
 * (c) Copyright 2018 Palantir Technologies Inc. All rights reserved.
 *
 * Licensed 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 com.palantir.atlasdb.keyvalue.cassandra;

import com.codahale.metrics.Counter;
import com.google.common.base.Suppliers;
import com.google.common.collect.Maps;
import com.palantir.atlasdb.AtlasDbMetricNames.CellFilterMetrics;
import com.palantir.atlasdb.keyvalue.api.Cell;
import com.palantir.atlasdb.keyvalue.api.Value;
import com.palantir.atlasdb.keyvalue.cassandra.CassandraKeyValueServices.ColumnAndTimestamp;
import com.palantir.atlasdb.tracing.TraceStatistics;
import com.palantir.atlasdb.util.MetricsManager;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;
import org.apache.cassandra.thrift.Column;
import org.apache.cassandra.thrift.ColumnOrSuperColumn;

@SuppressWarnings("IllegalType") // explicitly need LinkedHashMap for insertion ordering contract
final class RowColumnRangeExtractor {
    private RowColumnRangeExtractor() {}

    static final class RowColumnRangeResult {
        private final Map> results;
        private final Map rowsToLastCompositeColumns;
        private final Set emptyRows;
        private final Map rowsToRawColumnCount;

        @SuppressWarnings("NonApiType") // explicitly require LinkedHashMap to maintain ordering
        private RowColumnRangeResult(
                Map> results,
                Map rowsToLastCompositeColumns,
                Set emptyRows,
                Map rowsToRawColumnCount) {
            this.results = results;
            this.rowsToLastCompositeColumns = rowsToLastCompositeColumns;
            this.emptyRows = emptyRows;
            this.rowsToRawColumnCount = rowsToRawColumnCount;
        }

        public Map> getResults() {
            return Collections.unmodifiableMap(results);
        }

        public Map getRowsToLastCompositeColumns() {
            return Collections.unmodifiableMap(rowsToLastCompositeColumns);
        }

        public Set getEmptyRows() {
            return Collections.unmodifiableSet(emptyRows);
        }

        public Map getRowsToRawColumnCount() {
            return Collections.unmodifiableMap(rowsToRawColumnCount);
        }
    }

    static RowColumnRangeResult extract(
            Collection canonicalRows,
            Map> colsByKey,
            long startTs,
            MetricsManager metricsManager) {
        IdentityHashMap> collector = new IdentityHashMap<>(canonicalRows.size());
        IdentityHashMap rowsToLastCompositeColumns = new IdentityHashMap<>(canonicalRows.size());
        IdentityHashMap rowsToRawColumnCount = new IdentityHashMap<>(canonicalRows.size());
        Set emptyRows = Collections.newSetFromMap(new IdentityHashMap<>(0));

        // lazily create counter to avoid overhead when not needed
        Supplier notLatestVisibleValueCellFilterCounter =
                Suppliers.memoize(() -> metricsManager.registerOrGetCounter(
                        RowColumnRangeExtractor.class, CellFilterMetrics.NOT_LATEST_VISIBLE_VALUE));

        if (TraceStatistics.isTraceObservable()) {
            canonicalRows.forEach(row -> TraceStatistics.incBytesRead(row.length));
        }

        // Make sure returned maps are keyed by the given rows
        Map canonicalRowsByHash = Maps.uniqueIndex(canonicalRows, ByteBuffer::wrap);
        for (Map.Entry> colEntry : colsByKey.entrySet()) {
            byte[] rawRow = CassandraKeyValueServices.getBytesFromByteBuffer(colEntry.getKey());
            TraceStatistics.incBytesRead(rawRow);

            byte[] row = canonicalRowsByHash.get(ByteBuffer.wrap(rawRow));
            List columns = colEntry.getValue();

            if (columns.isEmpty()) {
                emptyRows.add(row);
            } else {
                rowsToLastCompositeColumns.put(
                        row, columns.get(columns.size() - 1).getColumn());
            }
            rowsToRawColumnCount.put(row, columns.size());
            for (ColumnOrSuperColumn c : columns) {
                ColumnAndTimestamp columnAndTimestamp = CassandraKeyValueServices.decomposeColumnName(c.getColumn());
                // Column name
                TraceStatistics.incBytesRead(columnAndTimestamp.columnName());
                // Column value
                TraceStatistics.incBytesRead(c.getColumn().getValue().length);

                long ts = columnAndTimestamp.timestamp();
                if (ts < startTs) {
                    Cell cell = Cell.create(row, columnAndTimestamp.columnName());
                    LinkedHashMap cellToValue =
                            collector.computeIfAbsent(row, _b -> new LinkedHashMap<>(1));
                    if (cellToValue.containsKey(cell)) {
                        TraceStatistics.incSkippedValues(1L);
                        notLatestVisibleValueCellFilterCounter.get().inc();
                    } else {
                        cellToValue.put(cell, Value.create(c.getColumn().getValue(), ts));
                    }
                } else {
                    TraceStatistics.incSkippedValues(1L);
                    notLatestVisibleValueCellFilterCounter.get().inc();
                }
            }
        }

        return new RowColumnRangeResult(collector, rowsToLastCompositeColumns, emptyRows, rowsToRawColumnCount);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy