Search in sources :

Example 31 with Value

use of com.palantir.atlasdb.keyvalue.api.Value in project atlasdb by palantir.

the class CassandraKeyValueServiceImpl method getMetadataForTables.

/**
 * Gets the metadata for all non-hidden tables.
 * <p>
 * Does not require all Cassandra nodes to be up and available, works as long as quorum is achieved.
 *
 * @return a mapping of table names to their respective metadata in form of a byte array.  Consider
 * {@link TableMetadata#BYTES_HYDRATOR} for hydrating.
 */
@Override
public Map<TableReference, byte[]> getMetadataForTables() {
    Map<TableReference, byte[]> tableToMetadataContents = Maps.newHashMap();
    // we don't even have a metadata table yet. Return empty map.
    if (!getAllTableReferencesWithoutFiltering().contains(AtlasDbConstants.DEFAULT_METADATA_TABLE)) {
        log.trace("getMetadata called with no _metadata table present");
        return tableToMetadataContents;
    }
    try (ClosableIterator<RowResult<Value>> range = getRange(AtlasDbConstants.DEFAULT_METADATA_TABLE, RangeRequest.all(), Long.MAX_VALUE)) {
        while (range.hasNext()) {
            RowResult<Value> valueRow = range.next();
            Iterable<Entry<Cell, Value>> cells = valueRow.getCells();
            for (Entry<Cell, Value> entry : cells) {
                Value value = entry.getValue();
                TableReference tableRef = CassandraKeyValueServices.tableReferenceFromBytes(entry.getKey().getRowName());
                byte[] contents;
                if (value == null) {
                    contents = AtlasDbConstants.EMPTY_TABLE_METADATA;
                } else {
                    contents = value.getContents();
                }
                if (!HiddenTables.isHidden(tableRef)) {
                    tableToMetadataContents.put(tableRef, contents);
                }
            }
        }
    }
    return tableToMetadataContents;
}
Also used : RowResult(com.palantir.atlasdb.keyvalue.api.RowResult) TableReference(com.palantir.atlasdb.keyvalue.api.TableReference) Entry(java.util.Map.Entry) Value(com.palantir.atlasdb.keyvalue.api.Value) Cell(com.palantir.atlasdb.keyvalue.api.Cell)

Example 32 with Value

use of com.palantir.atlasdb.keyvalue.api.Value in project atlasdb by palantir.

the class CassandraKeyValueServiceImpl method getRowsColumnRangeIteratorForSingleHost.

