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

com.palantir.atlasdb.keyvalue.impl.Cells Maven / Gradle / Ivy

There is a newer version: 0.1152.0
Show 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.impl;

import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.collect.AbstractIterator;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
import com.google.common.collect.Maps;
import com.google.common.collect.PeekingIterator;
import com.google.common.collect.Sets;
import com.google.common.io.BaseEncoding;
import com.google.common.primitives.UnsignedBytes;
import com.palantir.atlasdb.keyvalue.api.Cell;
import com.palantir.atlasdb.keyvalue.api.RowResult;
import com.palantir.atlasdb.transaction.api.TransactionConflictException.CellConflict;
import com.palantir.atlasdb.transaction.impl.TransactionConstants;
import com.palantir.common.annotation.Output;
import com.palantir.logsafe.logger.SafeLogger;
import com.palantir.logsafe.logger.SafeLoggerFactory;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.NavigableMap;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeMap;

public final class Cells {
    private static final SafeLogger log = SafeLoggerFactory.get(Cells.class);

    private Cells() {
        /* */
    }

    public static SortedSet getRows(Iterable cells) {
        if (Iterables.isEmpty(cells)) {
            return ImmutableSortedSet.orderedBy(UnsignedBytes.lexicographicalComparator())
                    .build();
        }
        return FluentIterable.from(cells)
                .transform(Cell::getRowName)
                .toSortedSet(UnsignedBytes.lexicographicalComparator());
    }

    static final byte[] SMALLEST_NAME = new byte[] {0};
    static final byte[] LARGEST_NAME = getLargestName();

    static byte[] getLargestName() {
        byte[] name = new byte[Cell.MAX_NAME_LENGTH];
        for (int i = 0; i < Cell.MAX_NAME_LENGTH; i++) {
            name[i] = (byte) 0xff;
        }
        return name;
    }

    public static Cell createSmallestCellForRow(byte[] rowName) {
        return Cell.create(rowName, SMALLEST_NAME);
    }

    public static Cell createLargestCellForRow(byte[] rowName) {
        return Cell.create(rowName, LARGEST_NAME);
    }

    public static Set cellsWithConstantColumn(Iterable rows, byte[] col) {
        return cellsWithConstantColumn(new HashSet(), rows, col);
    }

    public static Set cellsWithConstantColumn(Collection rows, byte[] col) {
        return cellsWithConstantColumn(Sets.newHashSetWithExpectedSize(rows.size()), rows, col);
    }

    private static Set cellsWithConstantColumn(@Output Set collector, Iterable rows, byte[] col) {
        for (byte[] row : rows) {
            collector.add(Cell.create(row, col));
        }
        return collector;
    }

    public static  NavigableMap> breakCellsUpByRow(
            Iterable> map) {
        NavigableMap> ret = new TreeMap<>(UnsignedBytes.lexicographicalComparator());
        for (Map.Entry e : map) {
            byte[] row = e.getKey().getRowName();
            NavigableMap sortedMap =
                    ret.computeIfAbsent(row, rowName -> new TreeMap<>(UnsignedBytes.lexicographicalComparator()));
            sortedMap.put(e.getKey().getColumnName(), e.getValue());
        }
        return ret;
    }

    public static  NavigableMap> breakCellsUpByRow(Map map) {
        return breakCellsUpByRow(map.entrySet());
    }

    public static NavigableMap> groupCellsByRow(Set cells) {
        NavigableMap> result = new TreeMap<>(UnsignedBytes.lexicographicalComparator());
        for (Cell cell : cells) {
            byte[] row = cell.getRowName();
            result.computeIfAbsent(row, _row -> new HashSet<>()).add(cell);
        }
        return result;
    }

    /**
     * The Collection provided to this function has to be sorted and strictly increasing.
     */
    public static  Iterator> createRowView(final Collection> sortedIterator) {
        final PeekingIterator> it = Iterators.peekingIterator(sortedIterator.iterator());
        Iterator>> resultIt =
                new AbstractIterator>>() {
                    byte[] row = null;
                    NavigableMap map = null;

                    @Override
                    protected Map.Entry> computeNext() {
                        if (!it.hasNext()) {
                            return endOfData();
                        }
                        row = it.peek().getKey().getRowName();
                        ImmutableSortedMap.Builder mapBuilder =
                                ImmutableSortedMap.orderedBy(UnsignedBytes.lexicographicalComparator());
                        while (it.hasNext()) {
                            Map.Entry peek = it.peek();
                            if (!Arrays.equals(peek.getKey().getRowName(), row)) {
                                break;
                            }
                            mapBuilder.put(peek.getKey().getColumnName(), peek.getValue());
                            it.next();
                        }
                        map = mapBuilder.buildOrThrow();
                        return Maps.immutableEntry(row, map);
                    }
                };
        return RowResults.viewOfEntries(resultIt);
    }

    public static  Map convertRowResultsToCells(Collection> rows) {
        Map ret = Maps.newHashMapWithExpectedSize(rows.size());
        for (RowResult row : rows) {
            byte[] rowName = row.getRowName();
            for (Map.Entry col : row.getColumns().entrySet()) {
                Cell cell = Cell.create(rowName, col.getKey());
                ret.put(cell, col.getValue());
            }
        }
        return ret;
    }

    public static  Map constantValueMap(Set keys, V value) {
        return Maps.asMap(keys, Functions.constant(value));
    }

    public static long getApproxSizeOfCell(Cell cell) {
        return cell.getColumnName().length
                + cell.getRowName().length
                + TransactionConstants.APPROX_IN_MEM_CELL_OVERHEAD_BYTES;
    }

    public static Function getNameFromBytesFunction() {
        return Cells::getNameFromBytes;
    }

    public static String getNameFromBytes(byte[] name) {
        if (name == null) {
            return "null";
        }
        return BaseEncoding.base16().lowerCase().encode(name);
    }

    public static CellConflict createConflict(Cell cell, long theirStartTs, long theirCommitTs) {
        return new CellConflict(cell, getHumanReadableCellName(cell), theirStartTs, theirCommitTs);
    }

    public static String getHumanReadableCellName(Cell cell) {
        if (cell == null) {
            return "null";
        }
        return cell.toString();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy