use of co.cask.cdap.api.annotation.ReadOnly in project cdap by caskdata.
the class HBaseTable method getInternal.
// columns being null means to get all rows; empty columns means get no rows.
@ReadOnly
private NavigableMap<byte[], byte[]> getInternal(byte[] row, @Nullable byte[][] columns) throws IOException {
if (columns != null && columns.length == 0) {
return EMPTY_ROW_MAP;
}
Get get = createGet(row, columns);
Result result = hTable.get(get);
// no tx logic needed
if (tx == null) {
return result.isEmpty() ? EMPTY_ROW_MAP : result.getFamilyMap(columnFamily);
}
return getRowMap(result, columnFamily);
}
use of co.cask.cdap.api.annotation.ReadOnly in project cdap by caskdata.
the class IndexedTable method readByIndex.
/**
* Reads table rows by the given secondary index key. If no rows are indexed by the given key, then a
* {@link co.cask.cdap.api.dataset.table.Scanner} with no results will be returned.
*
* @return a Scanner returning rows from the data table, whose stored value for the given column matches the
* given value.
* @throws java.lang.IllegalArgumentException if the given column is not configured for indexing.
*/
@ReadOnly
public Scanner readByIndex(byte[] column, byte[] value) {
assertIndexedColumn(column);
byte[] rowKeyPrefix = Bytes.concat(column, KEY_DELIMITER, value, KEY_DELIMITER);
byte[] stopRow = Bytes.stopKeyForPrefix(rowKeyPrefix);
Scanner indexScan = index.scan(rowKeyPrefix, stopRow);
return new IndexScanner(indexScan, column, value);
}
use of co.cask.cdap.api.annotation.ReadOnly in project cdap by caskdata.
the class IndexedTable method scanByIndex.
/**
* Reads table rows within the given secondary index key range. If no rows are indexed, falling within the given
* range, then a {@link co.cask.cdap.api.dataset.table.Scanner} with no results will be returned.
*
* @param column the column to use for the index lookup
* @param startValue the inclusive start of the range for which rows must fall within to be returned in the scan.
* {@code null} means start from first row of the table
* @param endValue the exclusive end of the range for which rows must fall within to be returned in the scan
* {@code null} means end with the last row of the table
* @return a Scanner returning rows from the data table, whose stored value for the given column is within the the
* given range.
* @throws java.lang.IllegalArgumentException if the given column is not configured for indexing.
*/
@ReadOnly
public Scanner scanByIndex(byte[] column, @Nullable byte[] startValue, @Nullable byte[] endValue) {
assertIndexedColumn(column);
// KEY_DELIMITER is not used at the end of the rowKeys, because they are used for a range scan,
// instead of a fixed-match lookup
byte[] startRow = startValue == null ? Bytes.concat(column, KEY_DELIMITER) : Bytes.concat(column, KEY_DELIMITER, startValue);
byte[] stopRow = endValue == null ? Bytes.stopKeyForPrefix(Bytes.concat(column, KEY_DELIMITER)) : Bytes.concat(column, KEY_DELIMITER, endValue);
Scanner indexScan = index.scan(startRow, stopRow);
return new IndexRangeScanner(indexScan, column, startValue, endValue);
}
use of co.cask.cdap.api.annotation.ReadOnly in project cdap by caskdata.
the class IndexedObjectStore method readAllByIndex.
/**
* Read all the objects from the objectStore for a given index. Returns all the objects that match the secondaryKey.
* Returns an empty list if no values are found. Never returns null.
*
* @param secondaryKey for the lookup.
* @return List of Objects matching the secondaryKey.
*/
@ReadOnly
public List<T> readAllByIndex(byte[] secondaryKey) {
List<T> resultList = new ArrayList<>();
//Lookup the secondaryKey and get all the keys in primary
//Each row with secondaryKey as rowKey contains column named as the primary key
// of every object that can be looked up using the secondaryKey
Row row = index.get(secondaryKey);
// if the index has no match, return nothing
if (!row.isEmpty()) {
for (byte[] column : row.getColumns().keySet()) {
T obj = objectStore.read(column);
resultList.add(obj);
}
}
return Collections.unmodifiableList(resultList);
}
use of co.cask.cdap.api.annotation.ReadOnly in project cdap by caskdata.
the class BufferingTable method get.
@ReadOnly
@Override
public List<Row> get(List<Get> gets) {
ensureTransactionIsStarted();
try {
// get persisted, then overwrite with whats buffered
List<Map<byte[], byte[]>> persistedRows = getPersisted(gets);
// gets and rows lists are always of the same size
Preconditions.checkArgument(gets.size() == persistedRows.size(), "Invalid number of rows fetched when performing multi-get. There must be one row for each get.");
List<Row> result = Lists.newArrayListWithCapacity(persistedRows.size());
Iterator<Map<byte[], byte[]>> persistedRowsIter = persistedRows.iterator();
Iterator<Get> getIter = gets.iterator();
while (persistedRowsIter.hasNext() && getIter.hasNext()) {
Get get = getIter.next();
Map<byte[], byte[]> persistedRow = persistedRowsIter.next();
// navigable copy of the persisted data. Implementation may return immutable or unmodifiable maps,
// so we make a copy here.
NavigableMap<byte[], byte[]> rowColumns = Maps.newTreeMap(Bytes.BYTES_COMPARATOR);
rowColumns.putAll(persistedRow);
byte[] row = get.getRow();
NavigableMap<byte[], Update> buffCols = buff.get(row);
// merge what was in the buffer and what was persisted
if (buffCols != null) {
List<byte[]> getColumns = get.getColumns();
byte[][] columns = getColumns == null ? null : getColumns.toArray(new byte[getColumns.size()][]);
mergeToPersisted(rowColumns, buffCols, columns);
}
result.add(new Result(row, unwrapDeletes(rowColumns)));
}
return result;
} catch (Exception e) {
LOG.debug("multi-get failed for table: " + getTransactionAwareName(), e);
throw new DataSetException("multi-get failed", e);
}
}
Aggregations