private Map<byte[], RowColumnRangeIterator> getRowsColumnRangeIteratorForSingleHost(InetSocketAddress host, TableReference tableRef, List<byte[]> rows, BatchColumnRangeSelection batchColumnRangeSelection, long startTs) {
    try {
        RowColumnRangeExtractor.RowColumnRangeResult firstPage = getRowsColumnRangeForSingleHost(host, tableRef, rows, batchColumnRangeSelection, startTs);
        Map<byte[], LinkedHashMap<Cell, Value>> results = firstPage.getResults();
        Map<byte[], Column> rowsToLastCompositeColumns = firstPage.getRowsToLastCompositeColumns();
        Map<byte[], byte[]> incompleteRowsToNextColumns = Maps.newHashMap();
        for (Entry<byte[], Column> e : rowsToLastCompositeColumns.entrySet()) {
            byte[] row = e.getKey();
            byte[] col = CassandraKeyValueServices.decomposeName(e.getValue()).getLhSide();
            // If we read a version of the cell before our start timestamp, it will be the most recent version
            // readable to us and we can continue to the next column. Otherwise we have to continue reading
            // this column.
            Map<Cell, Value> rowResult = results.get(row);
            boolean completedCell = (rowResult != null) && rowResult.containsKey(Cell.create(row, col));
            boolean endOfRange = isEndOfColumnRange(completedCell, col, firstPage.getRowsToRawColumnCount().get(row), batchColumnRangeSelection);
            if (!endOfRange) {
                byte[] nextCol = getNextColumnRangeColumn(completedCell, col);
                incompleteRowsToNextColumns.put(row, nextCol);
            }
        }
        Map<byte[], RowColumnRangeIterator> ret = Maps.newHashMapWithExpectedSize(rows.size());
        for (byte[] row : rowsToLastCompositeColumns.keySet()) {
            Iterator<Entry<Cell, Value>> resultIterator;
            Map<Cell, Value> result = results.get(row);
            if (result != null) {
                resultIterator = result.entrySet().iterator();
            } else {
                resultIterator = Collections.emptyIterator();
            }
            byte[] nextCol = incompleteRowsToNextColumns.get(row);
            if (nextCol == null) {
                ret.put(row, new LocalRowColumnRangeIterator(resultIterator));
            } else {
                BatchColumnRangeSelection newColumnRange = BatchColumnRangeSelection.create(nextCol, batchColumnRangeSelection.getEndCol(), batchColumnRangeSelection.getBatchHint());
                ret.put(row, new LocalRowColumnRangeIterator(Iterators.concat(resultIterator, getRowColumnRange(host, tableRef, row, newColumnRange, startTs))));
            }
        }
        // We saw no Cassandra results at all for these rows, so the entire column range is empty for these rows.
        for (byte[] row : firstPage.getEmptyRows()) {
            ret.put(row, new LocalRowColumnRangeIterator(Collections.emptyIterator()));
        }
        return ret;
    } catch (Exception e) {
        throw QosAwareThrowables.unwrapAndThrowRateLimitExceededOrAtlasDbDependencyException(e);
    }
}
Also used : BatchColumnRangeSelection(com.palantir.atlasdb.keyvalue.api.BatchColumnRangeSelection) LocalRowColumnRangeIterator(com.palantir.atlasdb.keyvalue.impl.LocalRowColumnRangeIterator) RowColumnRangeIterator(com.palantir.atlasdb.keyvalue.api.RowColumnRangeIterator) InsufficientConsistencyException(com.palantir.atlasdb.keyvalue.api.InsufficientConsistencyException) CheckAndSetException(com.palantir.atlasdb.keyvalue.api.CheckAndSetException) KeyAlreadyExistsException(com.palantir.atlasdb.keyvalue.api.KeyAlreadyExistsException) FunctionCheckedException(com.palantir.common.base.FunctionCheckedException) TException(org.apache.thrift.TException) UnavailableException(org.apache.cassandra.thrift.UnavailableException) PalantirRuntimeException(com.palantir.common.exception.PalantirRuntimeException) LinkedHashMap(java.util.LinkedHashMap) Entry(java.util.Map.Entry) LocalRowColumnRangeIterator(com.palantir.atlasdb.keyvalue.impl.LocalRowColumnRangeIterator) Column(org.apache.cassandra.thrift.Column) ColumnOrSuperColumn(org.apache.cassandra.thrift.ColumnOrSuperColumn) Value(com.palantir.atlasdb.keyvalue.api.Value) Cell(com.palantir.atlasdb.keyvalue.api.Cell)

Example 33 with Value

use of com.palantir.atlasdb.keyvalue.api.Value in project atlasdb by palantir.

the class CassandraKeyValueServiceImpl method getRowsForSingleHost.

