use of io.cdap.cdap.api.dataset.table.Result in project cdap by caskdata.
the class IndexedTable method incrementAndGet.
/**
* Increments (atomically) the specified row and columns by the specified amounts, and returns the new values.
* Note that performing this operation on an indexed column will generally have a negative impact on performance,
* since up to three writes will need to be performed for every increment (one removing the index for the previous,
* pre-increment value, one adding the index for the incremented value, and one for the increment itself).
*
* @see Table#incrementAndGet(byte[], byte[][], long[])
*/
@ReadWrite
@Override
public Row incrementAndGet(byte[] row, byte[][] columns, long[] amounts) {
if (columns.length != amounts.length) {
throw new IllegalArgumentException("Size of columns and amounts arguments must match");
}
Row existingRow = table.get(row, columns);
byte[][] updatedValues = new byte[columns.length][];
NavigableMap<byte[], byte[]> result = new TreeMap<>(Bytes.BYTES_COMPARATOR);
for (int i = 0; i < columns.length; i++) {
long existingValue = 0L;
byte[] existingBytes = existingRow.get(columns[i]);
if (existingBytes != null) {
if (existingBytes.length != Bytes.SIZEOF_LONG) {
throw new NumberFormatException("Attempted to increment a value that is not convertible to long," + " row: " + Bytes.toStringBinary(row) + " column: " + Bytes.toStringBinary(columns[i]));
}
existingValue = Bytes.toLong(existingBytes);
if (indexedColumns.contains(columns[i])) {
index.delete(createIndexKey(row, columns[i], existingBytes), IDX_COL);
}
}
updatedValues[i] = Bytes.toBytes(existingValue + amounts[i]);
result.put(columns[i], updatedValues[i]);
if (indexedColumns.contains(columns[i])) {
index.put(createIndexKey(row, columns[i], updatedValues[i]), IDX_COL, row);
}
}
table.put(row, columns, updatedValues);
return new Result(row, result);
}
use of io.cdap.cdap.api.dataset.table.Result in project cdap by caskdata.
the class BufferingTable method get.
@ReadOnly
@Override
public Row get(byte[] row, byte[][] columns) {
ensureTransactionIsStarted();
reportRead(1);
try {
return new Result(row, getRowMap(row, columns));
} catch (Exception e) {
LOG.debug("get failed for table: " + getTransactionAwareName() + ", row: " + Bytes.toStringBinary(row), e);
throw new DataSetException("get failed", e);
}
}
use of io.cdap.cdap.api.dataset.table.Result in project cdap by caskdata.
the class BufferingTable method get.
/**
* NOTE: Depending on the use-case, calling this method may be much less
* efficient than calling same method with columns as parameters because it may always require round trip to
* persistent store
*/
@ReadOnly
@Override
public Row get(byte[] row) {
ensureTransactionIsStarted();
reportRead(1);
try {
return new Result(row, getRowMap(row));
} catch (Exception e) {
LOG.debug("get failed for table: " + getTransactionAwareName() + ", row: " + Bytes.toStringBinary(row), e);
throw new DataSetException("get failed", e);
}
}
use of io.cdap.cdap.api.dataset.table.Result in project cdap by cdapio.
the class BufferingTable method get.
@ReadOnly
@Override
public Row get(byte[] row, byte[] startColumn, byte[] stopColumn, int limit) {
ensureTransactionIsStarted();
reportRead(1);
// checking if the row was deleted inside this tx
NavigableMap<byte[], Update> buffCols = buff.get(row);
// potential improvement: do not fetch columns available in in-mem buffer (we know them at this point)
try {
Map<byte[], byte[]> persistedCols = getPersisted(row, startColumn, stopColumn, limit);
// adding server cols, and then overriding with buffered values
NavigableMap<byte[], byte[]> result = Maps.newTreeMap(Bytes.BYTES_COMPARATOR);
if (persistedCols != null) {
result.putAll(persistedCols);
}
if (buffCols != null) {
buffCols = getRange(buffCols, startColumn, stopColumn, limit);
// null valued columns in in-memory buffer are deletes, so we need to delete them from the result list
mergeToPersisted(result, buffCols, null);
}
// applying limit
return new Result(row, head(result, limit));
} catch (Exception e) {
LOG.debug("get failed for table: " + getTransactionAwareName() + ", row: " + Bytes.toStringBinary(row), e);
throw new DataSetException("get failed", e);
}
}
use of io.cdap.cdap.api.dataset.table.Result in project cdap by cdapio.
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