{"id":28793036,"url":"https://github.com/cdapio/tephra","last_synced_at":"2025-07-25T02:36:07.934Z","repository":{"id":18684510,"uuid":"21894018","full_name":"cdapio/tephra","owner":"cdapio","description":"Apache Tephra: Transactions for HBase.","archived":false,"fork":false,"pushed_at":"2024-09-13T12:12:49.000Z","size":1294,"stargazers_count":157,"open_issues_count":8,"forks_count":43,"subscribers_count":87,"default_branch":"develop","last_synced_at":"2024-09-14T02:07:22.438Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://tephra.incubator.apache.org","language":"Java","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cdapio.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2014-07-16T09:07:44.000Z","updated_at":"2024-09-13T12:12:51.000Z","dependencies_parsed_at":"2022-09-09T10:00:17.876Z","dependency_job_id":"d17effb4-e75f-45c8-b9e3-13e0c4cf703c","html_url":"https://github.com/cdapio/tephra","commit_stats":null,"previous_names":["caskdata/tephra","continuuity/tephra"],"tags_count":22,"template":false,"template_full_name":null,"purl":"pkg:github/cdapio/tephra","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdapio%2Ftephra","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdapio%2Ftephra/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdapio%2Ftephra/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdapio%2Ftephra/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cdapio","download_url":"https://codeload.github.com/cdapio/tephra/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdapio%2Ftephra/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260465874,"owners_count":23013443,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-18T01:04:21.786Z","updated_at":"2025-07-25T02:36:07.912Z","avatar_url":"https://github.com/cdapio.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":".. ==================\n.. Cask Tephra\n.. ==================\n\n|(Tephra)|\n\nNote: **Tephra has moved to Apache Incubator**\n----------------------------------------------\nFor latest updates on Apache Tephra go to its new site at `http://tephra.incubator.apache.org \u003chttp://tephra.incubator.apache.org\u003e`__.\n\n-----\n\n**Transactions for Apache HBase** |(TM)|:\nCask Tephra provides globally consistent transactions on top of Apache HBase.  While HBase\nprovides strong consistency with row- or region-level ACID operations, it sacrifices\ncross-region and cross-table consistency in favor of scalability.  This trade-off requires\napplication developers to handle the complexity of ensuring consistency when their modifications\nspan region boundaries.  By providing support for global transactions that span regions, tables, or\nmultiple RPCs, Tephra simplifies application development on top of HBase, without a significant\nimpact on performance or scalability for many workloads.\n\nHow It Works\n------------\n\nTephra leverages HBase's native data versioning to provide multi-versioned concurrency\ncontrol (MVCC) for transactional reads and writes.  With MVCC capability, each transaction\nsees its own consistent \"snapshot\" of data, providing `snapshot isolation \n\u003chttp://en.wikipedia.org/wiki/Snapshot_isolation\u003e`__ of concurrent transactions.\n\nTephra consists of three main components:\n\n- **Transaction Server** - maintains global view of transaction state, assigns new transaction IDs\n  and performs conflict detection;\n- **Transaction Client** - coordinates start, commit, and rollback of transactions; and\n- **TransactionProcessor Coprocessor** - applies filtering to the data read (based on a \n  given transaction's state) and cleans up any data from old (no longer visible) transactions.\n\nTransaction Server\n..................\n\nA central transaction manager generates a globally unique, time-based transaction ID for each\ntransaction that is started, and maintains the state of all in-progress and recently committed\ntransactions for conflict detection.  While multiple transaction server instances can be run\nconcurrently for automatic failover, only one server instance is actively serving requests at a\ntime.  This is coordinated by performing leader election amongst the running instances through\nZooKeeper.  The active transaction server instance will also register itself using a service\ndiscovery interface in ZooKeeper, allowing clients to discover the currently active server\ninstance without additional configuration.\n\nTransaction Client\n..................\n\nA client makes a call to the active transaction server in order to start a new transaction.  This\nreturns a new transaction instance to the client, with a unique transaction ID (used to identify\nwrites for the transaction), as well as a list of transaction IDs to exclude for reads (from\nin-progress or invalidated transactions).  When performing writes, the client overrides the\ntimestamp for all modified HBase cells with the transaction ID.  When reading data from HBase, the\nclient skips cells associated with any of the excluded transaction IDs.  The read exclusions are\napplied through a server-side filter injected by the ``TransactionProcessor`` coprocessor.\n\nTransactionProcessor Coprocessor\n..................................\n\nThe ``TransactionProcessor`` coprocessor is loaded on all HBase tables where transactional reads\nand writes are performed.  When clients read data, it coordinates the server-side filtering\nperformed based on the client transaction's snapshot. Data cells from any transactions that are\ncurrently in-progress or those that have failed and could not be rolled back (\"invalid\" \ntransactions) will be skipped on these reads.  In addition, the ``TransactionProcessor`` cleans \nup any data versions that are no longer visible to any running transactions, either because the \ntransaction that the cell is associated with failed or a write from a newer transaction was \nsuccessfully committed to the same column.\n\nMore details on how Tephra transactions work and the interactions between these components can be\nfound in our `Transactions over HBase\n\u003chttp://www.slideshare.net/alexbaranau/transactions-over-hbase\u003e`_ presentation.\n\n\nIs It Building?\n----------------\nStatus of continuous integration build at `Travis CI \u003chttps://travis-ci.org/caskdata/tephra\u003e`__: |(BuildStatus)|\n\nRequirements\n------------\n\nJava Runtime\n............\n\nThe latest `JDK or JRE version 1.7.xx or 1.8.xx \u003chttp://www.java.com/en/download/manual.jsp\u003e`__\nfor Linux, Windows, or Mac OS X must be installed in your environment; we recommend the Oracle JDK.\n\nTo check the Java version installed, run the command::\n\n  $ java -version\n\nTephra is tested with the Oracle JDKs; it may work with other JDKs such as\n`Open JDK \u003chttp://openjdk.java.net\u003e`__, but it has not been tested with them.\n\nOnce you have installed the JDK, you'll need to set the JAVA_HOME environment variable.\n\n\nHadoop/HBase Environment\n........................\n\nTephra requires a working HBase and HDFS environment in order to operate. Tephra supports these\ncomponent versions:\n\n+---------------+-------------------+---------------------------------------------------------+\n| Component     | Source            | Supported Versions                                      |\n+===============+===================+=========================================================+\n| **HDFS**      | Apache Hadoop     | 2.0.2-alpha through 2.6.0                               |\n+               +-------------------+---------------------------------------------------------+\n|               | CDH or HDP        | (CDH) 5.0.0 through 5.7.0 or (HDP) 2.0, 2.1, 2.2 or 2.3 |\n+               +-------------------+---------------------------------------------------------+\n|               | MapR              | 4.1 (with MapR-FS)                                      |\n+---------------+-------------------+---------------------------------------------------------+\n| **HBase**     | Apache            | 0.96.x, 0.98.x, 1.0.x, and 1.1.x                        |\n+               +-------------------+---------------------------------------------------------+\n|               | CDH or HDP        | (CDH) 5.0.0 through 5.7.0 or (HDP) 2.0, 2.1, 2.2 or 2.3 |\n+               +-------------------+---------------------------------------------------------+\n|               | MapR              | 4.1 (with Apache HBase)                                 |\n+---------------+-------------------+---------------------------------------------------------+\n| **Zookeeper** | Apache            | Version 3.4.3 through 3.4.5                             |\n+               +-------------------+---------------------------------------------------------+\n|               | CDH or HDP        | (CDH) 5.0.0 through 5.7.0 or (HDP) 2.0, 2.1, 2.2 or 2.3 |\n+               +-------------------+---------------------------------------------------------+\n|               | MapR              | 4.1                                                     |\n+---------------+-------------------+---------------------------------------------------------+\n\n**Note:** Components versions shown in this table are those that we have tested and are\nconfident of their suitability and compatibility. Later versions of components may work,\nbut have not necessarily been either tested or confirmed compatible.\n\n\nGetting Started\n---------------\n\nYou can get started with Tephra by building directly from the latest source code::\n\n  git clone https://github.com/caskdata/tephra.git\n  cd tephra\n  mvn clean package\n\nAfter the build completes, you will have a full binary distribution of Tephra under the\n``tephra-distribution/target/`` directory.  Take the ``tephra-\u003cversion\u003e.tar.gz`` file and install\nit on your systems.\n\nFor any client applications, add the following dependencies to any Apache Maven POM files (or your\nbuild system's equivalent configuration), in order to make use of Tephra classes::\n\n  \u003cdependency\u003e\n    \u003cgroupId\u003eco.cask.tephra\u003c/groupId\u003e\n    \u003cartifactId\u003etephra-api\u003c/artifactId\u003e\n    \u003cversion\u003e0.7.1\u003c/version\u003e\n  \u003c/dependency\u003e\n  \u003cdependency\u003e\n    \u003cgroupId\u003eco.cask.tephra\u003c/groupId\u003e\n    \u003cartifactId\u003etephra-core\u003c/artifactId\u003e\n    \u003cversion\u003e0.7.1\u003c/version\u003e\n  \u003c/dependency\u003e\n\nSince the HBase APIs have changed between versions, you will need to select the\nappropriate HBase compatibility library.\n\nFor HBase 0.96.x::\n\n  \u003cdependency\u003e\n    \u003cgroupId\u003eco.cask.tephra\u003c/groupId\u003e\n    \u003cartifactId\u003etephra-hbase-compat-0.96\u003c/artifactId\u003e\n    \u003cversion\u003e0.7.1\u003c/version\u003e\n  \u003c/dependency\u003e\n\nFor HBase 0.98.x::\n\n  \u003cdependency\u003e\n    \u003cgroupId\u003eco.cask.tephra\u003c/groupId\u003e\n    \u003cartifactId\u003etephra-hbase-compat-0.98\u003c/artifactId\u003e\n    \u003cversion\u003e0.7.1\u003c/version\u003e\n  \u003c/dependency\u003e\n\nFor HBase 1.0.x::\n\n  \u003cdependency\u003e\n    \u003cgroupId\u003eco.cask.tephra\u003c/groupId\u003e\n    \u003cartifactId\u003etephra-hbase-compat-1.0\u003c/artifactId\u003e\n    \u003cversion\u003e0.7.1\u003c/version\u003e\n  \u003c/dependency\u003e\n\nIf you are running the CDH 5.4, 5.5, or 5.6 version of HBase 1.0.x (this version contains API incompatibilities\nwith Apache HBase 1.0.x)::\n\n  \u003cdependency\u003e\n    \u003cgroupId\u003eco.cask.tephra\u003c/groupId\u003e\n    \u003cartifactId\u003etephra-hbase-compat-1.0-cdh\u003c/artifactId\u003e\n    \u003cversion\u003e0.7.1\u003c/version\u003e\n  \u003c/dependency\u003e\n\nFor HBase 1.1.x or CDH 5.7 version of HBase 1.2.x::\n\n  \u003cdependency\u003e\n    \u003cgroupId\u003eco.cask.tephra\u003c/groupId\u003e\n    \u003cartifactId\u003etephra-hbase-compat-1.1\u003c/artifactId\u003e\n    \u003cversion\u003e0.7.1\u003c/version\u003e\n  \u003c/dependency\u003e\n\nDeployment and Configuration\n----------------------------\n\nTephra makes use of a central transaction server to assign unique transaction IDs for data\nmodifications and to perform conflict detection.  Only a single transaction server can actively\nhandle client requests at a time, however, additional transaction server instances can be run\nsimultaneously, providing automatic failover if the active server becomes unreachable.\n\nTransaction Server Configuration\n................................\n\nThe Tephra transaction server can be deployed on the same cluster nodes running the HBase HMaster\nprocess. The transaction server requires that the HBase libraries be available on the server's \nJava ``CLASSPATH``.  \n\nThe transaction server supports the following configuration properties.  All configuration\nproperties can be added to the ``hbase-site.xml`` file on the server's ``CLASSPATH``:\n\n+-------------------------------+------------+-----------------------------------------------------------------+\n| Name                          | Default    | Description                                                     |\n+===============================+============+=================================================================+\n| ``data.tx.bind.port``         | 15165      | Port to bind to                                                 |\n+-------------------------------+------------+-----------------------------------------------------------------+\n| ``data.tx.bind.address``      | 0.0.0.0    | Server address to listen on                                     |\n+-------------------------------+------------+-----------------------------------------------------------------+\n| ``data.tx.server.io.threads`` | 2          | Number of threads for socket IO                                 |\n+-------------------------------+------------+-----------------------------------------------------------------+\n| ``data.tx.server.threads``    | 20         | Number of handler threads                                       |\n+-------------------------------+------------+-----------------------------------------------------------------+\n| ``data.tx.timeout``           | 30         | Timeout for a transaction to complete (seconds)                 |\n+-------------------------------+------------+-----------------------------------------------------------------+\n| ``data.tx.long.timeout``      | 86400      | Timeout for a long running transaction to complete (seconds)    |\n+-------------------------------+------------+-----------------------------------------------------------------+\n| ``data.tx.cleanup.interval``  | 10         | Frequency to check for timed out transactions (seconds)         |\n+-------------------------------+------------+-----------------------------------------------------------------+\n| ``data.tx.snapshot.dir``      |            | HDFS directory used to store snapshots of tx state              |\n+-------------------------------+------------+-----------------------------------------------------------------+\n| ``data.tx.snapshot.interval`` | 300        | Frequency to write new snapshots                                |\n+-------------------------------+------------+-----------------------------------------------------------------+\n| ``data.tx.snapshot.retain``   | 10         | Number of old transaction snapshots to retain                   |\n+-------------------------------+------------+-----------------------------------------------------------------+\n| ``data.tx.metrics.period``    | 60         | Frequency for metrics reporting (seconds)                       |\n+-------------------------------+------------+-----------------------------------------------------------------+\n\nTo run the Transaction server, execute the following command in your Tephra installation::\n\n  ./bin/tephra start\n\nAny environment-specific customizations can be made by editing the ``bin/tephra-env.sh`` script.\n\n\nClient Configuration\n....................\n\nSince Tephra clients will be communicating with HBase, the HBase client libraries and the HBase cluster\nconfiguration must be available on the client's Java ``CLASSPATH``.\n\nClient API usage is described in the `Client APIs`_ section.\n\nThe transaction service client supports the following configuration properties.  All configuration\nproperties can be added to the ``hbase-site.xml`` file on the client's ``CLASSPATH``:\n\n+------------------------------------------+-----------+-----------------------------------------------+\n| Name                                     | Default   | Description                                   |\n+==========================================+===========+===============================================+\n| ``data.tx.client.timeout``               | 30000     | Client socket timeout (milliseconds)          |\n+------------------------------------------+-----------+-----------------------------------------------+\n| ``data.tx.client.provider``              | pool      | Client provider strategy:                     |\n|                                          |           |                                               |\n|                                          |           | - \"pool\" uses a pool of clients               |\n|                                          |           | - \"thread-local\" a client per thread          |\n|                                          |           |                                               |\n|                                          |           | Note that \"thread-local\" provider can have a  |\n|                                          |           | resource leak if threads are recycled         |\n+------------------------------------------+-----------+-----------------------------------------------+\n| ``data.tx.client.count``                 | 50        | Max number of clients for \"pool\" provider     |\n+------------------------------------------+-----------+-----------------------------------------------+\n| ``data.tx.client.obtain.timeout``        | 3000      | Timeout (milliseconds) to wait when obtaining |\n|                                          |           | clients from the \"pool\" provider              |\n+------------------------------------------+-----------+-----------------------------------------------+\n| ``data.tx.client.retry.strategy``        | backoff   | Client retry strategy: \"backoff\" for back off |\n|                                          |           | between attempts; \"n-times\" for fixed number  |\n|                                          |           | of tries                                      |\n+------------------------------------------+-----------+-----------------------------------------------+\n| ``data.tx.client.retry.attempts``        | 2         | Number of times to retry (\"n-times\" strategy) |\n+------------------------------------------+-----------+-----------------------------------------------+\n| ``data.tx.client.retry.backoff.initial`` | 100       | Initial sleep time (\"backoff\" strategy)       |\n+------------------------------------------+-----------+-----------------------------------------------+\n| ``data.tx.client.retry.backoff.factor``  | 4         | Multiplication factor for sleep time          |\n+------------------------------------------+-----------+-----------------------------------------------+\n| ``data.tx.client.retry.backoff.limit``   | 30000     | Exit when sleep time reaches this limit       |\n+------------------------------------------+-----------+-----------------------------------------------+\n\n\nHBase Coprocessor Configuration\n...............................\n\nIn addition to the transaction server, Tephra requires an HBase coprocessor to be installed on all\ntables where transactional reads and writes will be performed.  \n\nTo configure the coprocessor on all HBase tables, add the following to ``hbase-site.xml``.\n\nFor HBase 0.96.x::\n\n  \u003cproperty\u003e\n    \u003cname\u003ehbase.coprocessor.region.classes\u003c/name\u003e\n    \u003cvalue\u003eco.cask.tephra.hbase96.coprocessor.TransactionProcessor\u003c/value\u003e\n  \u003c/property\u003e\n\nFor HBase 0.98.x::\n\n  \u003cproperty\u003e\n    \u003cname\u003ehbase.coprocessor.region.classes\u003c/name\u003e\n    \u003cvalue\u003eco.cask.tephra.hbase98.coprocessor.TransactionProcessor\u003c/value\u003e\n  \u003c/property\u003e\n\nFor HBase 1.0.x::\n\n  \u003cproperty\u003e\n    \u003cname\u003ehbase.coprocessor.region.classes\u003c/name\u003e\n    \u003cvalue\u003eco.cask.tephra.hbase10.coprocessor.TransactionProcessor\u003c/value\u003e\n  \u003c/property\u003e\n\nFor the CDH 5.4, 5.5, or 5.6 version of HBase 1.0.x::\n\n  \u003cproperty\u003e\n    \u003cname\u003ehbase.coprocessor.region.classes\u003c/name\u003e\n    \u003cvalue\u003eco.cask.tephra.hbase10cdh.coprocessor.TransactionProcessor\u003c/value\u003e\n  \u003c/property\u003e\n\nFor HBase 1.1.x or CDH 5.7 version of HBase 1.2.x::\n\n  \u003cproperty\u003e\n    \u003cname\u003ehbase.coprocessor.region.classes\u003c/name\u003e\n    \u003cvalue\u003eco.cask.tephra.hbase11.coprocessor.TransactionProcessor\u003c/value\u003e\n  \u003c/property\u003e\n\nYou may configure the ``TransactionProcessor`` to be loaded only on HBase tables that you will\nbe using for transaction reads and writes.  However, you must ensure that the coprocessor is \navailable on all impacted tables in order for Tephra to function correctly.\n\nUsing Existing HBase Tables Transactionally\n...........................................\n\nTephra overrides HBase cell timestamps with transaction IDs, and uses these transaction\nIDs to filter out cells older than the TTL (Time-To-Live). Transaction IDs are at a higher\nscale than cell timestamps. When a regular HBase table that has existing data is\nconverted to a transactional table, existing data may be filtered out during reads. To\nallow reading of existing data from a transactional table, you will need to set the\nproperty ``data.tx.read.pre.existing`` as ``true`` on the table's table descriptor.\n\nNote that even without the property ``data.tx.read.pre.existing`` being set to ``true``,\nany existing data will not be removed during compactions. Existing data simply won't be\nvisible during reads.\n\nMetrics Reporting\n.................\n\nTephra ships with built-in support for reporting metrics via JMX and a log file, using the\n`Dropwizard Metrics \u003chttp://metrics.dropwizard.io\u003e`_ library.\n\nTo enable JMX reporting for metrics, you will need to enable JMX in the Java runtime\narguments. Edit the ``bin/tephra-env.sh`` script and uncomment the following lines, making any\ndesired changes to configuration for port used, SSL, and JMX authentication::\n\n  # export JMX_OPTS=\"-Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.port=13001\"\n  # export OPTS=\"$OPTS $JMX_OPTS\"\n\nTo enable file-based reporting for metrics, edit the ``conf/logback.xml`` file and uncomment the\nfollowing section, replacing the ``FILE-PATH`` placeholder with a valid directory on the local\nfilesystem::\n\n  \u003cappender name=\"METRICS\" class=\"ch.qos.logback.core.rolling.RollingFileAppender\"\u003e\n    \u003cfile\u003e/FILE-PATH/metrics.log\u003c/file\u003e\n    \u003crollingPolicy class=\"ch.qos.logback.core.rolling.TimeBasedRollingPolicy\"\u003e\n      \u003cfileNamePattern\u003emetrics.log.%d{yyyy-MM-dd}\u003c/fileNamePattern\u003e\n      \u003cmaxHistory\u003e30\u003c/maxHistory\u003e\n    \u003c/rollingPolicy\u003e\n    \u003cencoder\u003e\n      \u003cpattern\u003e%d{ISO8601} %msg%n\u003c/pattern\u003e\n    \u003c/encoder\u003e\n  \u003c/appender\u003e\n  \u003clogger name=\"tephra-metrics\" level=\"TRACE\" additivity=\"false\"\u003e\n    \u003cappender-ref ref=\"METRICS\" /\u003e\n  \u003c/logger\u003e\n\nThe frequency of metrics reporting may be configured by setting the ``data.tx.metrics.period``\nconfiguration property to the report frequency in seconds.\n\n\nClient APIs\n-----------\nThe ``TransactionAwareHTable`` class implements HBase's ``HTableInterface``, thus providing the same APIs\nthat a standard HBase ``HTable`` instance provides. Only certain operations are supported\ntransactionally. These are: \n\n.. csv-table::\n  :header: Methods Supported In Transactions\n  :widths: 100\n  :delim: 0x9\n\n    ``exists(Get get)``\n    ``exists(List\u003cGet\u003e gets)``\n    ``get(Get get)``\n    ``get(List\u003cGet\u003e gets)``\n    ``batch(List\u003c? extends Row\u003e actions, Object[] results)``\n    ``batch(List\u003c? extends Row\u003e actions)``\n    ``batchCallback(List\u003c? extends Row\u003e actions, Object[] results, Batch.Callback\u003cR\u003e callback)`` [0.96]\n    ``batchCallback(List\u003c? extends Row\u003e actions, Batch.Callback\u003cR\u003e callback)`` [0.96]\n    ``getScanner(byte[] family)``\n    ``getScanner(byte[] family, byte[] qualifier)``\n    ``put(Put put)``\n    ``put(List\u003cPut\u003e puts)``\n    ``delete(Delete delete)``\n    ``delete(List\u003cDelete\u003e deletes)``\n\nOther operations are not supported transactionally and will throw an ``UnsupportedOperationException`` if invoked.\nTo allow use of these non-transactional operations, call ``setAllowNonTransactional(true)``. This\nallows you to call the following methods non-transactionally:\n\n.. csv-table::\n  :header: Methods Supported Outside of Transactions\n  :widths: 100\n  :delim: 0x9\n\n    ``getRowOrBefore(byte[] row, byte[], family)``\n    ``checkAndPut(byte[] row, byte[] family, byte[] qualifier, byte[] value, Put put)``\n    ``checkAndDelete(byte[] row, byte[] family, byte[] qualifier, byte[] value, Delete delete)``\n    ``mutateRow(RowMutations rm)``\n    ``append(Append append)``\n    ``increment(Increment increment)``\n    ``incrementColumnValue(byte[] row, byte[] family, byte[] qualifier, long amount)``\n    ``incrementColumnValue(byte[] row, byte[] family, byte[] qualifier, long amount, Durability durability)``\n    ``incrementColumnValue(byte[] row, byte[] family, byte[] qualifier, long amount, boolean writeToWAL)``\n\nNote that for ``batch`` operations, only certain supported operations (``get``, ``put``, and ``delete``)\nare applied transactionally.\n\nUsage\n.....\nTo use a ``TransactionalAwareHTable``, you need an instance of ``TransactionContext``.\n``TransactionContext`` provides the basic contract for client use of transactions.  At each point\nin the transaction lifecycle, it provides the necessary interactions with the Tephra Transaction\nServer in order to start, commit, and rollback transactions.  Basic usage of\n``TransactionContext`` is handled using the following pattern:\n\n.. code:: java\n\n  TransactionContext context = new TransactionContext(client, transactionAwareHTable);\n  try {\n    context.start();\n    transactionAwareHTable.put(new Put(Bytes.toBytes(\"row\"));\n    // ...\n    context.finish();\n  } catch (TransactionFailureException e) {\n    context.abort();\n  }\n\n#. First, a new transaction is started using ``TransactionContext.start()``.\n#. Next, any data operations are performed within the context of the transaction.\n#. After data operations are complete, ``TransactionContext.finish()`` is called to commit the\n   transaction.\n#. If an exception occurs, ``TransactionContext.abort()`` can be called to rollback the\n   transaction.\n\n``TransactionAwareHTable`` handles the details of performing data operations transactionally, and\nimplements the necessary hooks in order to commit and rollback the data changes (see\n``TransactionAware``).\n\nExample\n.......\nTo demonstrate how you might use ``TransactionAwareHTable``\\s, below is a basic implementation of a\n``SecondaryIndexTable``. This class encapsulates the usage of a ``TransactionContext`` and provides a simple interface\nto a user:\n\n.. code:: java\n\n  /**\n   * A Transactional SecondaryIndexTable.\n   */\n  public class SecondaryIndexTable {\n    private byte[] secondaryIndex;\n    private TransactionAwareHTable transactionAwareHTable;\n    private TransactionAwareHTable secondaryIndexTable;\n    private TransactionContext transactionContext;\n    private final TableName secondaryIndexTableName;\n    private static final byte[] secondaryIndexFamily = \n      Bytes.toBytes(\"secondaryIndexFamily\");\n    private static final byte[] secondaryIndexQualifier = Bytes.toBytes('r');\n    private static final byte[] DELIMITER  = new byte[] {0};\n\n    public SecondaryIndexTable(TransactionServiceClient transactionServiceClient, \n                               HTable hTable, byte[] secondaryIndex) {\n      secondaryIndexTableName = \n            TableName.valueOf(hTable.getName().getNameAsString() + \".idx\");\n      HTable secondaryIndexHTable = null;\n      HBaseAdmin hBaseAdmin = null;\n      try {\n        hBaseAdmin = new HBaseAdmin(hTable.getConfiguration());\n        if (!hBaseAdmin.tableExists(secondaryIndexTableName)) {\n          hBaseAdmin.createTable(new HTableDescriptor(secondaryIndexTableName));\n        }\n        secondaryIndexHTable = new HTable(hTable.getConfiguration(), \n                                          secondaryIndexTableName);\n      } catch (Exception e) {\n        Throwables.propagate(e);\n      } finally {\n        try {\n          hBaseAdmin.close();\n        } catch (Exception e) {\n          Throwables.propagate(e);\n        }\n      }\n\n      this.secondaryIndex = secondaryIndex;\n      this.transactionAwareHTable = new TransactionAwareHTable(hTable);\n      this.secondaryIndexTable = new TransactionAwareHTable(secondaryIndexHTable);\n      this.transactionContext = new TransactionContext(transactionServiceClient, \n                                                       transactionAwareHTable,\n                                                       secondaryIndexTable);\n    }\n\n    public Result get(Get get) throws IOException {\n      return get(Collections.singletonList(get))[0];\n    }\n\n    public Result[] get(List\u003cGet\u003e gets) throws IOException {\n      try {\n        transactionContext.start();\n        Result[] result = transactionAwareHTable.get(gets);\n        transactionContext.finish();\n        return result;\n      } catch (Exception e) {\n        try {\n          transactionContext.abort();\n        } catch (TransactionFailureException e1) {\n          throw new IOException(\"Could not rollback transaction\", e1);\n        }\n      }\n      return null;\n    }\n\n    public Result[] getByIndex(byte[] value) throws IOException {\n      try {\n        transactionContext.start();\n        Scan scan = new Scan(value, Bytes.add(value, new byte[0]));\n        scan.addColumn(secondaryIndexFamily, secondaryIndexQualifier);\n        ResultScanner indexScanner = secondaryIndexTable.getScanner(scan);\n\n        ArrayList\u003cGet\u003e gets = new ArrayList\u003cGet\u003e();\n        for (Result result : indexScanner) {\n          for (Cell cell : result.listCells()) {\n            gets.add(new Get(cell.getValue()));\n          }\n        }\n        Result[] results = transactionAwareHTable.get(gets);\n        transactionContext.finish();\n        return results;\n      } catch (Exception e) {\n        try {\n          transactionContext.abort();\n        } catch (TransactionFailureException e1) {\n          throw new IOException(\"Could not rollback transaction\", e1);\n        }\n      }\n      return null;\n    }\n\n    public void put(Put put) throws IOException {\n      put(Collections.singletonList(put));\n    }\n\n\n    public void put(List\u003cPut\u003e puts) throws IOException {\n      try {\n        transactionContext.start();\n        ArrayList\u003cPut\u003e secondaryIndexPuts = new ArrayList\u003cPut\u003e();\n        for (Put put : puts) {\n          List\u003cPut\u003e indexPuts = new ArrayList\u003cPut\u003e();\n          Set\u003cMap.Entry\u003cbyte[], List\u003cKeyValue\u003e\u003e\u003e familyMap = put.getFamilyMap().entrySet();\n          for (Map.Entry\u003cbyte [], List\u003cKeyValue\u003e\u003e family : familyMap) {\n            for (KeyValue value : family.getValue()) {\n              if (value.getQualifier().equals(secondaryIndex)) {\n                byte[] secondaryRow = Bytes.add(value.getQualifier(),\n                                                DELIMITER,\n                                                Bytes.add(value.getValue(),\n                                                DELIMITER,\n                                                value.getRow()));\n                Put indexPut = new Put(secondaryRow);\n                indexPut.add(secondaryIndexFamily, secondaryIndexQualifier, put.getRow());\n                indexPuts.add(indexPut);\n              }\n            }\n          }\n          secondaryIndexPuts.addAll(indexPuts);\n        }\n        transactionAwareHTable.put(puts);\n        secondaryIndexTable.put(secondaryIndexPuts);\n        transactionContext.finish();\n      } catch (Exception e) {\n        try {\n          transactionContext.abort();\n        } catch (TransactionFailureException e1) {\n          throw new IOException(\"Could not rollback transaction\", e1);\n        }\n      }\n    }\n  }\n\n\nKnown Issues and Limitations\n----------------------------\n\n- Currently, column family ``Delete`` operations are implemented by writing a cell with an empty\n  qualifier (empty ``byte[]``) and empty value (empty ``byte[]``).  This is done in place of\n  native HBase ``Delete`` operations so the delete marker can be rolled back in the event of\n  a transaction failure -- normal HBase ``Delete`` operations cannot be undone.  However, this\n  means that applications that store data in a column with an empty qualifier will not be able to\n  store empty values, and will not be able to transactionally delete that column.\n- Column ``Delete`` operations are implemented by writing a empty value (empty ``byte[]``) to the\n  column.  This means that applications will not be able to store empty values to columns.\n- Invalid transactions are not automatically cleared from the exclusion list.  When a transaction is\n  invalidated, either from timing out or being invalidated by the client due to a failure to rollback\n  changes, its transaction ID is added to a list of excluded transactions.  Data from invalidated\n  transactions will be dropped by the ``TransactionProcessor`` coprocessor on HBase region flush\n  and compaction operations.  Currently, however, transaction IDs can only be manually removed\n  from the list of excluded transaction IDs, using the ``co.cask.tephra.TransactionAdmin`` tool.\n\n\nHow to Contribute\n-----------------\n\nInterested in helping to improve Tephra? We welcome all contributions, whether in filing detailed\nbug reports, submitting pull requests for code changes and improvements, or by asking questions and\nassisting others on the mailing list.\n\nBug Reports \u0026 Feature Requests\n..............................\n\nBugs and tasks are tracked in a public JIRA `issue tracker \u003chttps://issues.cask.co/browse/TEPHRA\u003e`__.\n\nTephra User Groups and Mailing Lists\n....................................\n\n- Tephra User Group: `tephra-user@googlegroups.com \u003chttps://groups.google.com/d/forum/tephra-user\u003e`__\n\n  The *tephra-user* mailing list is primarily for users using the product to develop\n  applications. You can expect questions from users, release announcements, and any other\n  discussions that we think will be helpful to the users.\n\n- Tephra Developer Group and Development Discussions: `tephra-dev@googlegroups.com \n  \u003chttps://groups.google.com/d/forum/tephra-dev\u003e`__\n\n  The *tephra-dev* mailing list is essentially for developers actively working on the\n  product, and should be used for all our design, architecture and technical discussions\n  moving forward. This mailing list will also receive all JIRA and GitHub notifications.\n\nIRC\n...\n\nHave questions about how Tephra works, or need help using it?  Drop by the ``#tephra``\nchat room on ``irc.freenode.net``.\n\nPull Requests\n.............\n\nWe have a simple pull-based development model with a consensus-building phase, similar to Apache's\nvoting process. If you’d like to help make Tephra better by adding new features, enhancing existing\nfeatures, or fixing bugs, here's how to do it:\n\n#. If you are planning a large change or contribution, discuss your plans on the ``tephra-dev``\n   mailing list first.  This will help us understand your needs and best guide your solution in a\n   way that fits the project.\n#. Fork Tephra into your own GitHub repository.\n#. Create a topic branch with an appropriate name.\n#. Work on the code to your heart's content.\n#. Once you’re satisfied, create a pull request from your GitHub repo (it’s helpful if you fill in\n   all of the description fields).\n#. After we review and accept your request, we’ll commit your code to the caskdata/tephra\n   repository.\n\nThanks for helping to improve Tephra!\n\n\nLicense and Trademarks\n----------------------\n\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use this product except\nin compliance with the License. You may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under the License\nis distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express\nor implied. See the License for the specific language governing permissions and limitations under\nthe License.\n\nCask, Cask Tephra and Tephra are trademarks of Cask Data, Inc. All rights reserved.\n\nApache, Apache HBase, and HBase are trademarks of The Apache Software Foundation. Used with permission. \nNo endorsement by The Apache Software Foundation is implied by the use of these marks.\n\n.. |(TM)| unicode:: U+2122 .. trademark sign\n   :trim:\n\n.. |(Tephra)| image:: docs/_images/tephra_logo_light_bknd_cask.png\n\n.. |(BuildStatus)| image:: https://travis-ci.org/caskdata/tephra.svg?branch=develop\n   :target: https://travis-ci.org/caskdata/tephra\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcdapio%2Ftephra","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcdapio%2Ftephra","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcdapio%2Ftephra/lists"}