private Map<Cell, Value> getRowsForSingleHost(final InetSocketAddress host, final TableReference tableRef, final List<byte[]> rows, final long startTs) {
    try {
        int rowCount = 0;
        final Map<Cell, Value> result = Maps.newHashMap();
        int fetchBatchCount = config.fetchBatchCount();
        for (final List<byte[]> batch : Lists.partition(rows, fetchBatchCount)) {
            rowCount += batch.size();
            result.putAll(clientPool.runWithRetryOnHost(host, new FunctionCheckedException<CassandraClient, Map<Cell, Value>, Exception>() {

                @Override
                public Map<Cell, Value> apply(CassandraClient client) throws Exception {
                    // We want to get all the columns in the row so set start and end to empty.
                    SlicePredicate pred = SlicePredicates.create(Range.ALL, Limit.NO_LIMIT);
                    List<ByteBuffer> rowNames = wrap(batch);
                    Map<ByteBuffer, List<ColumnOrSuperColumn>> results = wrappingQueryRunner.multiget("getRows", client, tableRef, rowNames, pred, readConsistency);
                    Map<Cell, Value> ret = Maps.newHashMapWithExpectedSize(batch.size());
                    new ValueExtractor(ret).extractResults(results, startTs, ColumnSelection.all());
                    return ret;
                }

                @Override
                public String toString() {
                    return "multiget_slice(" + tableRef.getQualifiedName() + ", " + batch.size() + " rows" + ")";
                }
            }));
        }
        if (rowCount > fetchBatchCount) {
            log.warn("Rebatched in getRows a call to {} that attempted to multiget {} rows; " + "this may indicate overly-large batching on a higher level.\n{}", LoggingArgs.tableRef(tableRef), SafeArg.of("rowCount", rowCount), SafeArg.of("stacktrace", CassandraKeyValueServices.getFilteredStackTrace("com.palantir")));
        }
        return ImmutableMap.copyOf(result);
    } catch (Exception e) {
        throw QosAwareThrowables.unwrapAndThrowRateLimitExceededOrAtlasDbDependencyException(e);
    }
}
Also used : SlicePredicate(org.apache.cassandra.thrift.SlicePredicate) ByteBuffer(java.nio.ByteBuffer) InsufficientConsistencyException(com.palantir.atlasdb.keyvalue.api.InsufficientConsistencyException) CheckAndSetException(com.palantir.atlasdb.keyvalue.api.CheckAndSetException) KeyAlreadyExistsException(com.palantir.atlasdb.keyvalue.api.KeyAlreadyExistsException) FunctionCheckedException(com.palantir.common.base.FunctionCheckedException) TException(org.apache.thrift.TException) UnavailableException(org.apache.cassandra.thrift.UnavailableException) PalantirRuntimeException(com.palantir.common.exception.PalantirRuntimeException) FunctionCheckedException(com.palantir.common.base.FunctionCheckedException) Value(com.palantir.atlasdb.keyvalue.api.Value) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList) Cell(com.palantir.atlasdb.keyvalue.api.Cell)

Example 34 with Value

use of com.palantir.atlasdb.keyvalue.api.Value in project atlasdb by palantir.

the class OneNodeDownGetTest method canGetRange.

@Test
public void canGetRange() {
    final RangeRequest range = RangeRequest.builder().endRowExclusive(OneNodeDownTestSuite.SECOND_ROW).build();
    ClosableIterator<RowResult<Value>> it = OneNodeDownTestSuite.kvs.getRange(OneNodeDownTestSuite.TEST_TABLE, range, Long.MAX_VALUE);
    ImmutableMap<byte[], Value> expectedColumns = ImmutableMap.of(OneNodeDownTestSuite.FIRST_COLUMN, OneNodeDownTestSuite.DEFAULT_VALUE, OneNodeDownTestSuite.SECOND_COLUMN, OneNodeDownTestSuite.DEFAULT_VALUE);
    RowResult<Value> expectedRowResult = RowResult.create(OneNodeDownTestSuite.FIRST_ROW, ImmutableSortedMap.copyOf(expectedColumns, UnsignedBytes.lexicographicalComparator()));
    assertThat(it).containsExactly(expectedRowResult);
}
Also used : RowResult(com.palantir.atlasdb.keyvalue.api.RowResult) RangeRequest(com.palantir.atlasdb.keyvalue.api.RangeRequest) Value(com.palantir.atlasdb.keyvalue.api.Value) Test(org.junit.Test)

Example 35 with Value

use of com.palantir.atlasdb.keyvalue.api.Value in project atlasdb by palantir.

the class SnapshotTransaction method partitionByRow.

/**
 * Partitions a {@link RowColumnRangeIterator} into contiguous blocks that share the same row name.
 * {@link KeyValueService#getRowsColumnRange(TableReference, Iterable, ColumnRangeSelection, int, long)} guarantees
 * that all columns for a single row are adjacent, so this method will return an {@link Iterator} with exactly one
 * entry per non-empty row.
 */
