public abstract class BufferingTable extends AbstractTable implements co.cask.cdap.api.dataset.metrics.MeteredDataset
TransactionAware implementation of Table which
keeps data in memory buffer until transaction commits.
Subclasses should implement methods which deal with persistent store. This implementation merges data from persistent store and in-memory buffer for read/write operations. NOTE: this implementation does not allow storing null as a value of a column NOTE: data fetched from persisted store should never have nulls in column values: this class doesn't check that and they could be exposed to user as nulls. At the same time since null value is not allowed by this implementation this could lead to un-expected results
This implementation assumes that the table has name and conflicts are resolved on row level.
NOTE: this implementation doesn't cache any data in-memory besides changes. I.e. if you do get of same data that is not in in-memory buffer twice, two times it will try to fetch it from persistent store. Given the snapshot isolation tx model, this can be improved in future implementations.
NOTE: current implementation persists changes only at the end of transaction. Beware of OOME. There should be better implementation for MapReduce case (YMMV though, for counters/aggregations this implementation looks sweet)
NOTE: Using get(byte[], byte[], byte[], int) is generally always not efficient since it always hits the
persisted store even if all needed data is in-memory buffer. See more info at method javadoc
AbstractTable.TableScanner| Modifier and Type | Field and Description |
|---|---|
protected static byte[] |
DELETE_MARKER |
EMPTY_ROW_MAP| Constructor and Description |
|---|
BufferingTable(String name)
Creates an instance of
BufferingTable with row level conflict detection, without readless increments,
and no schema. |
BufferingTable(String name,
co.cask.cdap.api.dataset.table.ConflictDetection level)
Creates an instance of
BufferingTable without readless increments disabled and no schema. |
BufferingTable(String name,
co.cask.cdap.api.dataset.table.ConflictDetection level,
boolean enableReadlessIncrements,
co.cask.cdap.api.data.schema.Schema schema,
String rowFieldName)
Creates an instance of
BufferingTable. |
| Modifier and Type | Method and Description |
|---|---|
void |
close() |
boolean |
commitTx() |
boolean |
compareAndSwap(byte[] row,
byte[] column,
byte[] expectedValue,
byte[] newValue) |
void |
delete(byte[] row)
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.
|
void |
delete(byte[] row,
byte[][] columns) |
co.cask.cdap.api.dataset.table.Row |
get(byte[] row)
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
|
co.cask.cdap.api.dataset.table.Row |
get(byte[] row,
byte[][] columns) |
co.cask.cdap.api.dataset.table.Row |
get(byte[] row,
byte[] startColumn,
byte[] stopColumn,
int limit) |
List<co.cask.cdap.api.dataset.table.Row> |
get(List<co.cask.cdap.api.dataset.table.Get> gets) |
byte[] |
getNameAsTxChangePrefix()
Generates a byte array to be used as the transaction change prefix.
|
protected abstract NavigableMap<byte[],byte[]> |
getPersisted(byte[] row,
byte[][] columns)
Fetches column->value pairs for set of columns from persistent store.
|
protected abstract NavigableMap<byte[],byte[]> |
getPersisted(byte[] row,
byte[] startColumn,
byte[] stopColumn,
int limit)
Fetches column->value pairs for range of columns from persistent store.
|
protected List<Map<byte[],byte[]>> |
getPersisted(List<co.cask.cdap.api.dataset.table.Get> gets)
Fetches a list of rows from persistent store.
|
protected static <T> NavigableMap<byte[],T> |
getRange(NavigableMap<byte[],T> rowMap,
byte[] startColumn,
byte[] stopColumn,
int limit) |
List<co.cask.cdap.api.data.batch.Split> |
getSplits(int numSplits,
byte[] start,
byte[] stop)
Fallback implementation of getSplits,
SplitsUtil.primitiveGetSplits(int, byte[], byte[]). |
String |
getTableName() |
String |
getTransactionAwareName() |
Collection<byte[]> |
getTxChanges() |
protected static <T> NavigableMap<byte[],T> |
head(NavigableMap<byte[],T> map,
int count) |
void |
increment(byte[] row,
byte[][] columns,
long[] amounts) |
co.cask.cdap.api.dataset.table.Row |
incrementAndGet(byte[] row,
byte[][] columns,
long[] amounts) |
protected abstract void |
persist(NavigableMap<byte[],NavigableMap<byte[],Update>> buff)
Persists in-memory buffer.
|
void |
postTxCommit() |
void |
put(byte[] row,
byte[][] columns,
byte[][] values)
NOTE: if value is null corresponded column is deleted.
|
boolean |
rollbackTx() |
co.cask.cdap.api.dataset.table.Scanner |
scan(byte[] startRow,
byte[] stopRow) |
co.cask.cdap.api.dataset.table.Scanner |
scan(co.cask.cdap.api.dataset.table.Scan scan) |
protected abstract co.cask.cdap.api.dataset.table.Scanner |
scanPersisted(co.cask.cdap.api.dataset.table.Scan scan)
Scans range of rows from persistent store for a given
Scan. |
void |
setMetricsCollector(MetricsCollector metricsCollector) |
void |
startTx(co.cask.tephra.Transaction tx) |
protected abstract void |
undo(NavigableMap<byte[],NavigableMap<byte[],Update>> persisted)
Undos previously persisted changes.
|
protected static byte[] |
unwrapDeleteIfNeeded(byte[] value) |
protected static NavigableMap<byte[],byte[]> |
unwrapDeletes(NavigableMap<byte[],byte[]> rowMap) |
protected static NavigableMap<byte[],NavigableMap<byte[],byte[]>> |
unwrapDeletesForRows(NavigableMap<byte[],NavigableMap<byte[],byte[]>> rows) |
void |
updateTx(co.cask.tephra.Transaction transaction) |
protected static byte[] |
wrapDeleteIfNeeded(byte[] value) |
createSplitReader, createSplitRecordScanner, delete, delete, get, get, getRecordType, getSplits, increment, increment, incrementAndGet, incrementAndGet, put, put, write, writepublic BufferingTable(String name)
BufferingTable with row level conflict detection, without readless increments,
and no schema.name - the name of the tablepublic BufferingTable(String name, co.cask.cdap.api.dataset.table.ConflictDetection level)
BufferingTable without readless increments disabled and no schema.name - the name of the tablelevel - the conflict detection levelpublic BufferingTable(String name, co.cask.cdap.api.dataset.table.ConflictDetection level, boolean enableReadlessIncrements, @Nullable co.cask.cdap.api.data.schema.Schema schema, @Nullable String rowFieldName)
BufferingTable.name - the name of the tablelevel - the conflict detection levelenableReadlessIncrements - whether or not readless increments are enabledschema - the schema of the table, or null if there is no schemarowFieldName - the name of the schema field that the row key maps to, or null if there is nonepublic String getTableName()
public String getTransactionAwareName()
getTransactionAwareName in interface co.cask.tephra.TransactionAwarepublic byte[] getNameAsTxChangePrefix()
protected abstract void persist(NavigableMap<byte[],NavigableMap<byte[],Update>> buff) throws Exception
buff - in-memory buffer to persist. Map is described as row->(column->value). Map can contain null values
which means that the corresponded column was deletedExceptionprotected abstract void undo(NavigableMap<byte[],NavigableMap<byte[],Update>> persisted) throws Exception
persisted - previously persisted changes. Map is described as row->(column->value). Map can contain null
values which means that the corresponded column was deletedExceptionprotected abstract NavigableMap<byte[],byte[]> getPersisted(byte[] row, @Nullable byte[][] columns) throws Exception
row - row key defines the row to fetch columns fromcolumns - set of columns to fetch. null means fetch everything; empty array which means fetch nothing.Exceptionprotected abstract NavigableMap<byte[],byte[]> getPersisted(byte[] row, byte[] startColumn, byte[] stopColumn, int limit) throws Exception
row - row key defines the row to fetch columns fromstartColumn - first column in a range, inclusivestopColumn - last column in a range, exclusivelimit - max number of columns to fetchExceptionprotected abstract co.cask.cdap.api.dataset.table.Scanner scanPersisted(co.cask.cdap.api.dataset.table.Scan scan)
throws Exception
Scan.
NOTE: persisted store can also be in-memory, it is called "persisted" to distinguish from in-memory buffer.scan - scan configurationScanner, never nullExceptionprotected List<Map<byte[],byte[]>> getPersisted(List<co.cask.cdap.api.dataset.table.Get> gets) throws Exception
getPersisted(byte[], byte[][]) on each get.
NOTE: persisted store can also be in-memory, it is called "persisted" to distinguish from in-memory buffer.gets - list of gets to performExceptionpublic void setMetricsCollector(MetricsCollector metricsCollector)
setMetricsCollector in interface co.cask.cdap.api.dataset.metrics.MeteredDatasetpublic void close()
throws IOException
close in interface Closeableclose in interface AutoCloseableIOExceptionpublic void startTx(co.cask.tephra.Transaction tx)
startTx in interface co.cask.tephra.TransactionAwarepublic void updateTx(co.cask.tephra.Transaction transaction)
updateTx in interface co.cask.tephra.TransactionAwarepublic Collection<byte[]> getTxChanges()
getTxChanges in interface co.cask.tephra.TransactionAwarepublic boolean commitTx()
throws Exception
commitTx in interface co.cask.tephra.TransactionAwareExceptionpublic void postTxCommit()
postTxCommit in interface co.cask.tephra.TransactionAwarepublic boolean rollbackTx()
throws Exception
rollbackTx in interface co.cask.tephra.TransactionAwareExceptionpublic co.cask.cdap.api.dataset.table.Row get(byte[] row)
get in interface co.cask.cdap.api.dataset.table.Tablepublic co.cask.cdap.api.dataset.table.Row get(byte[] row,
byte[][] columns)
get in interface co.cask.cdap.api.dataset.table.Tablepublic co.cask.cdap.api.dataset.table.Row get(byte[] row,
byte[] startColumn,
byte[] stopColumn,
int limit)
get in interface co.cask.cdap.api.dataset.table.Tablepublic List<co.cask.cdap.api.dataset.table.Row> get(List<co.cask.cdap.api.dataset.table.Get> gets)
get in interface co.cask.cdap.api.dataset.table.Tableget in class AbstractTablepublic void put(byte[] row,
byte[][] columns,
byte[][] values)
Table.put(byte[], byte[][], byte[][]).put in interface co.cask.cdap.api.dataset.table.Tablepublic void delete(byte[] row)
delete in interface co.cask.cdap.api.dataset.table.Tablepublic void delete(byte[] row,
byte[][] columns)
delete in interface co.cask.cdap.api.dataset.table.Tablepublic co.cask.cdap.api.dataset.table.Row incrementAndGet(byte[] row,
byte[][] columns,
long[] amounts)
incrementAndGet in interface co.cask.cdap.api.dataset.table.Tablepublic void increment(byte[] row,
byte[][] columns,
long[] amounts)
increment in interface co.cask.cdap.api.dataset.table.Tablepublic boolean compareAndSwap(byte[] row,
byte[] column,
byte[] expectedValue,
byte[] newValue)
compareAndSwap in interface co.cask.cdap.api.dataset.table.Tablepublic List<co.cask.cdap.api.data.batch.Split> getSplits(int numSplits, byte[] start, byte[] stop)
SplitsUtil.primitiveGetSplits(int, byte[], byte[]).
Ideally should be overridden by subclasses.getSplits in interface co.cask.cdap.api.dataset.table.TablenumSplits - Desired number of splits. If greater than zero, at most this many splits will be returned.
If less or equal to zero, any number of splits can be returned.start - If non-null, the returned splits will only cover keys that are greater or equal.stop - If non-null, the returned splits will only cover keys that are less.Splitpublic co.cask.cdap.api.dataset.table.Scanner scan(byte[] startRow,
byte[] stopRow)
scan in interface co.cask.cdap.api.dataset.table.Tablepublic co.cask.cdap.api.dataset.table.Scanner scan(co.cask.cdap.api.dataset.table.Scan scan)
scan in interface co.cask.cdap.api.dataset.table.Tableprotected static <T> NavigableMap<byte[],T> getRange(NavigableMap<byte[],T> rowMap, byte[] startColumn, byte[] stopColumn, int limit)
protected static <T> NavigableMap<byte[],T> head(NavigableMap<byte[],T> map, int count)
protected static byte[] wrapDeleteIfNeeded(byte[] value)
protected static byte[] unwrapDeleteIfNeeded(byte[] value)
protected static NavigableMap<byte[],NavigableMap<byte[],byte[]>> unwrapDeletesForRows(NavigableMap<byte[],NavigableMap<byte[],byte[]>> rows)
protected static NavigableMap<byte[],byte[]> unwrapDeletes(NavigableMap<byte[],byte[]> rowMap)
Copyright © 2016 Cask Data, Inc. Licensed under the Apache License, Version 2.0.