@Override public void startTx(Transaction tx) { if (buff == null) { String msg = "Attempted to use closed dataset " + getTransactionAwareName(); LOG.error(msg); throw new IllegalStateException(msg); } // starting with fresh buffer when tx starts buff.clear(); toUndo = null; this.tx = tx; }
@Override public void startTx(Transaction tx) { if (buff == null) { String msg = "Attempted to use closed dataset " + getTransactionAwareName(); LOG.error(msg); throw new IllegalStateException(msg); } // starting with fresh buffer when tx starts buff.clear(); toUndo = null; this.tx = tx; }
LOG.debug("multi-get failed for table: " + getTransactionAwareName(), e); throw new DataSetException("multi-get failed", e);
/** * NOTE: Depending on the use-case, calling this method may be much less efficient than calling same method * with columns as parameters because it will require a round trip to persistent store. */ @WriteOnly @Override public void delete(byte[] row) { ensureTransactionIsStarted(); // this is going to be expensive, but the only we can do as delete implementation act on per-column level try { Map<byte[], byte[]> rowMap = getRowMap(row); delete(row, rowMap.keySet().toArray(new byte[rowMap.keySet().size()][])); // "0" because we don't know what gets deleted reportWrite(1, 0); } catch (Exception e) { LOG.debug("delete failed for table: " + getTransactionAwareName() + ", row: " + Bytes.toStringBinary(row), e); throw new DataSetException("delete failed", e); } }
LOG.debug("multi-get failed for table: " + getTransactionAwareName(), e); throw new DataSetException("multi-get failed", e);
/** * NOTE: Depending on the use-case, calling this method may be much less efficient than calling same method * with columns as parameters because it will require a round trip to persistent store. */ @WriteOnly @Override public void delete(byte[] row) { ensureTransactionIsStarted(); // this is going to be expensive, but the only we can do as delete implementation act on per-column level try { Map<byte[], byte[]> rowMap = getRowMap(row); delete(row, rowMap.keySet().toArray(new byte[rowMap.keySet().size()][])); // "0" because we don't know what gets deleted reportWrite(1, 0); } catch (Exception e) { LOG.debug("delete failed for table: " + getTransactionAwareName() + ", row: " + Bytes.toStringBinary(row), e); throw new DataSetException("delete failed", e); } }
@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); } }
@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); } }
@ReadOnly @Override public Scanner scan(Scan scan) { ensureTransactionIsStarted(); NavigableMap<byte[], NavigableMap<byte[], Update>> bufferMap = scanBuffer(scan); try { return new BufferingScanner(bufferMap, scanPersisted(scan)); } catch (Exception e) { LOG.debug("scan failed for table: " + getTransactionAwareName() + ", scan: " + scan.toString(), e); throw new DataSetException("scan failed", e); } }
@ReadOnly @Override public Scanner scan(Scan scan) { ensureTransactionIsStarted(); NavigableMap<byte[], NavigableMap<byte[], Update>> bufferMap = scanBuffer(scan); try { return new BufferingScanner(bufferMap, scanPersisted(scan)); } catch (Exception e) { LOG.debug("scan failed for table: " + getTransactionAwareName() + ", scan: " + scan.toString(), e); throw new DataSetException("scan failed", e); } }
/** * 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); } }
/** * 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); } }
@ReadWrite @Override public boolean compareAndSwap(byte[] row, byte[] column, byte[] expectedValue, byte[] newValue) { ensureTransactionIsStarted(); // TODO: add support for empty values; see https://issues.cask.co/browse/TEPHRA-45 for details. if (newValue != null && newValue.length == 0) { warnAboutEmptyValue(column); } // NOTE: there is more efficient way to do it, but for now we want more simple implementation, not over-optimizing byte[][] columns = new byte[][]{column}; try { byte[] currentValue = getRowMap(row, columns).get(column); reportRead(1); if (Arrays.equals(expectedValue, currentValue)) { putInternal(row, columns, new byte[][]{newValue}); reportWrite(1, getSize(row) + getSize(column) + getSize(newValue)); return true; } } catch (Exception e) { LOG.debug("compareAndSwap failed for table: " + getTransactionAwareName() + ", row: " + Bytes.toStringBinary(row), e); throw new DataSetException("compareAndSwap failed", e); } return false; }
@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); // NOTE: since we cannot tell the exact column set, we always have to go to persisted store. // 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); } }
@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); // NOTE: since we cannot tell the exact column set, we always have to go to persisted store. // 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); } }
@ReadWrite @Override public boolean compareAndSwap(byte[] row, byte[] column, byte[] expectedValue, byte[] newValue) { ensureTransactionIsStarted(); // TODO: add support for empty values; see https://issues.cask.co/browse/TEPHRA-45 for details. if (newValue != null && newValue.length == 0) { warnAboutEmptyValue(column); } // NOTE: there is more efficient way to do it, but for now we want more simple implementation, not over-optimizing byte[][] columns = new byte[][]{column}; try { byte[] currentValue = getRowMap(row, columns).get(column); reportRead(1); if (Arrays.equals(expectedValue, currentValue)) { putInternal(row, columns, new byte[][]{newValue}); reportWrite(1, getSize(row) + getSize(column) + getSize(newValue)); return true; } } catch (Exception e) { LOG.debug("compareAndSwap failed for table: " + getTransactionAwareName() + ", row: " + Bytes.toStringBinary(row), e); throw new DataSetException("compareAndSwap failed", e); } return false; }
reportRead(1); } catch (Exception e) { LOG.debug("incrementAndGet failed for table: " + getTransactionAwareName() + ", row: " + Bytes.toStringBinary(row), e); throw new DataSetException("incrementAndGet failed", e);
reportRead(1); } catch (Exception e) { LOG.debug("incrementAndGet failed for table: " + getTransactionAwareName() + ", row: " + Bytes.toStringBinary(row), e); throw new DataSetException("incrementAndGet failed", e);