private Iterator<Map.Entry<byte[], RowColumnRangeIterator>> partitionByRow(RowColumnRangeIterator rawResults) {
    PeekingIterator<Map.Entry<Cell, Value>> peekableRawResults = Iterators.peekingIterator(rawResults);
    return new AbstractIterator<Map.Entry<byte[], RowColumnRangeIterator>>() {

        byte[] prevRowName;

        @Override
        protected Map.Entry<byte[], RowColumnRangeIterator> computeNext() {
            finishConsumingPreviousRow(peekableRawResults);
            if (!peekableRawResults.hasNext()) {
                return endOfData();
            }
            byte[] nextRowName = peekableRawResults.peek().getKey().getRowName();
            Iterator<Map.Entry<Cell, Value>> columnsIterator = new AbstractIterator<Map.Entry<Cell, Value>>() {

                @Override
                protected Map.Entry<Cell, Value> computeNext() {
                    if (!peekableRawResults.hasNext() || !Arrays.equals(peekableRawResults.peek().getKey().getRowName(), nextRowName)) {
                        return endOfData();
                    }
                    return peekableRawResults.next();
                }
            };
            prevRowName = nextRowName;
            return Maps.immutableEntry(nextRowName, new LocalRowColumnRangeIterator(columnsIterator));
        }

        private void finishConsumingPreviousRow(PeekingIterator<Map.Entry<Cell, Value>> iter) {
            int numConsumed = 0;
            while (iter.hasNext() && Arrays.equals(iter.peek().getKey().getRowName(), prevRowName)) {
                iter.next();
                numConsumed++;
            }
            if (numConsumed > 0) {
                log.warn("Not all columns for row {} were read. {} columns were discarded.", UnsafeArg.of("row", Arrays.toString(prevRowName)), SafeArg.of("numColumnsDiscarded", numConsumed));
            }
        }
    };
}
Also used : Entry(java.util.Map.Entry) LocalRowColumnRangeIterator(com.palantir.atlasdb.keyvalue.impl.LocalRowColumnRangeIterator) Value(com.palantir.atlasdb.keyvalue.api.Value) AbstractIterator(com.google.common.collect.AbstractIterator) PeekingIterator(com.google.common.collect.PeekingIterator) LocalRowColumnRangeIterator(com.palantir.atlasdb.keyvalue.impl.LocalRowColumnRangeIterator) RowColumnRangeIterator(com.palantir.atlasdb.keyvalue.api.RowColumnRangeIterator) Map(java.util.Map) ConcurrentNavigableMap(java.util.concurrent.ConcurrentNavigableMap) LinkedHashMap(java.util.LinkedHashMap) ImmutableSortedMap(com.google.common.collect.ImmutableSortedMap) ImmutableMap(com.google.common.collect.ImmutableMap) SortedMap(java.util.SortedMap) ConcurrentMap(java.util.concurrent.ConcurrentMap) ConcurrentSkipListMap(java.util.concurrent.ConcurrentSkipListMap) Cell(com.palantir.atlasdb.keyvalue.api.Cell)

Aggregations

Value (com.palantir.atlasdb.keyvalue.api.Value)74 Cell (com.palantir.atlasdb.keyvalue.api.Cell)55 RangeRequest (com.palantir.atlasdb.keyvalue.api.RangeRequest)20 RowResult (com.palantir.atlasdb.keyvalue.api.RowResult)18 Test (org.junit.Test)18 Entry (java.util.Map.Entry)16 TokenBackedBasicResultsPage (com.palantir.util.paging.TokenBackedBasicResultsPage)15 Map (java.util.Map)15 SortedMap (java.util.SortedMap)13 ImmutableMap (com.google.common.collect.ImmutableMap)12 TableReference (com.palantir.atlasdb.keyvalue.api.TableReference)10 LinkedHashMap (java.util.LinkedHashMap)9 ImmutableList (com.google.common.collect.ImmutableList)7 KeyAlreadyExistsException (com.palantir.atlasdb.keyvalue.api.KeyAlreadyExistsException)7 InsufficientConsistencyException (com.palantir.atlasdb.keyvalue.api.InsufficientConsistencyException)6 RowColumnRangeIterator (com.palantir.atlasdb.keyvalue.api.RowColumnRangeIterator)6 List (java.util.List)6 ImmutableSortedMap (com.google.common.collect.ImmutableSortedMap)5 BatchColumnRangeSelection (com.palantir.atlasdb.keyvalue.api.BatchColumnRangeSelection)5 LocalRowColumnRangeIterator (com.palantir.atlasdb.keyvalue.impl.LocalRowColumnRangeIterator)5