├── .github └── workflows │ ├── build-report.yml │ └── build.yml ├── .gitignore ├── .travis.yml ├── KEYS ├── LICENSE ├── README.rst ├── RELEASING.rst ├── bin ├── tephra └── tephra-env.sh ├── checkstyle.xml ├── conf └── logback.xml ├── docs └── _images │ ├── tephra_logo_light_background.png │ ├── tephra_logo_light_bkgnd_small.png │ └── tephra_logo_light_bknd_cask.png ├── pom.xml ├── src └── assemble │ └── bin.xml ├── suppressions.xml ├── tephra-api ├── pom.xml └── src │ └── main │ └── java │ └── co │ └── cask │ └── tephra │ ├── Transaction.java │ ├── TransactionAware.java │ ├── TransactionAwares.java │ ├── TransactionConflictException.java │ ├── TransactionFailureException.java │ ├── TransactionNotInProgressException.java │ └── TransactionType.java ├── tephra-core ├── pom.xml └── src │ ├── main │ ├── java │ │ ├── co │ │ │ └── cask │ │ │ │ └── tephra │ │ │ │ ├── AbstractTransactionAwareTable.java │ │ │ │ ├── AbstractTransactionExecutor.java │ │ │ │ ├── ChangeId.java │ │ │ │ ├── DefaultTransactionExecutor.java │ │ │ │ ├── InvalidTruncateTimeException.java │ │ │ │ ├── NoRetryStrategy.java │ │ │ │ ├── RetryOnConflictStrategy.java │ │ │ │ ├── RetryStrategies.java │ │ │ │ ├── RetryStrategy.java │ │ │ │ ├── TransactionAdmin.java │ │ │ │ ├── TransactionCodec.java │ │ │ │ ├── TransactionContext.java │ │ │ │ ├── TransactionCouldNotTakeSnapshotException.java │ │ │ │ ├── TransactionExecutor.java │ │ │ │ ├── TransactionExecutorFactory.java │ │ │ │ ├── TransactionManager.java │ │ │ │ ├── TransactionServiceMain.java │ │ │ │ ├── TransactionSystemClient.java │ │ │ │ ├── TxConstants.java │ │ │ │ ├── coprocessor │ │ │ │ ├── TransactionStateCache.java │ │ │ │ ├── TransactionStateCacheSupplier.java │ │ │ │ └── package-info.java │ │ │ │ ├── distributed │ │ │ │ ├── AbstractClientProvider.java │ │ │ │ ├── CloseableThriftClient.java │ │ │ │ ├── ElasticPool.java │ │ │ │ ├── PooledClientProvider.java │ │ │ │ ├── RetryNTimes.java │ │ │ │ ├── RetryStrategy.java │ │ │ │ ├── RetryStrategyProvider.java │ │ │ │ ├── RetryWithBackoff.java │ │ │ │ ├── SingleUseClientProvider.java │ │ │ │ ├── ThreadLocalClientProvider.java │ │ │ │ ├── ThriftClientProvider.java │ │ │ │ ├── TransactionConverterUtils.java │ │ │ │ ├── TransactionService.java │ │ │ │ ├── TransactionServiceClient.java │ │ │ │ ├── TransactionServiceThriftClient.java │ │ │ │ ├── TransactionServiceThriftHandler.java │ │ │ │ ├── package-info.java │ │ │ │ └── thrift │ │ │ │ │ ├── TBoolean.java │ │ │ │ │ ├── TInvalidTruncateTimeException.java │ │ │ │ │ ├── TTransaction.java │ │ │ │ │ ├── TTransactionCouldNotTakeSnapshotException.java │ │ │ │ │ ├── TTransactionNotInProgressException.java │ │ │ │ │ ├── TTransactionServer.java │ │ │ │ │ ├── TTransactionType.java │ │ │ │ │ └── TVisibilityLevel.java │ │ │ │ ├── inmemory │ │ │ │ ├── DetachedTxSystemClient.java │ │ │ │ ├── InMemoryTransactionService.java │ │ │ │ ├── InMemoryTxSystemClient.java │ │ │ │ ├── MinimalTxSystemClient.java │ │ │ │ └── package-info.java │ │ │ │ ├── metrics │ │ │ │ ├── DefaultMetricsCollector.java │ │ │ │ ├── MetricsCollector.java │ │ │ │ └── TxMetricsCollector.java │ │ │ │ ├── package-info.java │ │ │ │ ├── persist │ │ │ │ ├── AbstractTransactionLog.java │ │ │ │ ├── AbstractTransactionStateStorage.java │ │ │ │ ├── CommitMarkerCodec.java │ │ │ │ ├── HDFSTransactionLog.java │ │ │ │ ├── HDFSTransactionLogReaderSupplier.java │ │ │ │ ├── HDFSTransactionLogReaderV1.java │ │ │ │ ├── HDFSTransactionLogReaderV2.java │ │ │ │ ├── HDFSTransactionStateStorage.java │ │ │ │ ├── HDFSUtil.java │ │ │ │ ├── LocalFileTransactionLog.java │ │ │ │ ├── LocalFileTransactionStateStorage.java │ │ │ │ ├── NoOpTransactionStateStorage.java │ │ │ │ ├── TransactionEdit.java │ │ │ │ ├── TransactionEditCodecs.java │ │ │ │ ├── TransactionLog.java │ │ │ │ ├── TransactionLogReader.java │ │ │ │ ├── TransactionLogWriter.java │ │ │ │ ├── TransactionSnapshot.java │ │ │ │ ├── TransactionStateStorage.java │ │ │ │ ├── TransactionVisibilityState.java │ │ │ │ └── package-info.java │ │ │ │ ├── rpc │ │ │ │ ├── RPCServiceHandler.java │ │ │ │ ├── ThriftRPCServer.java │ │ │ │ └── package-info.java │ │ │ │ ├── runtime │ │ │ │ ├── ConfigModule.java │ │ │ │ ├── DiscoveryModules.java │ │ │ │ ├── TransactionClientModule.java │ │ │ │ ├── TransactionDistributedModule.java │ │ │ │ ├── TransactionInMemoryModule.java │ │ │ │ ├── TransactionLocalModule.java │ │ │ │ ├── TransactionModules.java │ │ │ │ ├── TransactionStateStorageProvider.java │ │ │ │ └── ZKModule.java │ │ │ │ ├── snapshot │ │ │ │ ├── BinaryDecoder.java │ │ │ │ ├── BinaryEncoder.java │ │ │ │ ├── DefaultSnapshotCodec.java │ │ │ │ ├── SnapshotCodec.java │ │ │ │ ├── SnapshotCodecProvider.java │ │ │ │ ├── SnapshotCodecV2.java │ │ │ │ ├── SnapshotCodecV3.java │ │ │ │ ├── SnapshotCodecV4.java │ │ │ │ └── package-info.java │ │ │ │ ├── util │ │ │ │ ├── ConfigurationFactory.java │ │ │ │ ├── ConfigurationProvider.java │ │ │ │ ├── HBaseVersion.java │ │ │ │ ├── HBaseVersionSpecificFactory.java │ │ │ │ └── TxUtils.java │ │ │ │ ├── visibility │ │ │ │ ├── DefaultFenceWait.java │ │ │ │ ├── FenceWait.java │ │ │ │ ├── ReadFence.java │ │ │ │ ├── VisibilityFence.java │ │ │ │ └── WriteFence.java │ │ │ │ └── zookeeper │ │ │ │ ├── BasicACLData.java │ │ │ │ ├── BasicNodeChildren.java │ │ │ │ ├── BasicNodeData.java │ │ │ │ └── TephraZKClientService.java │ │ └── org │ │ │ └── apache │ │ │ └── thrift │ │ │ └── server │ │ │ └── TThreadedSelectorServerWithFix.java │ └── thrift │ │ ├── README │ │ └── transaction.thrift │ └── test │ └── java │ └── co │ └── cask │ └── tephra │ ├── ThriftTransactionSystemTest.java │ ├── TransactionAdminTest.java │ ├── TransactionContextTest.java │ ├── TransactionExecutorTest.java │ ├── TransactionManagerTest.java │ ├── TransactionServiceMainTest.java │ ├── TransactionSystemTest.java │ ├── TransactionTest.java │ ├── distributed │ ├── ElasticPoolTest.java │ ├── PooledClientProviderTest.java │ └── ThriftTransactionServerTest.java │ ├── hbase │ └── AbstractTransactionVisibilityFilterTest.java │ ├── persist │ ├── AbstractTransactionStateStorageTest.java │ ├── CommitMarkerCodecTest.java │ ├── HDFSTransactionLogTest.java │ ├── HDFSTransactionStateStorageTest.java │ ├── InMemoryTransactionStateStorage.java │ ├── LocalTransactionStateStorageTest.java │ └── TransactionEditTest.java │ ├── snapshot │ └── SnapshotCodecTest.java │ ├── util │ ├── AbstractConfigurationProviderTest.java │ ├── HBaseVersionTest.java │ ├── TransactionEditUtil.java │ └── TxUtilsTest.java │ └── visibility │ └── VisibilityFenceTest.java ├── tephra-distribution └── pom.xml ├── tephra-examples ├── pom.xml └── src │ ├── main │ └── java │ │ └── co │ │ └── cask │ │ └── tephra │ │ └── examples │ │ ├── BalanceBooks.java │ │ └── package-info.java │ └── test │ └── java │ └── co │ └── cask │ └── tephra │ └── examples │ └── BalanceBooksTest.java ├── tephra-hbase-compat-0.96 ├── pom.xml └── src │ ├── main │ └── java │ │ └── co │ │ └── cask │ │ └── tephra │ │ └── hbase96 │ │ ├── HBase96ConfigurationProvider.java │ │ ├── SecondaryIndexTable.java │ │ ├── TransactionAwareHTable.java │ │ └── coprocessor │ │ ├── CellSkipFilter.java │ │ ├── TransactionFilters.java │ │ ├── TransactionProcessor.java │ │ └── TransactionVisibilityFilter.java │ └── test │ └── java │ └── co │ └── cask │ └── tephra │ └── hbase96 │ ├── HBase96ConfigurationProviderTest.java │ ├── TransactionAwareHTableTest.java │ └── coprocessor │ ├── CellSkipFilterTest.java │ ├── TransactionProcessorTest.java │ └── TransactionVisibilityFilterTest.java ├── tephra-hbase-compat-0.98 ├── pom.xml └── src │ ├── main │ └── java │ │ └── co │ │ └── cask │ │ └── tephra │ │ └── hbase98 │ │ ├── HBase98ConfigurationProvider.java │ │ ├── SecondaryIndexTable.java │ │ ├── TransactionAwareHTable.java │ │ └── coprocessor │ │ ├── CellSkipFilter.java │ │ ├── TransactionFilters.java │ │ ├── TransactionProcessor.java │ │ └── TransactionVisibilityFilter.java │ └── test │ └── java │ └── co │ └── cask │ └── tephra │ └── hbase98 │ ├── HBase98ConfigurationProviderTest.java │ ├── TransactionAwareHTableTest.java │ └── coprocessor │ ├── CellSkipFilterTest.java │ ├── TransactionProcessorTest.java │ └── TransactionVisibilityFilterTest.java ├── tephra-hbase-compat-1.0-cdh ├── pom.xml └── src │ ├── main │ └── java │ │ └── co │ │ └── cask │ │ └── tephra │ │ └── hbase10cdh │ │ ├── HBase10ConfigurationProvider.java │ │ ├── SecondaryIndexTable.java │ │ ├── TransactionAwareHTable.java │ │ └── coprocessor │ │ ├── CellSkipFilter.java │ │ ├── TransactionFilters.java │ │ ├── TransactionProcessor.java │ │ └── TransactionVisibilityFilter.java │ └── test │ └── java │ └── co │ └── cask │ └── tephra │ └── hbase10cdh │ ├── HBase10ConfigurationProviderTest.java │ ├── TransactionAwareHTableTest.java │ └── coprocessor │ ├── CellSkipFilterTest.java │ ├── TransactionProcessorTest.java │ └── TransactionVisibilityFilterTest.java ├── tephra-hbase-compat-1.0 ├── pom.xml └── src │ ├── main │ └── java │ │ └── co │ │ └── cask │ │ └── tephra │ │ └── hbase10 │ │ ├── HBase10ConfigurationProvider.java │ │ ├── SecondaryIndexTable.java │ │ ├── TransactionAwareHTable.java │ │ └── coprocessor │ │ ├── CellSkipFilter.java │ │ ├── TransactionFilters.java │ │ ├── TransactionProcessor.java │ │ └── TransactionVisibilityFilter.java │ └── test │ └── java │ └── co │ └── cask │ └── tephra │ └── hbase10 │ ├── HBase10ConfigurationProviderTest.java │ ├── TransactionAwareHTableTest.java │ └── coprocessor │ ├── CellSkipFilterTest.java │ ├── TransactionProcessorTest.java │ └── TransactionVisibilityFilterTest.java └── tephra-hbase-compat-1.1 ├── pom.xml └── src ├── main └── java │ └── co │ └── cask │ └── tephra │ └── hbase11 │ ├── HBase11ConfigurationProvider.java │ ├── SecondaryIndexTable.java │ ├── TransactionAwareHTable.java │ └── coprocessor │ ├── CellSkipFilter.java │ ├── TransactionFilters.java │ ├── TransactionProcessor.java │ └── TransactionVisibilityFilter.java └── test └── java └── co └── cask └── tephra └── hbase11 ├── HBase11ConfigurationProviderTest.java ├── TransactionAwareHTableTest.java └── coprocessor ├── CellSkipFilterTest.java ├── TransactionProcessorTest.java └── TransactionVisibilityFilterTest.java /.github/workflows/build-report.yml: -------------------------------------------------------------------------------- 1 | # Copyright © 2024 Cask Data, Inc. 2 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not 3 | # use this file except in compliance with the License. You may obtain a copy of 4 | # the License at 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # Unless required by applicable law or agreed to in writing, software 7 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 8 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 9 | # License for the specific language governing permissions and limitations under 10 | # the License. 11 | 12 | # This workflow will build a Java project with Maven 13 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven 14 | # Note: Any changes to this workflow would be used only after merging into develop 15 | name: Build Unit Tests Report 16 | 17 | on: 18 | workflow_run: 19 | workflows: 20 | - Build with unit tests 21 | types: 22 | - completed 23 | 24 | jobs: 25 | build: 26 | runs-on: ubuntu-latest 27 | 28 | if: ${{ github.event.workflow_run.conclusion != 'skipped' }} 29 | 30 | steps: 31 | # Pinned 1.0.0 version 32 | - uses: marocchino/action-workflow_run-status@54b6e87d6cb552fc5f36dbe9a722a6048725917a 33 | 34 | - name: Download artifact 35 | uses: actions/download-artifact@v4 36 | with: 37 | github-token: ${{ secrets.GITHUB_TOKEN }} 38 | run-id: ${{ github.event.workflow_run.id }} 39 | path: artifacts/ 40 | 41 | - name: Surefire Report 42 | # Pinned 3.5.2 version 43 | uses: mikepenz/action-junit-report@16a9560bd02f11e7e3bf6b3e2ef6bba6c9d07c32 44 | if: always() 45 | with: 46 | report_paths: '**/target/surefire-reports/TEST-*.xml' 47 | github_token: ${{ secrets.GITHUB_TOKEN }} 48 | detailed_summary: true 49 | commit: ${{ github.event.workflow_run.head_sha }} 50 | check_name: Build Test Report 51 | 52 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | # Copyright © 2020 Cask Data, Inc. 2 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not 3 | # use this file except in compliance with the License. You may obtain a copy of 4 | # the License at 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # Unless required by applicable law or agreed to in writing, software 7 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 8 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 9 | # License for the specific language governing permissions and limitations under 10 | # the License. 11 | 12 | # This workflow will build a Java project with Maven 13 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven 14 | # Note: Any changes to this workflow would be used only after merging into develop 15 | name: Build with unit tests 16 | 17 | on: 18 | push: 19 | branches: [ develop, release/** ] 20 | pull_request: 21 | branches: [ develop, release/** ] 22 | types: [opened, synchronize, reopened, labeled] 23 | 24 | jobs: 25 | build: 26 | runs-on: k8s-runner-build 27 | 28 | # We allow builds: 29 | # 1) When it's a merge into a branch 30 | # 2) For PRs that are labeled as build and 31 | # - It's a code change 32 | # - A build label was just added 33 | # A bit complex, but prevents builds when other labels are manipulated 34 | if: > 35 | github.event_name == 'push' 36 | || (contains(github.event.pull_request.labels.*.name, 'build') 37 | && (github.event.action != 'labeled' || github.event.label.name == 'build') 38 | ) 39 | steps: 40 | - uses: actions/checkout@v3 41 | with: 42 | ref: ${{ github.event.workflow_run.head_sha }} 43 | submodules: recursive 44 | - name: Cache 45 | uses: actions/cache@v3 46 | with: 47 | path: ~/.m2/repository 48 | key: ${{ runner.os }}-maven-${{ github.workflow }}-${{ hashFiles('**/pom.xml') }} 49 | restore-keys: | 50 | ${{ runner.os }}-maven-${{ github.workflow }} 51 | - name: Build with Maven 52 | run: mvn clean test -fae -T 2 -B -V -DcloudBuild -Dmaven.wagon.http.retryHandler.count=3 -Dmaven.wagon.httpconnectionManager.ttlSeconds=25 53 | - name: Archive build artifacts 54 | uses: actions/upload-artifact@v4 55 | if: always() 56 | with: 57 | name: reports-${{ github.run_id }} 58 | path: | 59 | **/target/rat.txt 60 | **/target/surefire-reports/* 61 | 62 | - name: Checkstyle report 63 | uses: tivv/checkstyle-github-action@fcf8ffb7c6a5c110bbc5dafb84aca54caf359b80 64 | if: always() 65 | with: 66 | path: '**/checkstyle-result.xml' 67 | commit: ${{ github.event.workflow_run.head_sha }} 68 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Eclipse Files 4 | .project 5 | .settings 6 | .settings/* 7 | .classpath 8 | 9 | # Mobile Tools for Java (J2ME) 10 | .mtj.tmp/ 11 | 12 | # Package Files # 13 | *.jar 14 | *.war 15 | *.ear 16 | 17 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 18 | hs_err_pid* 19 | 20 | # IntelliJ Files 21 | *.iws 22 | *.iml 23 | *.ipr 24 | .idea 25 | 26 | # Maven build directory 27 | target 28 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright © 2014 Cask Data, Inc. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | # use this file except in compliance with the License. You may obtain a copy of 6 | # the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations under 14 | # the License. 15 | # 16 | 17 | language: java 18 | 19 | jdk: 20 | - oraclejdk7 21 | 22 | branches: 23 | only: 24 | - develop 25 | - /^feature\/.*$/ 26 | - /^hotfix\/.*$/ 27 | - /^release\/.*$/ 28 | 29 | sudo: false 30 | 31 | cache: 32 | directories: 33 | - $HOME/.m2 34 | -------------------------------------------------------------------------------- /bin/tephra-env.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2014 Cask Data, Inc. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not 7 | # use this file except in compliance with the License. You may obtain a copy of 8 | # the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 14 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 15 | # License for the specific language governing permissions and limitations under 16 | # the License. 17 | # 18 | 19 | # 20 | # Common environment settings for Tephra. 21 | # Uncomment the lines below, where needed, and modify to adapt to your environment. 22 | # 23 | 24 | # A string representing this instance of the Tephra server. $USER by default. 25 | export IDENT_STRING=$USER 26 | 27 | # Where log files are stored. /var/log by default. 28 | export LOG_DIR=/tmp/tephra-$IDENT_STRING 29 | 30 | # The directory where pid files are stored. /var/run by default. 31 | export PID_DIR=/tmp 32 | 33 | # Add any extra classes to the classpath 34 | # export EXTRA_CLASSPATH 35 | 36 | # Set the JVM heap size 37 | # export JAVA_HEAPMAX=-Xmx2048m 38 | 39 | # Additional runtime options 40 | # 41 | # GC logging options. 42 | # Uncomment the following two lines, making any desired changes, to enable GC logging output 43 | # export GC_LOG_OPTS="-verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:server-gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=2 -XX:GCLogFileSize=50M" 44 | # export OPTS="$OPTS $GC_LOG_OPTS" 45 | # 46 | # JMX options. 47 | # Uncomment the following two lines, making any desired changes, to enable remote JMX connectivity 48 | # export JMX_OPTS="-Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.port=13001" 49 | # export OPTS="$OPTS $JMX_OPTS" 50 | 51 | # Extra Java runtime options. 52 | # Below are what we set by default. May only work with SUN JVM. 53 | # For more on why as well as other possible settings, 54 | # see http://wiki.apache.org/hadoop/PerformanceTuning 55 | export OPTS="$OPTS -XX:+UseConcMarkSweepGC" 56 | -------------------------------------------------------------------------------- /conf/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | 20 | 21 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | %d{ISO8601} - %-5p [%t:%C{1}@%L] - %m%n 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 47 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /docs/_images/tephra_logo_light_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdapio/tephra/ab37901017fdf795d8296cc384f547b9090489af/docs/_images/tephra_logo_light_background.png -------------------------------------------------------------------------------- /docs/_images/tephra_logo_light_bkgnd_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdapio/tephra/ab37901017fdf795d8296cc384f547b9090489af/docs/_images/tephra_logo_light_bkgnd_small.png -------------------------------------------------------------------------------- /docs/_images/tephra_logo_light_bknd_cask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdapio/tephra/ab37901017fdf795d8296cc384f547b9090489af/docs/_images/tephra_logo_light_bknd_cask.png -------------------------------------------------------------------------------- /src/assemble/bin.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | bin 22 | 23 | tar.gz 24 | 25 | true 26 | 27 | 28 | 29 | 30 | true 31 | 32 | 33 | lib 34 | false 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | ${project.basedir}/../bin 46 | bin 47 | 0755 48 | 0755 49 | 50 | 51 | 52 | ${project.basedir}/.. 53 | . 54 | 55 | LICENSE 56 | README.rst 57 | 58 | 0644 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /suppressions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /tephra-api/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 4.0.0 20 | 21 | 22 | co.cask.tephra 23 | tephra 24 | 0.7.2-SNAPSHOT 25 | 26 | 27 | tephra-api 28 | Tephra API 29 | Tephra Transaction System API Module 30 | 31 | -------------------------------------------------------------------------------- /tephra-api/src/main/java/co/cask/tephra/TransactionAwares.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Collection; 21 | import java.util.List; 22 | 23 | /** 24 | * Utility class that provides handy methods for working with {@link TransactionAware} classes and their instances. 25 | */ 26 | public final class TransactionAwares { 27 | private TransactionAwares() {} 28 | 29 | /** 30 | * Create composite transaction aware object that delegates transaction logic to given collection of 31 | * {@link TransactionAware}s 32 | * @param transactionAwares collection of {@link TransactionAware}s 33 | * @return instance of {@link TransactionAware} 34 | */ 35 | public static TransactionAware of(Collection transactionAwares) { 36 | // this is most common case, trying to optimize 37 | if (transactionAwares.size() == 1) { 38 | return transactionAwares.iterator().next(); 39 | } 40 | 41 | TransactionAwareCollection result = new TransactionAwareCollection(); 42 | result.addAll(transactionAwares); 43 | 44 | return result; 45 | } 46 | 47 | private static class TransactionAwareCollection extends ArrayList implements TransactionAware { 48 | 49 | @Override 50 | public void startTx(Transaction tx) { 51 | for (TransactionAware txAware : this) { 52 | txAware.startTx(tx); 53 | } 54 | } 55 | 56 | @Override 57 | public void updateTx(Transaction tx) { 58 | for (TransactionAware txAware : this) { 59 | txAware.updateTx(tx); 60 | } 61 | } 62 | 63 | @Override 64 | public Collection getTxChanges() { 65 | List changes = new ArrayList(); 66 | for (TransactionAware txAware : this) { 67 | changes.addAll(txAware.getTxChanges()); 68 | } 69 | 70 | return changes; 71 | } 72 | 73 | @Override 74 | public boolean commitTx() throws Exception { 75 | boolean success = true; 76 | for (TransactionAware txAware : this) { 77 | success = success && txAware.commitTx(); 78 | } 79 | return success; 80 | } 81 | 82 | @Override 83 | public void postTxCommit() { 84 | for (TransactionAware txAware : this) { 85 | txAware.postTxCommit(); 86 | } 87 | } 88 | 89 | @Override 90 | public boolean rollbackTx() throws Exception { 91 | boolean success = true; 92 | for (TransactionAware txAware : this) { 93 | success = success && txAware.rollbackTx(); 94 | } 95 | return success; 96 | } 97 | 98 | @Override 99 | public String getTransactionAwareName() { 100 | // todo: will go away, see comment at TransactionAware 101 | StringBuilder sb = new StringBuilder("{"); 102 | for (TransactionAware txAware : this) { 103 | sb.append(txAware.getTransactionAwareName()).append(","); 104 | } 105 | sb.replace(sb.length() - 1, sb.length() - 1, "}"); 106 | return sb.toString(); 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /tephra-api/src/main/java/co/cask/tephra/TransactionConflictException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra; 18 | 19 | /** 20 | * Thrown to indicate transaction conflict occurred when trying to commit a transaction. 21 | */ 22 | public class TransactionConflictException extends TransactionFailureException { 23 | public TransactionConflictException(String message) { 24 | super(message); 25 | } 26 | 27 | public TransactionConflictException(String message, Throwable cause) { 28 | super(message, cause); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tephra-api/src/main/java/co/cask/tephra/TransactionFailureException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra; 18 | 19 | /** 20 | * Thrown to indicate execution of a transaction failed. 21 | */ 22 | public class TransactionFailureException extends Exception { 23 | public TransactionFailureException(String message) { 24 | super(message); 25 | } 26 | 27 | public TransactionFailureException(String message, Throwable cause) { 28 | super(message, cause); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tephra-api/src/main/java/co/cask/tephra/TransactionNotInProgressException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra; 18 | 19 | /** 20 | * Thrown when transaction has timed out. 21 | */ 22 | public class TransactionNotInProgressException extends TransactionFailureException { 23 | public TransactionNotInProgressException(String message) { 24 | super(message); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tephra-api/src/main/java/co/cask/tephra/TransactionType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra; 18 | 19 | /** 20 | * Type of transaction. 21 | */ 22 | public enum TransactionType { 23 | /** 24 | * Short transactions detect conflicts during commit. 25 | */ 26 | SHORT, 27 | /** 28 | * Long running transactions do not detect conflicts during commit. 29 | */ 30 | LONG 31 | } 32 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/ChangeId.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra; 18 | 19 | import java.util.Arrays; 20 | 21 | /** 22 | * Represents a row key from a data set changed as part of a transaction. 23 | */ 24 | public final class ChangeId { 25 | private final byte[] key; 26 | private final int hash; 27 | 28 | public ChangeId(byte[] bytes) { 29 | key = bytes; 30 | hash = Arrays.hashCode(bytes); 31 | } 32 | 33 | public byte[] getKey() { 34 | return key; 35 | } 36 | 37 | @Override 38 | public boolean equals(Object o) { 39 | if (o == this) { 40 | return true; 41 | } 42 | if (o == null || o.getClass() != ChangeId.class) { 43 | return false; 44 | } 45 | ChangeId other = (ChangeId) o; 46 | return hash == other.hash && Arrays.equals(key, other.key); 47 | } 48 | 49 | @Override 50 | public int hashCode() { 51 | return hash; 52 | } 53 | 54 | @Override 55 | public String toString() { 56 | return toStringBinary(key, 0, key.length); 57 | } 58 | 59 | // Copy from Bytes.toStringBinary so that we don't need direct dependencies on Bytes. 60 | private String toStringBinary(byte [] b, int off, int len) { 61 | StringBuilder result = new StringBuilder(); 62 | for (int i = off; i < off + len; ++i) { 63 | int ch = b[i] & 0xFF; 64 | if ((ch >= '0' && ch <= '9') 65 | || (ch >= 'A' && ch <= 'Z') 66 | || (ch >= 'a' && ch <= 'z') 67 | || " `~!@#$%^&*()-_=+[]{}|;:'\",.<>/?".indexOf(ch) >= 0) { 68 | result.append((char) ch); 69 | } else { 70 | result.append(String.format("\\x%02X", ch)); 71 | } 72 | } 73 | return result.toString(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/InvalidTruncateTimeException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra; 18 | 19 | /** 20 | * Thrown when truncate invalid list is called with a time, and when there are in-progress transactions that 21 | * were started before the given time. 22 | */ 23 | public class InvalidTruncateTimeException extends Exception { 24 | public InvalidTruncateTimeException(String s) { 25 | super(s); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/NoRetryStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra; 18 | 19 | /** 20 | * Does no retries 21 | */ 22 | public class NoRetryStrategy implements RetryStrategy { 23 | public static final RetryStrategy INSTANCE = new NoRetryStrategy(); 24 | 25 | private NoRetryStrategy() {} 26 | 27 | @Override 28 | public long nextRetry(TransactionFailureException reason, int failureCount) { 29 | return -1; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/RetryOnConflictStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra; 18 | 19 | /** 20 | * Retries transaction execution when transaction fails with {@link TransactionConflictException}. 21 | */ 22 | public class RetryOnConflictStrategy implements RetryStrategy { 23 | private final int maxRetries; 24 | private final long retryDelay; 25 | 26 | public RetryOnConflictStrategy(int maxRetries, long retryDelay) { 27 | this.maxRetries = maxRetries; 28 | this.retryDelay = retryDelay; 29 | } 30 | 31 | @Override 32 | public long nextRetry(TransactionFailureException reason, int failureCount) { 33 | if (reason instanceof TransactionConflictException) { 34 | return failureCount > maxRetries ? -1 : retryDelay; 35 | } else { 36 | return -1; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/RetryStrategies.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra; 18 | 19 | /** 20 | * Collection of {@link RetryStrategy}s. 21 | */ 22 | public final class RetryStrategies { 23 | private RetryStrategies() {} 24 | 25 | /** 26 | * @param maxRetries max number of retries 27 | * @param delayInMs delay between retries in milliseconds 28 | * @return RetryStrategy that retries transaction execution when transaction fails with 29 | * {@link TransactionConflictException} 30 | */ 31 | public static RetryStrategy retryOnConflict(int maxRetries, long delayInMs) { 32 | return new RetryOnConflictStrategy(maxRetries, delayInMs); 33 | } 34 | 35 | public static RetryStrategy noRetries() { 36 | return NoRetryStrategy.INSTANCE; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/RetryStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra; 18 | 19 | /** 20 | * Retry strategy for failed transactions 21 | */ 22 | public interface RetryStrategy { 23 | /** 24 | * Returns the number of milliseconds to wait before retrying the operation. 25 | * 26 | * @param reason Reason for transaction failure. 27 | * @param failureCount Number of times that the request has been failed. 28 | * @return Number of milliseconds to wait before retrying the operation. Returning {@code 0} means 29 | * retry it immediately, while negative means abort the operation. 30 | */ 31 | long nextRetry(TransactionFailureException reason, int failureCount); 32 | } 33 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/TransactionCodec.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra; 18 | 19 | import co.cask.tephra.distributed.TransactionConverterUtils; 20 | import co.cask.tephra.distributed.thrift.TTransaction; 21 | import org.apache.thrift.TDeserializer; 22 | import org.apache.thrift.TException; 23 | import org.apache.thrift.TSerializer; 24 | 25 | import java.io.IOException; 26 | 27 | /** 28 | * Handles serialization and deserialization of {@link co.cask.tephra.Transaction} instances to and from {@code byte[]}. 29 | */ 30 | public class TransactionCodec { 31 | 32 | public TransactionCodec() { 33 | } 34 | 35 | public byte[] encode(Transaction tx) throws IOException { 36 | TTransaction thriftTx = TransactionConverterUtils.wrap(tx); 37 | TSerializer serializer = new TSerializer(); 38 | try { 39 | return serializer.serialize(thriftTx); 40 | } catch (TException te) { 41 | throw new IOException(te); 42 | } 43 | } 44 | 45 | public Transaction decode(byte[] encoded) throws IOException { 46 | TTransaction thriftTx = new TTransaction(); 47 | TDeserializer deserializer = new TDeserializer(); 48 | try { 49 | deserializer.deserialize(thriftTx, encoded); 50 | return TransactionConverterUtils.unwrap(thriftTx); 51 | } catch (TException te) { 52 | throw new IOException(te); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/TransactionCouldNotTakeSnapshotException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra; 18 | 19 | /** 20 | * Throw when taking a snapshot fails. 21 | */ 22 | public class TransactionCouldNotTakeSnapshotException extends Exception { 23 | public TransactionCouldNotTakeSnapshotException(String message) { 24 | super(message); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/TransactionExecutorFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra; 18 | 19 | /** 20 | * A factory for transaction executors. 21 | */ 22 | public interface TransactionExecutorFactory { 23 | 24 | TransactionExecutor createExecutor(Iterable txAwares); 25 | 26 | } 27 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/coprocessor/TransactionStateCacheSupplier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.coprocessor; 18 | 19 | import com.google.common.base.Supplier; 20 | import org.apache.hadoop.conf.Configuration; 21 | 22 | /** 23 | * Supplies instances of {@link TransactionStateCache} implementations. 24 | */ 25 | public class TransactionStateCacheSupplier implements Supplier { 26 | protected static volatile TransactionStateCache instance; 27 | protected static Object lock = new Object(); 28 | 29 | protected final Configuration conf; 30 | 31 | public TransactionStateCacheSupplier(Configuration conf) { 32 | this.conf = conf; 33 | } 34 | 35 | /** 36 | * Returns a singleton instance of the transaction state cache, performing lazy initialization if necessary. 37 | * @return A shared instance of the transaction state cache. 38 | */ 39 | @Override 40 | public TransactionStateCache get() { 41 | if (instance == null) { 42 | synchronized (lock) { 43 | if (instance == null) { 44 | instance = new TransactionStateCache(); 45 | instance.setConf(conf); 46 | instance.start(); 47 | } 48 | } 49 | } 50 | return instance; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/coprocessor/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | /** 18 | * This package contains HBase coprocessor implementations for the transaction system. 19 | */ 20 | package co.cask.tephra.coprocessor; 21 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/distributed/CloseableThriftClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.distributed; 18 | 19 | /** 20 | * An {@link AutoCloseable} to automatically return the thrift client to the ThriftClientProvider. 21 | */ 22 | public class CloseableThriftClient implements AutoCloseable { 23 | 24 | private final ThriftClientProvider provider; 25 | private final TransactionServiceThriftClient thriftClient; 26 | 27 | public CloseableThriftClient(ThriftClientProvider provider, TransactionServiceThriftClient thriftClient) { 28 | this.provider = provider; 29 | this.thriftClient = thriftClient; 30 | } 31 | 32 | public TransactionServiceThriftClient getThriftClient() { 33 | return thriftClient; 34 | } 35 | 36 | @Override 37 | public void close() { 38 | // in any case, the client must be returned to the pool. The pool is 39 | // responsible for discarding the client if it is in a bad state. 40 | provider.returnClient(thriftClient); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/distributed/RetryNTimes.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.distributed; 18 | 19 | import co.cask.tephra.TxConstants; 20 | import org.apache.hadoop.conf.Configuration; 21 | 22 | /** 23 | * A retry strategy that makes N attempts and then gives up. This does 24 | * not do anything before the re-attempt - extend this class to add a 25 | * sleep or similar. 26 | */ 27 | public class RetryNTimes extends RetryStrategy { 28 | 29 | int attempts = 0; 30 | int limit; 31 | 32 | /** 33 | * @param maxAttempts the number of attempts after which to stop 34 | */ 35 | protected RetryNTimes(int maxAttempts) { 36 | limit = maxAttempts; 37 | } 38 | 39 | @Override 40 | boolean failOnce() { 41 | ++attempts; 42 | return attempts < limit; 43 | } 44 | 45 | /** 46 | * A retry strategy provider for this strategy. 47 | */ 48 | public static class Provider implements RetryStrategyProvider { 49 | 50 | int nTimes; 51 | 52 | public Provider() { 53 | this.nTimes = TxConstants.Service.DEFAULT_DATA_TX_CLIENT_ATTEMPTS; 54 | } 55 | 56 | @Override 57 | public void configure(Configuration config) { 58 | nTimes = config.getInt(TxConstants.Service.CFG_DATA_TX_CLIENT_ATTEMPTS, nTimes); 59 | } 60 | 61 | @Override 62 | public RetryStrategy newRetryStrategy() { 63 | return new RetryNTimes(nTimes); 64 | } 65 | 66 | @Override 67 | public String toString() { 68 | return nTimes + " attempts without delay"; 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/distributed/RetryStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.distributed; 18 | 19 | /** 20 | * A retry strategy is an abstraction over how the remote tx client shuold retry operations after connection 21 | * failures. 22 | */ 23 | public abstract class RetryStrategy { 24 | 25 | /** 26 | * Increments the number of failed attempts. 27 | * @return whether another attempt should be made 28 | */ 29 | abstract boolean failOnce(); 30 | 31 | /** 32 | * Should be called before re-attempting. This can, for instance 33 | * inject a sleep time between retries. Default implementation is 34 | * to do nothing. 35 | */ 36 | void beforeRetry() { 37 | // do nothinhg 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/distributed/RetryStrategyProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.distributed; 18 | 19 | import org.apache.hadoop.conf.Configuration; 20 | 21 | /** 22 | * A retry strategy provider is used by the tx client to get a new retry strategy for every call. 23 | */ 24 | public interface RetryStrategyProvider { 25 | 26 | /** 27 | * Provides a new instance of a retry strategy. 28 | * @return a retry strategy 29 | */ 30 | RetryStrategy newRetryStrategy(); 31 | 32 | /** 33 | * Configure the strategy. 34 | * @param config the configuration 35 | */ 36 | void configure(Configuration config); 37 | 38 | } 39 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/distributed/RetryWithBackoff.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2015 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.distributed; 18 | 19 | import co.cask.tephra.TxConstants; 20 | import org.apache.hadoop.conf.Configuration; 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | 24 | /** 25 | * A retry strategy that makes N attempts and then gives up. This does 26 | * not do anything before the re-attempt - extend this class to add a 27 | * sleep or similar. 28 | */ 29 | public class RetryWithBackoff extends RetryStrategy { 30 | 31 | private static final Logger LOG = 32 | LoggerFactory.getLogger(RetryWithBackoff.class); 33 | 34 | int initialSleep; // initial sleep time 35 | int backoffFactor; // factor by which to increase sleep for each retry 36 | int maxSleep; // max sleep time. stop retrying when we exceed this 37 | int sleep; // current sleep time 38 | 39 | /** 40 | * @param initial the initial sleep time (before first retry) 41 | * @param backoff the backoff factor by which sleep time is multiplied 42 | * after each retry 43 | * @param limit the max sleep time. if sleep time reaches this limit, we 44 | * stop retrying 45 | */ 46 | protected RetryWithBackoff(int initial, int backoff, int limit) { 47 | initialSleep = initial; 48 | backoffFactor = backoff; 49 | maxSleep = limit; 50 | sleep = initialSleep; 51 | } 52 | 53 | @Override 54 | boolean failOnce() { 55 | return sleep < maxSleep; 56 | } 57 | 58 | @Override 59 | void beforeRetry() { 60 | LOG.info("Sleeping " + sleep + " ms before retry."); 61 | long current = System.currentTimeMillis(); 62 | long end = current + sleep; 63 | while (current < end) { 64 | try { 65 | Thread.sleep(end - current); 66 | } catch (InterruptedException e) { 67 | // do nothing 68 | } 69 | current = System.currentTimeMillis(); 70 | } 71 | sleep = sleep * backoffFactor; 72 | } 73 | 74 | /** 75 | * A provider for this retry strategy. 76 | */ 77 | public static class Provider implements RetryStrategyProvider { 78 | 79 | int initialSleep; // initial sleep time 80 | int backoffFactor; // factor by which to increase sleep for each retry 81 | int maxSleep; // max sleep time. stop retrying when we exceed this 82 | 83 | public Provider() { 84 | initialSleep = TxConstants.Service.DEFAULT_DATA_TX_CLIENT_BACKOFF_INITIAL; 85 | backoffFactor = TxConstants.Service.DEFAULT_DATA_TX_CLIENT_BACKOFF_FACTOR; 86 | maxSleep = TxConstants.Service.DEFAULT_DATA_TX_CLIENT_BACKOFF_LIMIT; 87 | } 88 | 89 | public void configure(Configuration config) { 90 | initialSleep = config.getInt(TxConstants.Service.CFG_DATA_TX_CLIENT_BACKOFF_INITIAL, initialSleep); 91 | backoffFactor = config.getInt(TxConstants.Service.CFG_DATA_TX_CLIENT_BACKOFF_FACTOR, backoffFactor); 92 | maxSleep = config.getInt(TxConstants.Service.CFG_DATA_TX_CLIENT_BACKOFF_LIMIT, maxSleep); 93 | } 94 | 95 | @Override 96 | public RetryStrategy newRetryStrategy() { 97 | return new RetryWithBackoff(initialSleep, backoffFactor, maxSleep); 98 | } 99 | 100 | @Override 101 | public String toString() { 102 | return "sleep " + initialSleep + " ms with back off factor " + 103 | backoffFactor + " and limit " + maxSleep + " ms"; 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/distributed/SingleUseClientProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.distributed; 18 | 19 | import org.apache.hadoop.conf.Configuration; 20 | import org.apache.thrift.TException; 21 | import org.apache.twill.discovery.DiscoveryServiceClient; 22 | import org.slf4j.Logger; 23 | import org.slf4j.LoggerFactory; 24 | 25 | import java.util.concurrent.TimeoutException; 26 | 27 | /** 28 | * An tx client provider that creates a new connection every time. 29 | */ 30 | public class SingleUseClientProvider extends AbstractClientProvider { 31 | 32 | private static final Logger LOG = 33 | LoggerFactory.getLogger(SingleUseClientProvider.class); 34 | 35 | public SingleUseClientProvider(Configuration conf, DiscoveryServiceClient discoveryServiceClient, int timeout) { 36 | super(conf, discoveryServiceClient); 37 | this.timeout = timeout; 38 | } 39 | 40 | final int timeout; 41 | 42 | @Override 43 | public CloseableThriftClient getCloseableClient() throws TException, TimeoutException, InterruptedException { 44 | try { 45 | return new CloseableThriftClient(this, newClient(timeout)); 46 | } catch (TException e) { 47 | LOG.error("Unable to create new tx client: " + e.getMessage()); 48 | throw e; 49 | } 50 | } 51 | 52 | @Override 53 | public void returnClient(TransactionServiceThriftClient client) { 54 | client.close(); 55 | } 56 | 57 | @Override 58 | public String toString() { 59 | return "Single-use(timeout = " + timeout + ")"; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/distributed/ThreadLocalClientProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.distributed; 18 | 19 | import org.apache.hadoop.conf.Configuration; 20 | import org.apache.thrift.TException; 21 | import org.apache.twill.discovery.DiscoveryServiceClient; 22 | import org.slf4j.Logger; 23 | import org.slf4j.LoggerFactory; 24 | 25 | import java.util.concurrent.TimeoutException; 26 | 27 | /** 28 | * An tx client provider that uses thread local to maintain at most one open connection per thread. 29 | * Note that there can be a connection leak if the threads are recycled. 30 | */ 31 | public class ThreadLocalClientProvider extends AbstractClientProvider { 32 | 33 | private static final Logger LOG = 34 | LoggerFactory.getLogger(ThreadLocalClientProvider.class); 35 | 36 | ThreadLocal clients = new ThreadLocal<>(); 37 | 38 | public ThreadLocalClientProvider(Configuration conf, DiscoveryServiceClient discoveryServiceClient) { 39 | super(conf, discoveryServiceClient); 40 | } 41 | 42 | @Override 43 | public CloseableThriftClient getCloseableClient() throws TException, TimeoutException, InterruptedException { 44 | TransactionServiceThriftClient client = this.clients.get(); 45 | if (client == null) { 46 | try { 47 | client = this.newClient(); 48 | clients.set(client); 49 | } catch (TException e) { 50 | LOG.error("Unable to create new tx client for thread: " 51 | + e.getMessage()); 52 | throw e; 53 | } 54 | } 55 | return new CloseableThriftClient(this, client); 56 | } 57 | 58 | @Override 59 | public void returnClient(TransactionServiceThriftClient client) { 60 | if (!client.isValid()) { 61 | client.close(); 62 | clients.remove(); 63 | } 64 | } 65 | 66 | @Override 67 | public String toString() { 68 | return "Thread-local"; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/distributed/ThriftClientProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.distributed; 18 | 19 | import org.apache.thrift.TException; 20 | 21 | import java.util.concurrent.TimeoutException; 22 | 23 | /** 24 | * This interface is used to provide thrift tx service clients: 25 | * there is only one (singleton) 26 | * tx service per JVM, but many threads may use it concurrently. 27 | * However, being a thrift client, it is not thread-safe. In 28 | * order to avoid serializing all tx calls by synchronizing 29 | * on the tx service client, we employ a pool of clients. But 30 | * in different scenarios there are different strategies for 31 | * pooling: If there are many short-lived threads, it is wise 32 | * to have a shared pool between all threads. But if there are 33 | * few long-lived threads, it may be better to have thread-local 34 | * client for each thread. 35 | * 36 | * This interface provides an abstraction of the pooling strategy. 37 | */ 38 | public interface ThriftClientProvider { 39 | 40 | /** 41 | * Initialize the provider. At this point, it should be verified 42 | * that tx service is up and running and getClient() can 43 | * create new clients when necessary. 44 | */ 45 | void initialize() throws TException; 46 | 47 | /** 48 | * Retrieve an AutoCloseable wrapper around tx client for exclusive use by the 49 | * current thread. The client must be closed (returned) to the provider after use. 50 | * @return an tx client, connected and fully functional 51 | */ 52 | CloseableThriftClient getCloseableClient() throws TException, 53 | TimeoutException, InterruptedException; 54 | 55 | /** 56 | * Release an tx client back to the provider's pool, if the client is valid. 57 | * If the client becomes disfunctional, for instance, due to a socket 58 | * exception. The provider must make sure to close the client, and it 59 | * must remove the client from its arsenal and be prepared to create 60 | * a new client subsequently. 61 | * 62 | * @param client The client to return 63 | */ 64 | void returnClient(TransactionServiceThriftClient client); 65 | } 66 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/distributed/TransactionConverterUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.distributed; 18 | 19 | import co.cask.tephra.Transaction; 20 | import co.cask.tephra.TransactionType; 21 | import co.cask.tephra.distributed.thrift.TTransaction; 22 | import co.cask.tephra.distributed.thrift.TTransactionType; 23 | import co.cask.tephra.distributed.thrift.TVisibilityLevel; 24 | import com.google.common.primitives.Longs; 25 | 26 | /** 27 | * Utility methods to convert to thrift and back. 28 | */ 29 | public final class TransactionConverterUtils { 30 | private static final long[] EMPTY_LONG_ARRAY = {}; 31 | 32 | public static TTransaction wrap(Transaction tx) { 33 | return new TTransaction(tx.getTransactionId(), tx.getReadPointer(), 34 | Longs.asList(tx.getInvalids()), Longs.asList(tx.getInProgress()), 35 | tx.getFirstShortInProgress(), getTTransactionType(tx.getType()), 36 | tx.getWritePointer(), Longs.asList(tx.getCheckpointWritePointers()), 37 | getTVisibilityLevel(tx.getVisibilityLevel())); 38 | } 39 | 40 | public static Transaction unwrap(TTransaction thriftTx) { 41 | return new Transaction(thriftTx.getReadPointer(), thriftTx.getTransactionId(), thriftTx.getWritePointer(), 42 | thriftTx.getInvalids() == null ? EMPTY_LONG_ARRAY : Longs.toArray(thriftTx.getInvalids()), 43 | thriftTx.getInProgress() == null ? EMPTY_LONG_ARRAY : 44 | Longs.toArray(thriftTx.getInProgress()), 45 | thriftTx.getFirstShort(), getTransactionType(thriftTx.getType()), 46 | thriftTx.getCheckpointWritePointers() == null ? EMPTY_LONG_ARRAY : 47 | Longs.toArray(thriftTx.getCheckpointWritePointers()), 48 | getVisibilityLevel(thriftTx.getVisibilityLevel())); 49 | } 50 | 51 | private static TransactionType getTransactionType(TTransactionType tType) { 52 | return tType == TTransactionType.SHORT ? TransactionType.SHORT : TransactionType.LONG; 53 | } 54 | 55 | private static TTransactionType getTTransactionType(TransactionType type) { 56 | return type == TransactionType.SHORT ? TTransactionType.SHORT : TTransactionType.LONG; 57 | } 58 | 59 | private static Transaction.VisibilityLevel getVisibilityLevel(TVisibilityLevel tLevel) { 60 | // default to SNAPSHOT 61 | if (tLevel == null) { 62 | return Transaction.VisibilityLevel.SNAPSHOT; 63 | } 64 | 65 | switch (tLevel) { 66 | case SNAPSHOT: 67 | return Transaction.VisibilityLevel.SNAPSHOT; 68 | case SNAPSHOT_EXCLUDE_CURRENT: 69 | return Transaction.VisibilityLevel.SNAPSHOT_EXCLUDE_CURRENT; 70 | case SNAPSHOT_ALL: 71 | return Transaction.VisibilityLevel.SNAPSHOT_ALL; 72 | default: 73 | throw new IllegalArgumentException("Unknown TVisibilityLevel: " + tLevel); 74 | } 75 | } 76 | 77 | private static TVisibilityLevel getTVisibilityLevel(Transaction.VisibilityLevel level) { 78 | switch (level) { 79 | case SNAPSHOT: 80 | return TVisibilityLevel.SNAPSHOT; 81 | case SNAPSHOT_EXCLUDE_CURRENT: 82 | return TVisibilityLevel.SNAPSHOT_EXCLUDE_CURRENT; 83 | case SNAPSHOT_ALL: 84 | return TVisibilityLevel.SNAPSHOT_ALL; 85 | default: 86 | throw new IllegalArgumentException("Unknown VisibilityLevel: " + level); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/distributed/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | /** 18 | * This package contains standalone server of the transaction system v2. It is now simple netty piece, but will change 19 | * we integrate new RPC 20 | */ 21 | package co.cask.tephra.distributed; 22 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/distributed/thrift/TTransactionType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | /** 18 | * Autogenerated by Thrift Compiler (0.9.0) 19 | * 20 | * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 21 | * @generated 22 | */ 23 | package co.cask.tephra.distributed.thrift; 24 | 25 | 26 | import java.util.Map; 27 | import java.util.HashMap; 28 | import org.apache.thrift.TEnum; 29 | 30 | public enum TTransactionType implements org.apache.thrift.TEnum { 31 | SHORT(1), 32 | LONG(2); 33 | 34 | private final int value; 35 | 36 | private TTransactionType(int value) { 37 | this.value = value; 38 | } 39 | 40 | /** 41 | * Get the integer value of this enum value, as defined in the Thrift IDL. 42 | */ 43 | public int getValue() { 44 | return value; 45 | } 46 | 47 | /** 48 | * Find a the enum type by its integer value, as defined in the Thrift IDL. 49 | * @return null if the value is not found. 50 | */ 51 | public static TTransactionType findByValue(int value) { 52 | switch (value) { 53 | case 1: 54 | return SHORT; 55 | case 2: 56 | return LONG; 57 | default: 58 | return null; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/distributed/thrift/TVisibilityLevel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | /** 18 | * Autogenerated by Thrift Compiler (0.9.0) 19 | * 20 | * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 21 | * @generated 22 | */ 23 | package co.cask.tephra.distributed.thrift; 24 | 25 | 26 | public enum TVisibilityLevel implements org.apache.thrift.TEnum { 27 | SNAPSHOT(1), 28 | SNAPSHOT_EXCLUDE_CURRENT(2), 29 | SNAPSHOT_ALL(3); 30 | 31 | private final int value; 32 | 33 | private TVisibilityLevel(int value) { 34 | this.value = value; 35 | } 36 | 37 | /** 38 | * Get the integer value of this enum value, as defined in the Thrift IDL. 39 | */ 40 | public int getValue() { 41 | return value; 42 | } 43 | 44 | /** 45 | * Find a the enum type by its integer value, as defined in the Thrift IDL. 46 | * @return null if the value is not found. 47 | */ 48 | public static TVisibilityLevel findByValue(int value) { 49 | switch (value) { 50 | case 1: 51 | return SNAPSHOT; 52 | case 2: 53 | return SNAPSHOT_EXCLUDE_CURRENT; 54 | case 3: 55 | return SNAPSHOT_ALL; 56 | default: 57 | return null; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/inmemory/MinimalTxSystemClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.inmemory; 18 | 19 | import co.cask.tephra.InvalidTruncateTimeException; 20 | import co.cask.tephra.Transaction; 21 | import co.cask.tephra.TransactionCouldNotTakeSnapshotException; 22 | import co.cask.tephra.TransactionNotInProgressException; 23 | import co.cask.tephra.TransactionSystemClient; 24 | import co.cask.tephra.TransactionType; 25 | import co.cask.tephra.TxConstants; 26 | 27 | import java.io.InputStream; 28 | import java.util.Collection; 29 | import java.util.Set; 30 | 31 | /** 32 | * Dummy implementation of TxSystemClient. May be useful for perf testing. 33 | */ 34 | public class MinimalTxSystemClient implements TransactionSystemClient { 35 | private long currentTxPointer = 1; 36 | 37 | @Override 38 | public Transaction startShort() { 39 | long wp = currentTxPointer++; 40 | // NOTE: -1 here is because we have logic that uses (readpointer + 1) as a "exclusive stop key" in some datasets 41 | return new Transaction( 42 | Long.MAX_VALUE - 1, wp, new long[0], new long[0], 43 | Transaction.NO_TX_IN_PROGRESS, TransactionType.SHORT); 44 | } 45 | 46 | @Override 47 | public Transaction startShort(int timeout) { 48 | return startShort(); 49 | } 50 | 51 | @Override 52 | public Transaction startLong() { 53 | return startShort(); 54 | } 55 | 56 | @Override 57 | public boolean canCommit(Transaction tx, Collection changeIds) { 58 | return true; 59 | } 60 | 61 | @Override 62 | public boolean commit(Transaction tx) { 63 | return true; 64 | } 65 | 66 | @Override 67 | public void abort(Transaction tx) { 68 | // do nothing 69 | } 70 | 71 | @Override 72 | public boolean invalidate(long tx) { 73 | return true; 74 | } 75 | 76 | @Override 77 | public Transaction checkpoint(Transaction tx) throws TransactionNotInProgressException { 78 | return tx; 79 | } 80 | 81 | @Override 82 | public InputStream getSnapshotInputStream() throws TransactionCouldNotTakeSnapshotException { 83 | throw new TransactionCouldNotTakeSnapshotException("Not snapshot to take."); 84 | } 85 | 86 | @Override 87 | public String status() { 88 | return TxConstants.STATUS_OK; 89 | } 90 | 91 | @Override 92 | public void resetState() { 93 | // do nothing 94 | } 95 | 96 | @Override 97 | public boolean truncateInvalidTx(Set invalidTxIds) { 98 | return true; 99 | } 100 | 101 | @Override 102 | public boolean truncateInvalidTxBefore(long time) throws InvalidTruncateTimeException { 103 | return true; 104 | } 105 | 106 | @Override 107 | public int getInvalidSize() { 108 | return 0; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/inmemory/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | /** 18 | * This package contains in memory implementation of the transaction system v2. 19 | */ 20 | package co.cask.tephra.inmemory; 21 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/metrics/MetricsCollector.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.metrics; 18 | 19 | import com.google.common.util.concurrent.Service; 20 | import org.apache.hadoop.conf.Configurable; 21 | import org.apache.hadoop.conf.Configuration; 22 | 23 | /** 24 | * Basic API for Tephra to support system metrics. 25 | */ 26 | public interface MetricsCollector extends Service { 27 | /** 28 | * Report a metric as an absolute value. 29 | */ 30 | void gauge(String metricName, int value, String... tags); 31 | 32 | /** 33 | * Report a metric as a count over a given time duration. This method uses an implicit count of 1. 34 | */ 35 | void rate(String metricName); 36 | 37 | /** 38 | * Report a metric as a count over a given time duration. 39 | */ 40 | void rate(String metricName, int count); 41 | 42 | /** 43 | * Report a metric calculating the distribution of the value. 44 | */ 45 | void histogram(String metricName, int value); 46 | 47 | /** 48 | * Called before the collector service is started, allowing the collector to setup any 49 | * required configuration. 50 | */ 51 | void configure(Configuration conf); 52 | } 53 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/metrics/TxMetricsCollector.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.metrics; 18 | 19 | import com.google.common.util.concurrent.AbstractIdleService; 20 | import org.apache.hadoop.conf.Configuration; 21 | 22 | /** 23 | * Metrics Collector Class, to emit Transaction Related Metrics. 24 | * Note: This default implementation is a no-op and doesn't emit any metrics 25 | */ 26 | public class TxMetricsCollector extends AbstractIdleService implements MetricsCollector { 27 | 28 | @Override 29 | public void gauge(String metricName, int value, String... tags) { 30 | //no-op 31 | } 32 | 33 | @Override 34 | public void rate(String metricName) { 35 | // no-op 36 | } 37 | 38 | @Override 39 | public void rate(String metricName, int count) { 40 | // no-op 41 | } 42 | 43 | @Override 44 | public void histogram(String metricName, int value) { 45 | // no-op 46 | } 47 | 48 | @Override 49 | public void configure(Configuration conf) { 50 | // no-op 51 | } 52 | 53 | /* Service methods */ 54 | 55 | @Override 56 | protected void startUp() throws Exception { 57 | // no-op 58 | } 59 | 60 | @Override 61 | protected void shutDown() throws Exception { 62 | // no-op 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | /** 18 | * This package contains implementations of the transaction system v2. 19 | */ 20 | package co.cask.tephra; 21 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/persist/AbstractTransactionStateStorage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.persist; 18 | 19 | import co.cask.tephra.snapshot.SnapshotCodecProvider; 20 | import com.google.common.util.concurrent.AbstractIdleService; 21 | 22 | import java.io.IOException; 23 | import java.io.OutputStream; 24 | 25 | /** 26 | * Common base class for all transaction storage implementations. This implement logic to prefix a snapshot 27 | * with a version when encoding, and to select the correct codec for decoding based on this version prefix. 28 | */ 29 | public abstract class AbstractTransactionStateStorage extends AbstractIdleService implements TransactionStateStorage { 30 | 31 | protected final SnapshotCodecProvider codecProvider; 32 | 33 | protected AbstractTransactionStateStorage(SnapshotCodecProvider codecProvider) { 34 | this.codecProvider = codecProvider; 35 | } 36 | 37 | @Override 38 | public void writeSnapshot(OutputStream out, TransactionSnapshot snapshot) throws IOException { 39 | codecProvider.encode(out, snapshot); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/persist/HDFSTransactionLogReaderSupplier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.persist; 18 | 19 | import co.cask.tephra.TxConstants; 20 | import com.google.common.base.Supplier; 21 | import org.apache.hadoop.io.SequenceFile; 22 | import org.apache.hadoop.io.Text; 23 | 24 | /** 25 | * Provides the correct version of {@link TransactionLogReader}, based on the log's version metadata, 26 | * to read HDFS Transaction Logs. 27 | */ 28 | public class HDFSTransactionLogReaderSupplier implements Supplier { 29 | private final SequenceFile.Reader reader; 30 | private final byte version; 31 | private TransactionLogReader logReader; 32 | 33 | public HDFSTransactionLogReaderSupplier(SequenceFile.Reader reader) { 34 | this.reader = reader; 35 | Text versionInfo = reader.getMetadata().get(new Text(TxConstants.TransactionLog.VERSION_KEY)); 36 | this.version = versionInfo == null ? 1 : Byte.parseByte(versionInfo.toString()); 37 | } 38 | 39 | @Override 40 | public TransactionLogReader get() { 41 | if (logReader != null) { 42 | return logReader; 43 | } 44 | 45 | switch (version) { 46 | case 2: 47 | logReader = new HDFSTransactionLogReaderV2(reader); 48 | return logReader; 49 | case 1: 50 | logReader = new HDFSTransactionLogReaderV1(reader); 51 | return logReader; 52 | default: 53 | throw new IllegalArgumentException(String.format("Invalid version %s found in the Transaction Log", version)); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/persist/HDFSTransactionLogReaderV1.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.persist; 18 | 19 | import org.apache.hadoop.io.LongWritable; 20 | import org.apache.hadoop.io.SequenceFile; 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | 24 | import java.io.EOFException; 25 | import java.io.IOException; 26 | 27 | /** 28 | * {@link TransactionLogReader} that can read v1 (default) version of Transaction logs. The logs are expected to 29 | * have a sequence of {@link TransactionEdit}s. 30 | */ 31 | public class HDFSTransactionLogReaderV1 implements TransactionLogReader { 32 | private static final Logger LOG = LoggerFactory.getLogger(HDFSTransactionLogReaderV1.class); 33 | private final SequenceFile.Reader reader; 34 | private final LongWritable key; 35 | private boolean closed; 36 | 37 | public HDFSTransactionLogReaderV1(SequenceFile.Reader reader) { 38 | this.reader = reader; 39 | this.key = new LongWritable(); 40 | } 41 | 42 | @Override 43 | public TransactionEdit next() throws IOException { 44 | return next(new TransactionEdit()); 45 | } 46 | 47 | @Override 48 | public TransactionEdit next(TransactionEdit reuse) throws IOException { 49 | if (closed) { 50 | return null; 51 | } 52 | 53 | try { 54 | boolean successful = reader.next(key, reuse); 55 | return successful ? reuse : null; 56 | } catch (EOFException e) { 57 | LOG.warn("Hit an unexpected EOF while trying to read the Transaction Edit. Skipping the entry.", e); 58 | return null; 59 | } 60 | } 61 | 62 | @Override 63 | public void close() throws IOException { 64 | if (closed) { 65 | return; 66 | } 67 | reader.close(); 68 | closed = true; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/persist/TransactionLog.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.persist; 18 | 19 | import java.io.IOException; 20 | import java.util.List; 21 | 22 | /** 23 | * Represents a log of transaction state changes. 24 | */ 25 | public interface TransactionLog { 26 | 27 | String getName(); 28 | 29 | long getTimestamp(); 30 | 31 | void append(TransactionEdit edit) throws IOException; 32 | 33 | void append(List edits) throws IOException; 34 | 35 | void close() throws IOException; 36 | 37 | TransactionLogReader getReader() throws IOException; 38 | } 39 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/persist/TransactionLogReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.persist; 18 | 19 | import java.io.Closeable; 20 | import java.io.IOException; 21 | 22 | /** 23 | * Represents a reader for {@link TransactionLog} instances. 24 | */ 25 | public interface TransactionLogReader extends Closeable { 26 | /** 27 | * Returns the next {@code TransactionEdit} from the log file, based on the current position, or {@code null} 28 | * if the end of the file has been reached. 29 | */ 30 | TransactionEdit next() throws IOException; 31 | 32 | /** 33 | * Populates {@code reuse} with the next {@code TransactionEdit}, based on the reader's current position in the 34 | * log file. 35 | * @param reuse The {@code TransactionEdit} instance to populate with the log entry data. 36 | * @return The {@code TransactionEdit} instance, or {@code null} if the end of the file has been reached. 37 | * @throws IOException If an error is encountered reading the log data. 38 | */ 39 | TransactionEdit next(TransactionEdit reuse) throws IOException; 40 | } 41 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/persist/TransactionLogWriter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.persist; 18 | 19 | import java.io.Closeable; 20 | import java.io.IOException; 21 | 22 | /** 23 | * Common interface for transaction log writers used by classes extending {@link AbstractTransactionLog}. 24 | */ 25 | public interface TransactionLogWriter extends Closeable { 26 | /** 27 | * Adds a new transaction entry to the log. Note that this does not guarantee that the entry has been flushed 28 | * to persistent storage until {@link #sync()} has been called. 29 | * 30 | * @param entry The transaction edit to append. 31 | * @throws IOException If an error occurs while writing the edit to storage. 32 | */ 33 | void append(AbstractTransactionLog.Entry entry) throws IOException; 34 | 35 | /** 36 | * Makes an entry of number of transaction entries that will follow in that log in a single sync. 37 | * 38 | * @param count Number of transaction entries. 39 | * @throws IOException If an error occurs while writing the count to storage. 40 | */ 41 | void commitMarker(int count) throws IOException; 42 | 43 | /** 44 | * Syncs any pending transaction edits added through {@link #append(AbstractTransactionLog.Entry)}, 45 | * but not yet flushed to durable storage. 46 | * 47 | * @throws IOException If an error occurs while flushing the outstanding edits. 48 | */ 49 | void sync() throws IOException; 50 | } 51 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/persist/TransactionVisibilityState.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.persist; 18 | 19 | import co.cask.tephra.TransactionManager; 20 | 21 | import java.util.Collection; 22 | import java.util.NavigableMap; 23 | 24 | /** 25 | * Transaction Visibility state contains information required by TransactionProcessor CoProcessor 26 | * to determine cell visibility. 27 | */ 28 | public interface TransactionVisibilityState { 29 | 30 | /** 31 | * Returns the timestamp from when this snapshot was created. 32 | */ 33 | long getTimestamp(); 34 | 35 | /** 36 | * Returns the read pointer at the time of the snapshot. 37 | */ 38 | long getReadPointer(); 39 | 40 | /** 41 | * Returns the next write pointer at the time of the snapshot. 42 | */ 43 | long getWritePointer(); 44 | 45 | /** 46 | * Returns the list of invalid write pointers at the time of the snapshot. 47 | */ 48 | Collection getInvalid(); 49 | 50 | /** 51 | * Returns the map of write pointers to in-progress transactions at the time of the snapshot. 52 | */ 53 | NavigableMap getInProgress(); 54 | 55 | /** 56 | * @return transaction id {@code X} such that any of the transactions newer than {@code X} might be invisible to 57 | * some of the currently in-progress transactions or to those that will be started

58 | * NOTE: the returned tx id can be invalid. 59 | */ 60 | long getVisibilityUpperBound(); 61 | } 62 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/persist/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | /** 18 | * This package contains interfaces and implementations for persisting transaction state. 19 | */ 20 | package co.cask.tephra.persist; 21 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/rpc/RPCServiceHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package co.cask.tephra.rpc; 17 | 18 | /** 19 | * Defines lifecycle interface for all rpc handlers. 20 | */ 21 | public interface RPCServiceHandler { 22 | 23 | void init() throws Exception; 24 | 25 | void destroy() throws Exception; 26 | } 27 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/rpc/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | /** 17 | * This package contains class for writing RPC server and client in simple manner. 18 | */ 19 | package co.cask.tephra.rpc; 20 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/runtime/ConfigModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.runtime; 18 | 19 | import com.google.inject.AbstractModule; 20 | import org.apache.hadoop.conf.Configuration; 21 | 22 | /** 23 | * Provides Guice bindings for {@link Configuration}. 24 | */ 25 | public final class ConfigModule extends AbstractModule { 26 | 27 | private final Configuration configuration; 28 | 29 | public ConfigModule(Configuration configuration) { 30 | this.configuration = configuration; 31 | } 32 | 33 | @Override 34 | protected void configure() { 35 | bind(Configuration.class).toInstance(configuration); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/runtime/DiscoveryModules.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.runtime; 18 | 19 | import com.google.inject.AbstractModule; 20 | import com.google.inject.Module; 21 | import com.google.inject.PrivateModule; 22 | import com.google.inject.Provides; 23 | import com.google.inject.Singleton; 24 | import org.apache.twill.common.Cancellable; 25 | import org.apache.twill.discovery.Discoverable; 26 | import org.apache.twill.discovery.DiscoveryService; 27 | import org.apache.twill.discovery.DiscoveryServiceClient; 28 | import org.apache.twill.discovery.InMemoryDiscoveryService; 29 | import org.apache.twill.discovery.ServiceDiscovered; 30 | import org.apache.twill.discovery.ZKDiscoveryService; 31 | import org.apache.twill.zookeeper.ZKClientService; 32 | 33 | /** 34 | * Provides access to Google Guice modules for in-memory, single-node, and distributed operation for 35 | * {@link DiscoveryService} and {@link DiscoveryServiceClient}. 36 | */ 37 | public final class DiscoveryModules { 38 | 39 | public Module getInMemoryModules() { 40 | return new InMemoryDiscoveryModule(); 41 | } 42 | 43 | public Module getSingleNodeModules() { 44 | return new InMemoryDiscoveryModule(); 45 | } 46 | 47 | public Module getDistributedModules() { 48 | return new ZKDiscoveryModule(); 49 | } 50 | 51 | private static final class InMemoryDiscoveryModule extends AbstractModule { 52 | 53 | // ensuring to be singleton across JVM 54 | private static final InMemoryDiscoveryService IN_MEMORY_DISCOVERY_SERVICE = new InMemoryDiscoveryService(); 55 | 56 | @Override 57 | protected void configure() { 58 | InMemoryDiscoveryService discovery = IN_MEMORY_DISCOVERY_SERVICE; 59 | bind(DiscoveryService.class).toInstance(discovery); 60 | bind(DiscoveryServiceClient.class).toInstance(discovery); 61 | } 62 | } 63 | 64 | private static final class ZKDiscoveryModule extends PrivateModule { 65 | 66 | @Override 67 | protected void configure() { 68 | expose(DiscoveryService.class); 69 | expose(DiscoveryServiceClient.class); 70 | } 71 | 72 | @Provides 73 | @Singleton 74 | private ZKDiscoveryService providesZKDiscoveryService(ZKClientService zkClient) { 75 | return new ZKDiscoveryService(zkClient); 76 | } 77 | 78 | @Provides 79 | @Singleton 80 | private DiscoveryService providesDiscoveryService(final ZKClientService zkClient, 81 | final ZKDiscoveryService delegate) { 82 | return new DiscoveryService() { 83 | @Override 84 | public Cancellable register(Discoverable discoverable) { 85 | if (!zkClient.isRunning()) { 86 | zkClient.startAndWait(); 87 | } 88 | return delegate.register(discoverable); 89 | } 90 | }; 91 | } 92 | 93 | @Provides 94 | @Singleton 95 | private DiscoveryServiceClient providesDiscoveryServiceClient(final ZKClientService zkClient, 96 | final ZKDiscoveryService delegate) { 97 | return new DiscoveryServiceClient() { 98 | @Override 99 | public ServiceDiscovered discover(String s) { 100 | if (!zkClient.isRunning()) { 101 | zkClient.startAndWait(); 102 | } 103 | return delegate.discover(s); 104 | } 105 | }; 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/runtime/TransactionClientModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.runtime; 18 | 19 | import co.cask.tephra.TxConstants; 20 | import co.cask.tephra.distributed.PooledClientProvider; 21 | import co.cask.tephra.distributed.ThreadLocalClientProvider; 22 | import co.cask.tephra.distributed.ThriftClientProvider; 23 | import com.google.inject.AbstractModule; 24 | import com.google.inject.Inject; 25 | import com.google.inject.Provider; 26 | import com.google.inject.Singleton; 27 | import org.apache.hadoop.conf.Configuration; 28 | import org.apache.twill.discovery.DiscoveryServiceClient; 29 | 30 | /** 31 | * Provides Guice binding for {@link co.cask.tephra.distributed.ThriftClientProvider}. 32 | */ 33 | public class TransactionClientModule extends AbstractModule { 34 | 35 | @Override 36 | protected void configure() { 37 | bind(ThriftClientProvider.class).toProvider(ThriftClientProviderSupplier.class); 38 | } 39 | 40 | /** 41 | * Provides implementation of {@link co.cask.tephra.distributed.ThriftClientProvider} 42 | * based on configuration. 43 | */ 44 | @Singleton 45 | private static final class ThriftClientProviderSupplier implements Provider { 46 | 47 | private final Configuration cConf; 48 | private DiscoveryServiceClient discoveryServiceClient; 49 | 50 | @Inject 51 | ThriftClientProviderSupplier(Configuration cConf) { 52 | this.cConf = cConf; 53 | } 54 | 55 | @Inject(optional = true) 56 | void setDiscoveryServiceClient(DiscoveryServiceClient discoveryServiceClient) { 57 | this.discoveryServiceClient = discoveryServiceClient; 58 | } 59 | 60 | @Override 61 | public ThriftClientProvider get() { 62 | // configure the client provider 63 | String provider = cConf.get(TxConstants.Service.CFG_DATA_TX_CLIENT_PROVIDER, 64 | TxConstants.Service.DEFAULT_DATA_TX_CLIENT_PROVIDER); 65 | ThriftClientProvider clientProvider; 66 | if ("pool".equals(provider)) { 67 | clientProvider = new PooledClientProvider(cConf, discoveryServiceClient); 68 | } else if ("thread-local".equals(provider)) { 69 | clientProvider = new ThreadLocalClientProvider(cConf, discoveryServiceClient); 70 | } else { 71 | String message = "Unknown Transaction Service Client Provider '" + provider + "'."; 72 | throw new IllegalArgumentException(message); 73 | } 74 | return clientProvider; 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/runtime/TransactionDistributedModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.runtime; 18 | 19 | import co.cask.tephra.DefaultTransactionExecutor; 20 | import co.cask.tephra.TransactionExecutor; 21 | import co.cask.tephra.TransactionExecutorFactory; 22 | import co.cask.tephra.TransactionManager; 23 | import co.cask.tephra.TransactionSystemClient; 24 | import co.cask.tephra.distributed.TransactionServiceClient; 25 | import co.cask.tephra.metrics.DefaultMetricsCollector; 26 | import co.cask.tephra.metrics.MetricsCollector; 27 | import co.cask.tephra.persist.HDFSTransactionStateStorage; 28 | import co.cask.tephra.persist.TransactionStateStorage; 29 | import co.cask.tephra.snapshot.SnapshotCodecProvider; 30 | import com.google.inject.AbstractModule; 31 | import com.google.inject.Singleton; 32 | import com.google.inject.assistedinject.FactoryModuleBuilder; 33 | import com.google.inject.name.Names; 34 | 35 | /** 36 | * Guice bindings for running in distributed mode on a cluster. 37 | */ 38 | final class TransactionDistributedModule extends AbstractModule { 39 | 40 | @Override 41 | protected void configure() { 42 | bind(SnapshotCodecProvider.class).in(Singleton.class); 43 | bind(TransactionStateStorage.class).annotatedWith(Names.named("persist")) 44 | .to(HDFSTransactionStateStorage.class).in(Singleton.class); 45 | bind(TransactionStateStorage.class).toProvider(TransactionStateStorageProvider.class).in(Singleton.class); 46 | 47 | bind(TransactionManager.class).in(Singleton.class); 48 | bind(TransactionSystemClient.class).to(TransactionServiceClient.class).in(Singleton.class); 49 | bind(MetricsCollector.class).to(DefaultMetricsCollector.class).in(Singleton.class); 50 | 51 | install(new FactoryModuleBuilder() 52 | .implement(TransactionExecutor.class, DefaultTransactionExecutor.class) 53 | .build(TransactionExecutorFactory.class)); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/runtime/TransactionInMemoryModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.runtime; 18 | 19 | import co.cask.tephra.DefaultTransactionExecutor; 20 | import co.cask.tephra.TransactionExecutor; 21 | import co.cask.tephra.TransactionExecutorFactory; 22 | import co.cask.tephra.TransactionManager; 23 | import co.cask.tephra.TransactionSystemClient; 24 | import co.cask.tephra.inmemory.InMemoryTxSystemClient; 25 | import co.cask.tephra.metrics.MetricsCollector; 26 | import co.cask.tephra.metrics.TxMetricsCollector; 27 | import co.cask.tephra.persist.NoOpTransactionStateStorage; 28 | import co.cask.tephra.persist.TransactionStateStorage; 29 | import co.cask.tephra.snapshot.SnapshotCodecProvider; 30 | 31 | import com.google.inject.AbstractModule; 32 | import com.google.inject.Singleton; 33 | import com.google.inject.assistedinject.FactoryModuleBuilder; 34 | 35 | /** 36 | * Guice bindings for running completely in-memory (no persistence). This should only be used for 37 | * test classes, as the transaction state cannot be recovered in the case of a failure. 38 | */ 39 | public class TransactionInMemoryModule extends AbstractModule { 40 | public TransactionInMemoryModule() { 41 | } 42 | 43 | @Override 44 | protected void configure() { 45 | bind(SnapshotCodecProvider.class).in(Singleton.class); 46 | bind(TransactionStateStorage.class).to(NoOpTransactionStateStorage.class).in(Singleton.class); 47 | bind(TransactionManager.class).in(Singleton.class); 48 | bind(TransactionSystemClient.class).to(InMemoryTxSystemClient.class).in(Singleton.class); 49 | // no metrics output for in-memory 50 | bind(MetricsCollector.class).to(TxMetricsCollector.class); 51 | 52 | install(new FactoryModuleBuilder() 53 | .implement(TransactionExecutor.class, DefaultTransactionExecutor.class) 54 | .build(TransactionExecutorFactory.class)); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/runtime/TransactionLocalModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.runtime; 18 | 19 | import co.cask.tephra.DefaultTransactionExecutor; 20 | import co.cask.tephra.TransactionExecutor; 21 | import co.cask.tephra.TransactionExecutorFactory; 22 | import co.cask.tephra.TransactionManager; 23 | import co.cask.tephra.TransactionSystemClient; 24 | import co.cask.tephra.inmemory.InMemoryTxSystemClient; 25 | import co.cask.tephra.metrics.DefaultMetricsCollector; 26 | import co.cask.tephra.metrics.MetricsCollector; 27 | import co.cask.tephra.persist.LocalFileTransactionStateStorage; 28 | import co.cask.tephra.persist.TransactionStateStorage; 29 | import co.cask.tephra.snapshot.SnapshotCodecProvider; 30 | 31 | import com.google.inject.AbstractModule; 32 | import com.google.inject.Singleton; 33 | import com.google.inject.assistedinject.FactoryModuleBuilder; 34 | import com.google.inject.name.Names; 35 | 36 | /** 37 | * Guice bindings for running in single-node mode (persistence to local disk and in-memory client). 38 | */ 39 | final class TransactionLocalModule extends AbstractModule { 40 | 41 | @Override 42 | protected void configure() { 43 | bind(SnapshotCodecProvider.class).in(Singleton.class); 44 | bind(TransactionStateStorage.class).annotatedWith(Names.named("persist")) 45 | .to(LocalFileTransactionStateStorage.class).in(Singleton.class); 46 | bind(TransactionStateStorage.class).toProvider(TransactionStateStorageProvider.class).in(Singleton.class); 47 | 48 | bind(TransactionManager.class).in(Singleton.class); 49 | bind(TransactionSystemClient.class).to(InMemoryTxSystemClient.class).in(Singleton.class); 50 | bind(MetricsCollector.class).to(DefaultMetricsCollector.class); 51 | 52 | install(new FactoryModuleBuilder() 53 | .implement(TransactionExecutor.class, DefaultTransactionExecutor.class) 54 | .build(TransactionExecutorFactory.class)); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/runtime/TransactionModules.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.runtime; 18 | 19 | import com.google.inject.Module; 20 | 21 | /** 22 | * Provides access to Google Guice modules for in-memory, single-node, and distributed operation. 23 | */ 24 | public class TransactionModules { 25 | public TransactionModules() { 26 | } 27 | 28 | public Module getInMemoryModules() { 29 | return new TransactionInMemoryModule(); 30 | } 31 | 32 | public Module getSingleNodeModules() { 33 | return new TransactionLocalModule(); 34 | } 35 | 36 | public Module getDistributedModules() { 37 | return new TransactionDistributedModule(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/runtime/TransactionStateStorageProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package co.cask.tephra.runtime; 17 | 18 | import co.cask.tephra.TxConstants; 19 | import co.cask.tephra.persist.NoOpTransactionStateStorage; 20 | import co.cask.tephra.persist.TransactionStateStorage; 21 | import com.google.inject.Inject; 22 | import com.google.inject.Injector; 23 | import com.google.inject.Key; 24 | import com.google.inject.Provider; 25 | import com.google.inject.Singleton; 26 | import com.google.inject.name.Names; 27 | import org.apache.hadoop.conf.Configuration; 28 | 29 | /** 30 | * A provider for {@link TransactionStateStorage} that provides different 31 | * {@link TransactionStateStorage} implementation based on configuration. 32 | */ 33 | @Singleton 34 | public final class TransactionStateStorageProvider implements Provider { 35 | 36 | private final Configuration cConf; 37 | private final Injector injector; 38 | 39 | @Inject 40 | TransactionStateStorageProvider(Configuration cConf, Injector injector) { 41 | this.cConf = cConf; 42 | this.injector = injector; 43 | } 44 | 45 | @Override 46 | public TransactionStateStorage get() { 47 | if (cConf.getBoolean(TxConstants.Manager.CFG_DO_PERSIST, true)) { 48 | return injector.getInstance(Key.get(TransactionStateStorage.class, Names.named("persist"))); 49 | } else { 50 | return injector.getInstance(NoOpTransactionStateStorage.class); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/runtime/ZKModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.runtime; 18 | 19 | import co.cask.tephra.TxConstants; 20 | import co.cask.tephra.zookeeper.TephraZKClientService; 21 | import com.google.common.collect.ArrayListMultimap; 22 | import com.google.inject.AbstractModule; 23 | import com.google.inject.Provides; 24 | import com.google.inject.Singleton; 25 | import org.apache.hadoop.conf.Configuration; 26 | import org.apache.twill.zookeeper.RetryStrategies; 27 | import org.apache.twill.zookeeper.ZKClient; 28 | import org.apache.twill.zookeeper.ZKClientService; 29 | import org.apache.twill.zookeeper.ZKClientServices; 30 | import org.apache.twill.zookeeper.ZKClients; 31 | 32 | import java.util.concurrent.TimeUnit; 33 | 34 | /** 35 | * Provides Guice binding to {@link ZKClient} and {@link ZKClientService}. 36 | */ 37 | public class ZKModule extends AbstractModule { 38 | 39 | @Override 40 | protected void configure() { 41 | /** 42 | * ZKClientService is provided by the provider method 43 | * {@link #provideZKClientService(org.apache.hadoop.conf.Configuration)}. 44 | */ 45 | bind(ZKClient.class).to(ZKClientService.class); 46 | } 47 | 48 | @Provides 49 | @Singleton 50 | private ZKClientService provideZKClientService(Configuration conf) { 51 | String zkStr = conf.get(TxConstants.Service.CFG_DATA_TX_ZOOKEEPER_QUORUM); 52 | if (zkStr == null) { 53 | // Default to HBase one. 54 | zkStr = conf.get(TxConstants.HBase.ZOOKEEPER_QUORUM); 55 | } 56 | 57 | int timeOut = conf.getInt(TxConstants.HBase.ZK_SESSION_TIMEOUT, TxConstants.HBase.DEFAULT_ZK_SESSION_TIMEOUT); 58 | ZKClientService zkClientService = new TephraZKClientService(zkStr, timeOut, null, 59 | ArrayListMultimap.create()); 60 | return ZKClientServices.delegate( 61 | ZKClients.reWatchOnExpire( 62 | ZKClients.retryOnFailure(zkClientService, RetryStrategies.exponentialDelay(500, 2000, TimeUnit.MILLISECONDS) 63 | ) 64 | ) 65 | ); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/snapshot/BinaryDecoder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.snapshot; 18 | 19 | import java.io.EOFException; 20 | import java.io.IOException; 21 | import java.io.InputStream; 22 | 23 | /** 24 | * An decoder to help read snapshots in binary format. 25 | */ 26 | public final class BinaryDecoder { 27 | 28 | private final InputStream input; 29 | 30 | /** 31 | * @param input Stream to read from. 32 | */ 33 | public BinaryDecoder(InputStream input) { 34 | this.input = input; 35 | } 36 | 37 | /** 38 | * Read one int from the input. 39 | * @return the read number 40 | * @throws java.io.IOException If there is IO error. 41 | * @throws java.io.EOFException If end of file reached. 42 | */ 43 | public int readInt() throws IOException { 44 | int val = 0; 45 | int shift = 0; 46 | int b = readByte(); 47 | while (b > 0x7f) { 48 | val ^= (b & 0x7f) << shift; 49 | shift += 7; 50 | b = readByte(); 51 | } 52 | val ^= b << shift; 53 | return (val >>> 1) ^ -(val & 1); 54 | } 55 | 56 | /** 57 | * Read one long int from the input. 58 | * @return the read number 59 | * @throws java.io.IOException If there is IO error. 60 | * @throws java.io.EOFException If end of file reached. 61 | */ 62 | public long readLong() throws IOException { 63 | long val = 0; 64 | int shift = 0; 65 | int b = readByte(); 66 | while (b > 0x7f) { 67 | val ^= (long) (b & 0x7f) << shift; 68 | shift += 7; 69 | b = readByte(); 70 | } 71 | val ^= (long) b << shift; 72 | return (val >>> 1) ^ -(val & 1); 73 | } 74 | 75 | /** 76 | * Read a byte sequence. First read an int to indicate how many bytes to read, then that many bytes. 77 | * @return the read bytes as a byte array 78 | * @throws java.io.IOException If there is IO error. 79 | * @throws java.io.EOFException If end of file reached. 80 | */ 81 | public byte[] readBytes() throws IOException { 82 | int toRead = readInt(); 83 | byte[] bytes = new byte[toRead]; 84 | while (toRead > 0) { 85 | int byteRead = input.read(bytes, bytes.length - toRead, toRead); 86 | if (byteRead == -1) { 87 | throw new EOFException(); 88 | } 89 | toRead -= byteRead; 90 | } 91 | return bytes; 92 | } 93 | 94 | /** 95 | * Reads a single byte value. 96 | * 97 | * @return The byte value read. 98 | * @throws java.io.IOException If there is IO error. 99 | * @throws java.io.EOFException If end of file reached. 100 | */ 101 | private int readByte() throws IOException { 102 | int b = input.read(); 103 | if (b == -1) { 104 | throw new EOFException(); 105 | } 106 | return b; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/snapshot/BinaryEncoder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.snapshot; 18 | 19 | import java.io.IOException; 20 | import java.io.OutputStream; 21 | 22 | /** 23 | * An encoder to help encode snapshots in binary format. 24 | */ 25 | public final class BinaryEncoder { 26 | 27 | private final OutputStream output; 28 | 29 | /** 30 | * @param output stream to write to 31 | */ 32 | public BinaryEncoder(OutputStream output) { 33 | this.output = output; 34 | } 35 | 36 | /** 37 | * write a single int value. 38 | * @throws java.io.IOException If there is IO error. 39 | */ 40 | public BinaryEncoder writeInt(int i) throws IOException { 41 | // Compute the zig-zag value. First double the value and flip the bit if the input is negative. 42 | int val = (i << 1) ^ (i >> 31); 43 | 44 | if ((val & ~0x7f) != 0) { 45 | output.write(0x80 | val & 0x7f); 46 | val >>>= 7; 47 | while (val > 0x7f) { 48 | output.write(0x80 | val & 0x7f); 49 | val >>>= 7; 50 | } 51 | } 52 | output.write(val); 53 | 54 | return this; 55 | } 56 | 57 | /** 58 | * write a single long int value. 59 | * @throws java.io.IOException If there is IO error. 60 | */ 61 | public BinaryEncoder writeLong(long l) throws IOException { 62 | // Compute the zig-zag value. First double the value and flip the bit if the input is negative. 63 | long val = (l << 1) ^ (l >> 63); 64 | 65 | if ((val & ~0x7f) != 0) { 66 | output.write((int) (0x80 | val & 0x7f)); 67 | val >>>= 7; 68 | while (val > 0x7f) { 69 | output.write((int) (0x80 | val & 0x7f)); 70 | val >>>= 7; 71 | } 72 | } 73 | output.write((int) val); 74 | 75 | return this; 76 | } 77 | 78 | /** 79 | * write a sequence of bytes. First writes the number of bytes as an int, then the bytes themselves. 80 | * @throws java.io.IOException If there is IO error. 81 | */ 82 | public BinaryEncoder writeBytes(byte[] bytes) throws IOException { 83 | writeLong(bytes.length); 84 | output.write(bytes, 0, bytes.length); 85 | return this; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/snapshot/SnapshotCodec.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.snapshot; 18 | 19 | import co.cask.tephra.persist.TransactionSnapshot; 20 | import co.cask.tephra.persist.TransactionVisibilityState; 21 | 22 | import java.io.InputStream; 23 | import java.io.OutputStream; 24 | 25 | /** 26 | * Interface to decode and encode a transaction snapshot. Each codec implements one version of the encoding. 27 | * It need not include the version when encoding the snapshot. 28 | */ 29 | public interface SnapshotCodec { 30 | 31 | /** 32 | * @return the version of the encoding implemented by the codec. 33 | */ 34 | int getVersion(); 35 | 36 | /** 37 | * Encode a transaction snapshot into an output stream. 38 | * @param out the output stream to write to 39 | * @param snapshot the snapshot to encode 40 | */ 41 | void encode(OutputStream out, TransactionSnapshot snapshot); 42 | 43 | /** 44 | * Decode a transaction snapshot from an input stream. 45 | * @param in the input stream to read from 46 | * @return the decoded snapshot 47 | */ 48 | TransactionSnapshot decode(InputStream in); 49 | 50 | /** 51 | * Decode transaction visibility state from an input stream. 52 | * @param in the input stream to read from 53 | * @return {@link TransactionVisibilityState} 54 | */ 55 | TransactionVisibilityState decodeTransactionVisibilityState(InputStream in); 56 | } 57 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/snapshot/SnapshotCodecV2.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.snapshot; 18 | 19 | import co.cask.tephra.TransactionManager; 20 | import co.cask.tephra.TransactionType; 21 | import com.google.common.collect.Maps; 22 | import it.unimi.dsi.fastutil.longs.LongArrayList; 23 | 24 | import java.io.IOException; 25 | import java.util.Map; 26 | import java.util.NavigableMap; 27 | 28 | /** 29 | * Handles serialization/deserialization of a {@link co.cask.tephra.persist.TransactionSnapshot} 30 | * and its elements to {@code byte[]}. 31 | */ 32 | public class SnapshotCodecV2 extends DefaultSnapshotCodec { 33 | @Override 34 | public int getVersion() { 35 | return 2; 36 | } 37 | 38 | @Override 39 | protected void encodeInProgress(BinaryEncoder encoder, Map inProgress) 40 | throws IOException { 41 | 42 | if (!inProgress.isEmpty()) { 43 | encoder.writeInt(inProgress.size()); 44 | for (Map.Entry entry : inProgress.entrySet()) { 45 | encoder.writeLong(entry.getKey()); // tx id 46 | encoder.writeLong(entry.getValue().getExpiration()); 47 | encoder.writeLong(entry.getValue().getVisibilityUpperBound()); 48 | encoder.writeInt(entry.getValue().getType().ordinal()); 49 | } 50 | } 51 | encoder.writeInt(0); // zero denotes end of list as per AVRO spec 52 | } 53 | 54 | @Override 55 | protected NavigableMap decodeInProgress(BinaryDecoder decoder) 56 | throws IOException { 57 | 58 | int size = decoder.readInt(); 59 | NavigableMap inProgress = Maps.newTreeMap(); 60 | while (size != 0) { // zero denotes end of list as per AVRO spec 61 | for (int remaining = size; remaining > 0; --remaining) { 62 | long txId = decoder.readLong(); 63 | long expiration = decoder.readLong(); 64 | long visibilityUpperBound = decoder.readLong(); 65 | int txTypeIdx = decoder.readInt(); 66 | TransactionType txType; 67 | try { 68 | txType = TransactionType.values()[txTypeIdx]; 69 | } catch (ArrayIndexOutOfBoundsException e) { 70 | throw new IOException("Type enum ordinal value is out of range: " + txTypeIdx); 71 | } 72 | inProgress.put(txId, 73 | new TransactionManager.InProgressTx(visibilityUpperBound, expiration, txType, 74 | new LongArrayList())); 75 | } 76 | size = decoder.readInt(); 77 | } 78 | return inProgress; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/snapshot/SnapshotCodecV3.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.snapshot; 18 | 19 | /** 20 | * Handles serialization/deserialization of a {@link co.cask.tephra.persist.TransactionSnapshot} 21 | * and its elements to {@code byte[]}. 22 | * 23 | *

The serialization/deserialization of this codec is the same as that performed by {@link SnapshotCodecV2}, 24 | * but a new version number is used to allow easy migration from projects using deprecated codecs with 25 | * conflicting version numbers.

26 | */ 27 | public class SnapshotCodecV3 extends SnapshotCodecV2 { 28 | @Override 29 | public int getVersion() { 30 | return 3; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/snapshot/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | /** 18 | * This package contains interfaces and implementations for encoding and decoding transaction snapshots. 19 | */ 20 | package co.cask.tephra.snapshot; 21 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/util/ConfigurationFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.util; 18 | 19 | import com.google.inject.Provider; 20 | import org.apache.hadoop.conf.Configuration; 21 | 22 | /** 23 | * Provides {@code org.apache.hadoop.conf.Configuration} instances, constructed by the correct version used 24 | * for the runtime. 25 | */ 26 | public class ConfigurationFactory implements Provider { 27 | private static class ConfigurationProviderFactory extends HBaseVersionSpecificFactory { 28 | @Override 29 | protected String getHBase96Classname() { 30 | return "co.cask.tephra.hbase96.HBase96ConfigurationProvider"; 31 | } 32 | 33 | @Override 34 | protected String getHBase98Classname() { 35 | return "co.cask.tephra.hbase98.HBase98ConfigurationProvider"; 36 | } 37 | 38 | @Override 39 | protected String getHBase10Classname() { 40 | return "co.cask.tephra.hbase10.HBase10ConfigurationProvider"; 41 | } 42 | 43 | @Override 44 | protected String getHBase11Classname() { 45 | return "co.cask.tephra.hbase11.HBase11ConfigurationProvider"; 46 | } 47 | 48 | @Override 49 | protected String getHBase10CDHClassname() { 50 | return "co.cask.tephra.hbase10cdh.HBase10ConfigurationProvider"; 51 | } 52 | } 53 | 54 | private final ConfigurationProvider provider = new ConfigurationProviderFactory().get(); 55 | 56 | /** 57 | * Returns a new {@link org.apache.hadoop.conf.Configuration} instance from the HBase version-specific factory. 58 | */ 59 | @Override 60 | public Configuration get() { 61 | return provider.get(); 62 | } 63 | 64 | /** 65 | * Returns a new {@link org.apache.hadoop.conf.Configuration} instance from the HBase version-specific factory. 66 | * 67 | * @param baseConf additional configuration properties to merge on to the classpath configuration 68 | * @return the merged configuration 69 | */ 70 | public Configuration get(Configuration baseConf) { 71 | return provider.get(baseConf); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/util/ConfigurationProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.util; 18 | 19 | import com.google.inject.Provider; 20 | import org.apache.hadoop.conf.Configuration; 21 | 22 | /** 23 | * Provides {@code Configuration} instances, constructed by the HBase version on which we are running. 24 | */ 25 | public abstract class ConfigurationProvider implements Provider { 26 | @Override 27 | public abstract Configuration get(); 28 | 29 | public abstract Configuration get(Configuration baseConf); 30 | } 31 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/util/HBaseVersionSpecificFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015-2016 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.util; 18 | 19 | import com.google.inject.Provider; 20 | import com.google.inject.ProvisionException; 21 | import org.apache.twill.internal.utils.Instances; 22 | 23 | /** 24 | * Common class factory behavior for classes which need specific implementations depending on HBase versions. 25 | * Specific factories can subclass this class and simply plug in the class names for their implementations. 26 | * 27 | * @param Version specific class provided by this factory. 28 | */ 29 | public abstract class HBaseVersionSpecificFactory implements Provider { 30 | @Override 31 | public T get() { 32 | T instance = null; 33 | try { 34 | switch (HBaseVersion.get()) { 35 | case HBASE_94: 36 | throw new ProvisionException("HBase 0.94 is no longer supported. Please upgrade to HBase 0.96 or newer."); 37 | case HBASE_96: 38 | instance = createInstance(getHBase96Classname()); 39 | break; 40 | case HBASE_98: 41 | instance = createInstance(getHBase98Classname()); 42 | break; 43 | case HBASE_10: 44 | instance = createInstance(getHBase10Classname()); 45 | break; 46 | case HBASE_10_CDH: 47 | instance = createInstance(getHBase10CDHClassname()); 48 | break; 49 | case HBASE_11: 50 | case HBASE_12_CDH: 51 | instance = createInstance(getHBase11Classname()); 52 | break; 53 | case UNKNOWN: 54 | throw new ProvisionException("Unknown HBase version: " + HBaseVersion.getVersionString()); 55 | } 56 | } catch (ClassNotFoundException cnfe) { 57 | throw new ProvisionException(cnfe.getMessage(), cnfe); 58 | } 59 | return instance; 60 | } 61 | 62 | protected T createInstance(String className) throws ClassNotFoundException { 63 | Class clz = Class.forName(className); 64 | return (T) Instances.newInstance(clz); 65 | } 66 | 67 | protected abstract String getHBase96Classname(); 68 | protected abstract String getHBase98Classname(); 69 | protected abstract String getHBase10Classname(); 70 | protected abstract String getHBase10CDHClassname(); 71 | protected abstract String getHBase11Classname(); 72 | } 73 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/visibility/DefaultFenceWait.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2016 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.visibility; 18 | 19 | import co.cask.tephra.TransactionContext; 20 | import co.cask.tephra.TransactionFailureException; 21 | import com.google.common.base.Stopwatch; 22 | import org.slf4j.Logger; 23 | import org.slf4j.LoggerFactory; 24 | 25 | import java.util.concurrent.TimeUnit; 26 | import java.util.concurrent.TimeoutException; 27 | 28 | /** 29 | * Default implementation of {@link FenceWait}. 30 | */ 31 | public class DefaultFenceWait implements FenceWait { 32 | private static final Logger LOG = LoggerFactory.getLogger(DefaultFenceWait.class); 33 | 34 | private final TransactionContext txContext; 35 | 36 | DefaultFenceWait(TransactionContext txContext) { 37 | this.txContext = txContext; 38 | } 39 | 40 | @Override 41 | public void await(long timeout, TimeUnit timeUnit) 42 | throws TransactionFailureException, InterruptedException, TimeoutException { 43 | Stopwatch stopwatch = new Stopwatch(); 44 | stopwatch.start(); 45 | long sleepTimeMicros = timeUnit.toMicros(timeout) / 10; 46 | // Have sleep time to be within 1 microsecond and 500 milliseconds 47 | sleepTimeMicros = Math.max(Math.min(sleepTimeMicros, 500 * 1000), 1); 48 | while (stopwatch.elapsedTime(timeUnit) < timeout) { 49 | txContext.start(); 50 | try { 51 | txContext.finish(); 52 | return; 53 | } catch (TransactionFailureException e) { 54 | LOG.error("Got exception waiting for fence. Sleeping for {} microseconds", sleepTimeMicros, e); 55 | txContext.abort(); 56 | TimeUnit.MICROSECONDS.sleep(sleepTimeMicros); 57 | } 58 | } 59 | throw new TimeoutException("Timeout waiting for fence"); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/visibility/FenceWait.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2016 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.visibility; 18 | 19 | import co.cask.tephra.TransactionFailureException; 20 | 21 | import java.util.concurrent.TimeUnit; 22 | import java.util.concurrent.TimeoutException; 23 | 24 | /** 25 | * Used by a writer to wait on a fence so that changes are visible to all readers with in-progress transactions. 26 | */ 27 | public interface FenceWait { 28 | /** 29 | * Waits until the fence is complete, or till the timeout specified. The fence wait transaction will get re-tried 30 | * several times until the timeout. 31 | *

32 | * 33 | * If a fence wait times out then it means there are still some readers with in-progress transactions that have not 34 | * seen the change. In this case the wait will have to be retried using the same FenceWait object. 35 | * 36 | * @param timeout Maximum time to wait 37 | * @param timeUnit {@link TimeUnit} for timeout and sleepTime 38 | * @throws TransactionFailureException when not able to start fence wait transaction 39 | * @throws InterruptedException on any interrupt 40 | * @throws TimeoutException when timeout is reached 41 | */ 42 | void await(long timeout, TimeUnit timeUnit) 43 | throws TransactionFailureException, InterruptedException, TimeoutException; 44 | } 45 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/visibility/ReadFence.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.visibility; 18 | 19 | import co.cask.tephra.Transaction; 20 | import co.cask.tephra.TransactionAware; 21 | import com.google.common.primitives.Bytes; 22 | import com.google.common.primitives.Longs; 23 | 24 | import java.util.Collection; 25 | import java.util.Collections; 26 | 27 | /** 28 | * Implementation of {@link VisibilityFence} used by reader. 29 | */ 30 | class ReadFence implements TransactionAware { 31 | private final byte[] fenceId; 32 | private Transaction tx; 33 | 34 | public ReadFence(byte[] fenceId) { 35 | this.fenceId = fenceId; 36 | } 37 | 38 | @Override 39 | public void startTx(Transaction tx) { 40 | this.tx = tx; 41 | } 42 | 43 | @Override 44 | public void updateTx(Transaction tx) { 45 | // Fences only need original transaction 46 | } 47 | 48 | @Override 49 | public Collection getTxChanges() { 50 | if (tx == null) { 51 | throw new IllegalStateException("Transaction has not started yet"); 52 | } 53 | return Collections.singleton(Bytes.concat(fenceId, Longs.toByteArray(tx.getTransactionId()))); 54 | } 55 | 56 | @Override 57 | public boolean commitTx() throws Exception { 58 | // Nothing to persist 59 | return true; 60 | } 61 | 62 | @Override 63 | public void postTxCommit() { 64 | tx = null; 65 | } 66 | 67 | @Override 68 | public boolean rollbackTx() throws Exception { 69 | // Nothing to rollback 70 | return true; 71 | } 72 | 73 | @Override 74 | public String getTransactionAwareName() { 75 | return getClass().getSimpleName(); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/visibility/WriteFence.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.visibility; 18 | 19 | import co.cask.tephra.Transaction; 20 | import co.cask.tephra.TransactionAware; 21 | import com.google.common.primitives.Bytes; 22 | import com.google.common.primitives.Longs; 23 | import com.google.common.primitives.UnsignedBytes; 24 | 25 | import java.util.Collection; 26 | import java.util.TreeSet; 27 | 28 | /** 29 | * Implementation used by {@link FenceWait} to wait for a {@link VisibilityFence}. 30 | */ 31 | class WriteFence implements TransactionAware { 32 | private final byte[] fenceId; 33 | private Transaction tx; 34 | private Collection inProgressChanges; 35 | 36 | public WriteFence(byte[] fenceId) { 37 | this.fenceId = fenceId; 38 | } 39 | 40 | @Override 41 | public void startTx(Transaction tx) { 42 | this.tx = tx; 43 | if (inProgressChanges == null) { 44 | inProgressChanges = new TreeSet<>(UnsignedBytes.lexicographicalComparator()); 45 | for (long inProgressTx : tx.getInProgress()) { 46 | inProgressChanges.add(Bytes.concat(fenceId, Longs.toByteArray(inProgressTx))); 47 | } 48 | } 49 | } 50 | 51 | @Override 52 | public void updateTx(Transaction tx) { 53 | // Fences only need original transaction 54 | } 55 | 56 | @Override 57 | public Collection getTxChanges() { 58 | if (inProgressChanges == null || tx == null) { 59 | throw new IllegalStateException("Transaction has not started yet"); 60 | } 61 | return inProgressChanges; 62 | } 63 | 64 | @Override 65 | public boolean commitTx() throws Exception { 66 | // Nothing to persist 67 | return true; 68 | } 69 | 70 | @Override 71 | public void postTxCommit() { 72 | tx = null; 73 | } 74 | 75 | @Override 76 | public boolean rollbackTx() throws Exception { 77 | // Nothing to rollback 78 | return true; 79 | } 80 | 81 | @Override 82 | public String getTransactionAwareName() { 83 | return getClass().getSimpleName(); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/zookeeper/BasicACLData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2016 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.zookeeper; 18 | 19 | import org.apache.twill.zookeeper.ACLData; 20 | import org.apache.zookeeper.data.ACL; 21 | import org.apache.zookeeper.data.Stat; 22 | 23 | import java.util.List; 24 | 25 | /** 26 | * A straightforward implementation of {@link ACLData}. 27 | */ 28 | final class BasicACLData implements ACLData { 29 | 30 | private final List acl; 31 | private final Stat stat; 32 | 33 | BasicACLData(List acl, Stat stat) { 34 | this.acl = acl; 35 | this.stat = stat; 36 | } 37 | 38 | @Override 39 | public List getACL() { 40 | return acl; 41 | } 42 | 43 | @Override 44 | public Stat getStat() { 45 | return stat; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/zookeeper/BasicNodeChildren.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2016 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.zookeeper; 18 | 19 | import com.google.common.base.Objects; 20 | import org.apache.twill.zookeeper.NodeChildren; 21 | import org.apache.zookeeper.data.Stat; 22 | 23 | import java.util.List; 24 | 25 | /** 26 | * Implementation of the {@link NodeChildren}. 27 | */ 28 | final class BasicNodeChildren implements NodeChildren { 29 | 30 | private final Stat stat; 31 | private final List children; 32 | 33 | BasicNodeChildren(List children, Stat stat) { 34 | this.stat = stat; 35 | this.children = children; 36 | } 37 | 38 | @Override 39 | public Stat getStat() { 40 | return stat; 41 | } 42 | 43 | @Override 44 | public List getChildren() { 45 | return children; 46 | } 47 | 48 | @Override 49 | public boolean equals(Object o) { 50 | if (this == o) { 51 | return true; 52 | } 53 | if (o == null || !(o instanceof NodeChildren)) { 54 | return false; 55 | } 56 | 57 | NodeChildren that = (NodeChildren) o; 58 | return stat.equals(that.getStat()) && children.equals(that.getChildren()); 59 | } 60 | 61 | @Override 62 | public int hashCode() { 63 | return Objects.hashCode(children, stat); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /tephra-core/src/main/java/co/cask/tephra/zookeeper/BasicNodeData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2016 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.zookeeper; 18 | 19 | import com.google.common.base.Objects; 20 | import org.apache.twill.zookeeper.NodeData; 21 | import org.apache.zookeeper.data.Stat; 22 | 23 | import java.util.Arrays; 24 | 25 | /** 26 | * A straightforward implementation for {@link NodeData}. 27 | */ 28 | final class BasicNodeData implements NodeData { 29 | 30 | private final byte[] data; 31 | private final Stat stat; 32 | 33 | BasicNodeData(byte[] data, Stat stat) { 34 | this.data = data; 35 | this.stat = stat; 36 | } 37 | 38 | @Override 39 | public Stat getStat() { 40 | return stat; 41 | } 42 | 43 | @Override 44 | public byte[] getData() { 45 | return data; 46 | } 47 | 48 | @Override 49 | public boolean equals(Object o) { 50 | if (this == o) { 51 | return true; 52 | } 53 | if (o == null || !(o instanceof NodeData)) { 54 | return false; 55 | } 56 | 57 | BasicNodeData that = (BasicNodeData) o; 58 | 59 | return stat.equals(that.getStat()) && Arrays.equals(data, that.getData()); 60 | } 61 | 62 | @Override 63 | public int hashCode() { 64 | return Objects.hashCode(data, stat); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /tephra-core/src/main/thrift/README: -------------------------------------------------------------------------------- 1 | # Copyright © 2014 Cask Data, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | # use this file except in compliance with the License. You may obtain a copy of 5 | # the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations under 13 | # the License. 14 | 15 | To generate thrift classes: 16 | thrift --gen java --out ../java/ transaction.thrift 17 | -------------------------------------------------------------------------------- /tephra-core/src/main/thrift/transaction.thrift: -------------------------------------------------------------------------------- 1 | # Copyright © 2012-2014 Cask Data, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | # use this file except in compliance with the License. You may obtain a copy of 5 | # the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations under 13 | # the License. 14 | 15 | namespace java co.cask.tephra.distributed.thrift 16 | 17 | enum TTransactionType { 18 | SHORT = 1, 19 | LONG = 2 20 | } 21 | 22 | enum TVisibilityLevel { 23 | SNAPSHOT = 1, 24 | SNAPSHOT_EXCLUDE_CURRENT = 2, 25 | SNAPSHOT_ALL = 3 26 | } 27 | 28 | struct TTransaction { 29 | 1: i64 transactionId, 30 | 2: i64 readPointer, 31 | 3: list invalids, 32 | 4: list inProgress, 33 | 5: i64 firstShort, 34 | 6: TTransactionType type, 35 | 7: i64 writePointer, 36 | 8: list checkpointWritePointers, 37 | 9: TVisibilityLevel visibilityLevel 38 | } 39 | 40 | exception TTransactionNotInProgressException { 41 | 1: string message 42 | } 43 | 44 | exception TTransactionCouldNotTakeSnapshotException { 45 | 1: string message 46 | } 47 | 48 | exception TInvalidTruncateTimeException { 49 | 1: string message 50 | } 51 | 52 | # workaround for THRIFT-1474 53 | struct TBoolean { 54 | 1: bool value 55 | } 56 | 57 | service TTransactionServer { 58 | // temporary tx2 stuff 59 | TTransaction startLong(), 60 | TTransaction startShort(), 61 | TTransaction startShortTimeout(1: i32 timeout), 62 | TBoolean canCommitTx(1: TTransaction tx, 2: set changes) throws (1:TTransactionNotInProgressException e), 63 | TBoolean commitTx(1: TTransaction tx) throws (1:TTransactionNotInProgressException e), 64 | void abortTx(1: TTransaction tx), 65 | bool invalidateTx(1: i64 tx), 66 | binary getSnapshot() throws (1:TTransactionCouldNotTakeSnapshotException e), 67 | void resetState(), 68 | string status(), 69 | TBoolean truncateInvalidTx(1: set txns), 70 | TBoolean truncateInvalidTxBefore(1: i64 time) throws (1: TInvalidTruncateTimeException e), 71 | i32 invalidTxSize(), 72 | TTransaction checkpoint(1: TTransaction tx) throws (1: TTransactionNotInProgressException e), 73 | } 74 | -------------------------------------------------------------------------------- /tephra-core/src/test/java/co/cask/tephra/TransactionServiceMainTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra; 18 | 19 | import co.cask.tephra.distributed.TransactionServiceClient; 20 | import com.google.common.base.Throwables; 21 | import org.apache.hadoop.conf.Configuration; 22 | import org.apache.twill.internal.zookeeper.InMemoryZKServer; 23 | import org.junit.ClassRule; 24 | import org.junit.Test; 25 | import org.junit.rules.TemporaryFolder; 26 | 27 | import java.util.concurrent.CountDownLatch; 28 | 29 | /** 30 | * Test for verifying TransactionServiceMain works correctly. 31 | */ 32 | public class TransactionServiceMainTest { 33 | 34 | @ClassRule 35 | public static TemporaryFolder tmpFolder = new TemporaryFolder(); 36 | 37 | @Test 38 | public void testClientServer() throws Exception { 39 | // Simply start a transaction server and connect to it with the client. 40 | InMemoryZKServer zkServer = InMemoryZKServer.builder().setDataDir(tmpFolder.newFolder()).build(); 41 | zkServer.startAndWait(); 42 | 43 | try { 44 | Configuration conf = new Configuration(); 45 | conf.set(TxConstants.Service.CFG_DATA_TX_ZOOKEEPER_QUORUM, zkServer.getConnectionStr()); 46 | conf.set(TxConstants.Manager.CFG_TX_SNAPSHOT_DIR, tmpFolder.newFolder().getAbsolutePath()); 47 | 48 | final TransactionServiceMain main = new TransactionServiceMain(conf); 49 | final CountDownLatch latch = new CountDownLatch(1); 50 | Thread t = new Thread() { 51 | @Override 52 | public void run() { 53 | try { 54 | main.start(); 55 | latch.countDown(); 56 | } catch (Exception e) { 57 | throw Throwables.propagate(e); 58 | } 59 | } 60 | }; 61 | 62 | try { 63 | t.start(); 64 | // Wait for service to startup 65 | latch.await(); 66 | TransactionServiceClient.doMain(true, conf); 67 | } finally { 68 | main.stop(); 69 | t.join(); 70 | } 71 | } finally { 72 | zkServer.stopAndWait(); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /tephra-core/src/test/java/co/cask/tephra/hbase/AbstractTransactionVisibilityFilterTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.hbase; 18 | 19 | import co.cask.tephra.TransactionManager; 20 | import co.cask.tephra.TxConstants; 21 | import co.cask.tephra.util.ConfigurationFactory; 22 | import com.google.common.collect.Lists; 23 | import org.apache.hadoop.conf.Configuration; 24 | import org.junit.After; 25 | import org.junit.Before; 26 | 27 | import java.util.List; 28 | 29 | /** 30 | * Common test class for TransactionVisibilityFilter implementations. 31 | */ 32 | public abstract class AbstractTransactionVisibilityFilterTest { 33 | 34 | protected static final byte[] FAM = new byte[] {'f'}; 35 | protected static final byte[] FAM2 = new byte[] {'f', '2'}; 36 | protected static final byte[] FAM3 = new byte[] {'f', '3'}; 37 | protected static final byte[] COL = new byte[] {'c'}; 38 | protected static final List EMPTY_CHANGESET = Lists.newArrayListWithCapacity(0); 39 | 40 | protected TransactionManager txManager; 41 | 42 | @Before 43 | public void setup() throws Exception { 44 | Configuration conf = new ConfigurationFactory().get(); 45 | conf.unset(TxConstants.Persist.CFG_TX_SNAPHOT_CODEC_CLASSES); 46 | txManager = new TransactionManager(conf); 47 | txManager.startAndWait(); 48 | } 49 | 50 | @After 51 | public void tearDown() throws Exception { 52 | txManager.stopAndWait(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /tephra-core/src/test/java/co/cask/tephra/persist/HDFSTransactionStateStorageTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2014 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.persist; 18 | 19 | import co.cask.tephra.TxConstants; 20 | import co.cask.tephra.metrics.TxMetricsCollector; 21 | import co.cask.tephra.snapshot.SnapshotCodecProvider; 22 | import org.apache.hadoop.conf.Configuration; 23 | import org.apache.hadoop.hdfs.MiniDFSCluster; 24 | import org.junit.AfterClass; 25 | import org.junit.BeforeClass; 26 | import org.junit.ClassRule; 27 | import org.junit.rules.TemporaryFolder; 28 | 29 | import java.io.IOException; 30 | 31 | 32 | /** 33 | * Tests persistence of transaction snapshots and write-ahead logs to HDFS storage, using the 34 | * {@link HDFSTransactionStateStorage} and {@link HDFSTransactionLog} implementations. 35 | */ 36 | public class HDFSTransactionStateStorageTest extends AbstractTransactionStateStorageTest { 37 | 38 | @ClassRule 39 | public static TemporaryFolder tmpFolder = new TemporaryFolder(); 40 | 41 | private static MiniDFSCluster dfsCluster; 42 | private static Configuration conf; 43 | 44 | @BeforeClass 45 | public static void setupBeforeClass() throws Exception { 46 | Configuration hConf = new Configuration(); 47 | hConf.set(MiniDFSCluster.HDFS_MINIDFS_BASEDIR, tmpFolder.newFolder().getAbsolutePath()); 48 | 49 | dfsCluster = new MiniDFSCluster.Builder(hConf).numDataNodes(1).build(); 50 | conf = new Configuration(dfsCluster.getFileSystem().getConf()); 51 | } 52 | 53 | @AfterClass 54 | public static void tearDownAfterClass() throws Exception { 55 | dfsCluster.shutdown(); 56 | } 57 | 58 | @Override 59 | protected Configuration getConfiguration(String testName) throws IOException { 60 | // tests should use the current user for HDFS 61 | conf.unset(TxConstants.Manager.CFG_TX_HDFS_USER); 62 | conf.set(TxConstants.Manager.CFG_TX_SNAPSHOT_DIR, tmpFolder.newFolder().getAbsolutePath()); 63 | return conf; 64 | } 65 | 66 | @Override 67 | protected AbstractTransactionStateStorage getStorage(Configuration conf) { 68 | return new HDFSTransactionStateStorage(conf, new SnapshotCodecProvider(conf), new TxMetricsCollector()); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /tephra-core/src/test/java/co/cask/tephra/util/AbstractConfigurationProviderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.util; 18 | 19 | import org.apache.hadoop.conf.Configuration; 20 | import org.junit.Test; 21 | 22 | import static org.junit.Assert.assertEquals; 23 | import static org.junit.Assert.assertNotNull; 24 | 25 | /** 26 | * 27 | */ 28 | public abstract class AbstractConfigurationProviderTest { 29 | @Test 30 | public void testVersionFactory() { 31 | HBaseVersion.Version foundVersion = HBaseVersion.get(); 32 | assertEquals(getExpectedVersion(), foundVersion); 33 | } 34 | 35 | protected abstract HBaseVersion.Version getExpectedVersion(); 36 | 37 | @Test 38 | public void testConfigurationProvider() { 39 | Configuration conf = new Configuration(); 40 | conf.set("foo", "bar"); 41 | Configuration newConf = new ConfigurationFactory().get(conf); 42 | assertNotNull(newConf); 43 | assertEquals("bar", newConf.get("foo")); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /tephra-core/src/test/java/co/cask/tephra/util/TransactionEditUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.util; 18 | 19 | import co.cask.tephra.ChangeId; 20 | import co.cask.tephra.TransactionType; 21 | import co.cask.tephra.persist.TransactionEdit; 22 | import com.google.common.collect.Lists; 23 | import com.google.common.collect.Sets; 24 | 25 | import java.util.List; 26 | import java.util.Random; 27 | import java.util.Set; 28 | 29 | /** 30 | * Util class for {@link TransactionEdit} related tests. 31 | */ 32 | public final class TransactionEditUtil { 33 | private static Random random = new Random(); 34 | 35 | /** 36 | * Generates a number of semi-random {@link TransactionEdit} instances. 37 | * These are just randomly selected from the possible states, so would not necessarily reflect a real-world 38 | * distribution. 39 | * 40 | * @param numEntries how many entries to generate in the returned list. 41 | * @return a list of randomly generated transaction log edits. 42 | */ 43 | public static List createRandomEdits(int numEntries) { 44 | List edits = Lists.newArrayListWithCapacity(numEntries); 45 | for (int i = 0; i < numEntries; i++) { 46 | TransactionEdit.State nextType = TransactionEdit.State.values()[random.nextInt(6)]; 47 | long writePointer = Math.abs(random.nextLong()); 48 | switch (nextType) { 49 | case INPROGRESS: 50 | edits.add( 51 | TransactionEdit.createStarted(writePointer, writePointer - 1, 52 | System.currentTimeMillis() + 300000L, TransactionType.SHORT)); 53 | break; 54 | case COMMITTING: 55 | edits.add(TransactionEdit.createCommitting(writePointer, generateChangeSet(10))); 56 | break; 57 | case COMMITTED: 58 | edits.add(TransactionEdit.createCommitted(writePointer, generateChangeSet(10), writePointer + 1, 59 | random.nextBoolean())); 60 | break; 61 | case INVALID: 62 | edits.add(TransactionEdit.createInvalid(writePointer)); 63 | break; 64 | case ABORTED: 65 | edits.add(TransactionEdit.createAborted(writePointer, TransactionType.SHORT, null)); 66 | break; 67 | case MOVE_WATERMARK: 68 | edits.add(TransactionEdit.createMoveWatermark(writePointer)); 69 | break; 70 | } 71 | } 72 | return edits; 73 | } 74 | 75 | private static Set generateChangeSet(int numEntries) { 76 | Set changes = Sets.newHashSet(); 77 | for (int i = 0; i < numEntries; i++) { 78 | byte[] bytes = new byte[8]; 79 | random.nextBytes(bytes); 80 | changes.add(new ChangeId(bytes)); 81 | } 82 | return changes; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /tephra-core/src/test/java/co/cask/tephra/util/TxUtilsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.util; 18 | 19 | import co.cask.tephra.Transaction; 20 | import org.junit.Test; 21 | 22 | import static org.junit.Assert.assertEquals; 23 | 24 | /** 25 | * Test cases for {@link TxUtils} utility methods. 26 | */ 27 | public class TxUtilsTest { 28 | @Test 29 | public void testMaxVisibleTimestamp() { 30 | // make sure we don't overflow with MAX_VALUE write pointer 31 | assertEquals(Long.MAX_VALUE, TxUtils.getMaxVisibleTimestamp(Transaction.ALL_VISIBLE_LATEST)); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tephra-examples/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | tephra 21 | co.cask.tephra 22 | 0.7.2-SNAPSHOT 23 | 24 | 4.0.0 25 | 26 | tephra-examples 27 | Tephra Examples 28 | 29 | 30 | 31 | 2.6.0 32 | 1.0.0-cdh5.4.2 33 | 34 | 35 | 36 | 37 | cloudera 38 | https://repository.cloudera.com/artifactory/cloudera-repos/ 39 | 40 | 41 | 42 | 43 | 44 | 45 | co.cask.tephra 46 | tephra-api 47 | ${project.version} 48 | 49 | 50 | co.cask.tephra 51 | tephra-core 52 | ${project.version} 53 | 54 | 55 | co.cask.tephra 56 | tephra-hbase-compat-1.0-cdh 57 | ${project.version} 58 | 59 | 60 | org.apache.hbase 61 | hbase-common 62 | ${hbase10cdh.version} 63 | provided 64 | 65 | 66 | org.apache.hbase 67 | hbase-client 68 | ${hbase10cdh.version} 69 | provided 70 | 71 | 72 | org.apache.hbase 73 | hbase-protocol 74 | ${hbase10cdh.version} 75 | provided 76 | 77 | 78 | org.apache.hbase 79 | hbase-server 80 | ${hbase10cdh.version} 81 | provided 82 | 83 | 84 | 85 | 86 | co.cask.tephra 87 | tephra-core 88 | ${project.version} 89 | test-jar 90 | test 91 | 92 | 93 | junit 94 | junit 95 | 96 | 97 | org.apache.hbase 98 | hbase-server 99 | ${hbase10cdh.version} 100 | test-jar 101 | test 102 | 103 | 104 | org.apache.hbase 105 | hbase-testing-util 106 | ${hbase10cdh.version} 107 | test 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /tephra-examples/src/main/java/co/cask/tephra/examples/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | /** 18 | * This package contains example applications for Tephra designed to illustrate sample Tephra usage 19 | * and provide out-of-the-box sample applications which can be run to test cluster functionality. 20 | * 21 | *

Currently the following applications are provided: 22 | * 23 | *

    24 | *
  • BalanceBooks - this application runs a specified number of concurrent clients in separate 25 | * threads, which perform transactions to make withdrawals from each other's accounts and deposits to their own 26 | * accounts. At the end of the test, the total value of all account balances is verified to be equal to zero, 27 | * which confirms that transactional integrity was not violated. 28 | *
  • 29 | *
30 | *

31 | * 32 | *

33 | * Note that, for simplicity, the examples package is currently hardcoded to compile against a specific HBase 34 | * version (currently 1.0-cdh). In the future, we should provide Maven profiles to allow compiling the examples 35 | * against each of the supported HBase versions. 36 | *

37 | */ 38 | package co.cask.tephra.examples; 39 | -------------------------------------------------------------------------------- /tephra-hbase-compat-0.96/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | tephra 21 | co.cask.tephra 22 | 0.7.2-SNAPSHOT 23 | 24 | 4.0.0 25 | 26 | tephra-hbase-compat-0.96 27 | Tephra HBase 0.96 Compatibility 28 | Tephra Transaction System HBase 0.96 Compatibility Module 29 | 30 | 31 | 32 | co.cask.tephra 33 | tephra-api 34 | ${project.version} 35 | 36 | 37 | co.cask.tephra 38 | tephra-core 39 | ${project.version} 40 | 41 | 42 | org.apache.hbase 43 | hbase 44 | 45 | 46 | 47 | 48 | org.apache.hbase 49 | hbase-common 50 | ${hbase96.version} 51 | provided 52 | 53 | 54 | org.apache.hbase 55 | hbase-client 56 | ${hbase96.version} 57 | provided 58 | 59 | 60 | org.apache.hbase 61 | hbase-protocol 62 | ${hbase96.version} 63 | provided 64 | 65 | 66 | org.apache.hbase 67 | hbase-server 68 | ${hbase96.version} 69 | provided 70 | 71 | 72 | 73 | 74 | co.cask.tephra 75 | tephra-core 76 | ${project.version} 77 | test-jar 78 | test 79 | 80 | 81 | junit 82 | junit 83 | 84 | 85 | org.apache.hbase 86 | hbase-testing-util 87 | ${hbase96.version} 88 | test 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /tephra-hbase-compat-0.96/src/main/java/co/cask/tephra/hbase96/HBase96ConfigurationProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.hbase96; 18 | 19 | import co.cask.tephra.util.ConfigurationProvider; 20 | import org.apache.hadoop.conf.Configuration; 21 | import org.apache.hadoop.hbase.HBaseConfiguration; 22 | 23 | /** 24 | * HBase 0.96 version of {@link co.cask.tephra.util.ConfigurationProvider}. 25 | */ 26 | public class HBase96ConfigurationProvider extends ConfigurationProvider { 27 | @Override 28 | public Configuration get() { 29 | return HBaseConfiguration.create(); 30 | } 31 | 32 | @Override 33 | public Configuration get(Configuration baseConf) { 34 | return HBaseConfiguration.create(baseConf); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tephra-hbase-compat-0.96/src/main/java/co/cask/tephra/hbase96/coprocessor/TransactionFilters.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2016 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.hbase96.coprocessor; 18 | 19 | import co.cask.tephra.Transaction; 20 | import org.apache.hadoop.hbase.filter.Filter; 21 | import org.apache.hadoop.hbase.regionserver.ScanType; 22 | 23 | import java.util.Map; 24 | import javax.annotation.Nullable; 25 | 26 | /** 27 | * Factory class for providing {@link Filter} instances. 28 | */ 29 | public class TransactionFilters { 30 | /** 31 | * Creates a new {@link org.apache.hadoop.hbase.filter.Filter} for returning data only from visible transactions. 32 | * 33 | * @param tx the current transaction to apply. Only data visible to this transaction will be returned. 34 | * @param ttlByFamily map of time-to-live (TTL) (in milliseconds) by column family name 35 | * @param allowEmptyValues if {@code true} cells with empty {@code byte[]} values will be returned, if {@code false} 36 | * these will be interpreted as "delete" markers and the column will be filtered out 37 | * @param scanType the type of scan operation being performed 38 | */ 39 | public static Filter getVisibilityFilter(Transaction tx, Map ttlByFamily, boolean allowEmptyValues, 40 | ScanType scanType) { 41 | return new CellSkipFilter(new TransactionVisibilityFilter(tx, ttlByFamily, allowEmptyValues, scanType, null)); 42 | } 43 | 44 | /** 45 | * Creates a new {@link org.apache.hadoop.hbase.filter.Filter} for returning data only from visible transactions. 46 | * 47 | * @param tx the current transaction to apply. Only data visible to this transaction will be returned. 48 | * @param ttlByFamily map of time-to-live (TTL) (in milliseconds) by column family name 49 | * @param allowEmptyValues if {@code true} cells with empty {@code byte[]} values will be returned, if {@code false} 50 | * these will be interpreted as "delete" markers and the column will be filtered out 51 | * @param scanType the type of scan operation being performed 52 | * @param cellFilter if non-null, this filter will be applied to all cells visible to the current transaction, by 53 | * calling {@link Filter#filterKeyValue(org.apache.hadoop.hbase.Cell)}. If null, then 54 | * {@link Filter.ReturnCode#INCLUDE_AND_NEXT_COL} will be returned instead. 55 | */ 56 | public static Filter getVisibilityFilter(Transaction tx, Map ttlByFamily, boolean allowEmptyValues, 57 | ScanType scanType, @Nullable Filter cellFilter) { 58 | return new CellSkipFilter(new TransactionVisibilityFilter(tx, ttlByFamily, allowEmptyValues, scanType, cellFilter)); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /tephra-hbase-compat-0.96/src/test/java/co/cask/tephra/hbase96/HBase96ConfigurationProviderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.hbase96; 18 | 19 | import co.cask.tephra.util.AbstractConfigurationProviderTest; 20 | import co.cask.tephra.util.HBaseVersion; 21 | 22 | /** 23 | * Test for HBase 0.96 version specific behavior. 24 | */ 25 | public class HBase96ConfigurationProviderTest extends AbstractConfigurationProviderTest { 26 | @Override 27 | protected HBaseVersion.Version getExpectedVersion() { 28 | return HBaseVersion.Version.HBASE_96; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tephra-hbase-compat-0.98/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | tephra 21 | co.cask.tephra 22 | 0.7.2-SNAPSHOT 23 | 24 | 4.0.0 25 | 26 | tephra-hbase-compat-0.98 27 | Tephra HBase 0.98 Compatibility 28 | 29 | 30 | 31 | co.cask.tephra 32 | tephra-api 33 | ${project.version} 34 | 35 | 36 | co.cask.tephra 37 | tephra-core 38 | ${project.version} 39 | 40 | 41 | org.apache.hbase 42 | hbase 43 | 44 | 45 | 46 | 47 | org.apache.hbase 48 | hbase-common 49 | ${hbase98.version} 50 | provided 51 | 52 | 53 | org.apache.hbase 54 | hbase-client 55 | ${hbase98.version} 56 | provided 57 | 58 | 59 | org.apache.hbase 60 | hbase-protocol 61 | ${hbase98.version} 62 | provided 63 | 64 | 65 | org.apache.hbase 66 | hbase-server 67 | ${hbase98.version} 68 | provided 69 | 70 | 71 | 72 | 73 | co.cask.tephra 74 | tephra-core 75 | ${project.version} 76 | test-jar 77 | test 78 | 79 | 80 | junit 81 | junit 82 | 83 | 84 | org.apache.hbase 85 | hbase-testing-util 86 | ${hbase98.version} 87 | test 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /tephra-hbase-compat-0.98/src/main/java/co/cask/tephra/hbase98/HBase98ConfigurationProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.hbase98; 18 | 19 | import co.cask.tephra.util.ConfigurationProvider; 20 | import org.apache.hadoop.conf.Configuration; 21 | import org.apache.hadoop.hbase.HBaseConfiguration; 22 | 23 | /** 24 | * HBase 0.98 version of {@link co.cask.tephra.util.ConfigurationProvider}. 25 | */ 26 | public class HBase98ConfigurationProvider extends ConfigurationProvider { 27 | @Override 28 | public Configuration get() { 29 | return HBaseConfiguration.create(); 30 | } 31 | 32 | @Override 33 | public Configuration get(Configuration baseConf) { 34 | return HBaseConfiguration.create(baseConf); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tephra-hbase-compat-0.98/src/main/java/co/cask/tephra/hbase98/coprocessor/TransactionFilters.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2016 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.hbase98.coprocessor; 18 | 19 | import co.cask.tephra.Transaction; 20 | import org.apache.hadoop.hbase.filter.Filter; 21 | import org.apache.hadoop.hbase.regionserver.ScanType; 22 | 23 | import java.util.Map; 24 | import javax.annotation.Nullable; 25 | 26 | /** 27 | * Factory class for providing {@link Filter} instances. 28 | */ 29 | public class TransactionFilters { 30 | /** 31 | * Creates a new {@link org.apache.hadoop.hbase.filter.Filter} for returning data only from visible transactions. 32 | * 33 | * @param tx the current transaction to apply. Only data visible to this transaction will be returned. 34 | * @param ttlByFamily map of time-to-live (TTL) (in milliseconds) by column family name 35 | * @param allowEmptyValues if {@code true} cells with empty {@code byte[]} values will be returned, if {@code false} 36 | * these will be interpreted as "delete" markers and the column will be filtered out 37 | * @param scanType the type of scan operation being performed 38 | */ 39 | public static Filter getVisibilityFilter(Transaction tx, Map ttlByFamily, boolean allowEmptyValues, 40 | ScanType scanType) { 41 | return new CellSkipFilter(new TransactionVisibilityFilter(tx, ttlByFamily, allowEmptyValues, scanType, null)); 42 | } 43 | 44 | /** 45 | * Creates a new {@link org.apache.hadoop.hbase.filter.Filter} for returning data only from visible transactions. 46 | * 47 | * @param tx the current transaction to apply. Only data visible to this transaction will be returned. 48 | * @param ttlByFamily map of time-to-live (TTL) (in milliseconds) by column family name 49 | * @param allowEmptyValues if {@code true} cells with empty {@code byte[]} values will be returned, if {@code false} 50 | * these will be interpreted as "delete" markers and the column will be filtered out 51 | * @param scanType the type of scan operation being performed 52 | * @param cellFilter if non-null, this filter will be applied to all cells visible to the current transaction, by 53 | * calling {@link Filter#filterKeyValue(org.apache.hadoop.hbase.Cell)}. If null, then 54 | * {@link Filter.ReturnCode#INCLUDE_AND_NEXT_COL} will be returned instead. 55 | */ 56 | public static Filter getVisibilityFilter(Transaction tx, Map ttlByFamily, boolean allowEmptyValues, 57 | ScanType scanType, @Nullable Filter cellFilter) { 58 | return new CellSkipFilter(new TransactionVisibilityFilter(tx, ttlByFamily, allowEmptyValues, scanType, cellFilter)); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /tephra-hbase-compat-0.98/src/test/java/co/cask/tephra/hbase98/HBase98ConfigurationProviderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.hbase98; 18 | 19 | import co.cask.tephra.util.AbstractConfigurationProviderTest; 20 | import co.cask.tephra.util.HBaseVersion; 21 | 22 | /** 23 | * Test for HBase 0.98 version specific behavior. 24 | */ 25 | public class HBase98ConfigurationProviderTest extends AbstractConfigurationProviderTest { 26 | @Override 27 | protected HBaseVersion.Version getExpectedVersion() { 28 | return HBaseVersion.Version.HBASE_98; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tephra-hbase-compat-1.0-cdh/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | tephra 21 | co.cask.tephra 22 | 0.7.2-SNAPSHOT 23 | 24 | 4.0.0 25 | 26 | tephra-hbase-compat-1.0-cdh 27 | Tephra HBase 1.0 Compatibility for CDH 28 | 29 | 30 | 31 | 2.6.0 32 | 33 | 34 | 35 | 36 | cloudera 37 | https://repository.cloudera.com/artifactory/cloudera-repos/ 38 | 39 | 40 | 41 | 42 | 43 | 44 | co.cask.tephra 45 | tephra-api 46 | ${project.version} 47 | 48 | 49 | co.cask.tephra 50 | tephra-core 51 | ${project.version} 52 | 53 | 54 | org.apache.hbase 55 | hbase-common 56 | ${hbase10cdh.version} 57 | provided 58 | 59 | 60 | org.apache.hbase 61 | hbase-client 62 | ${hbase10cdh.version} 63 | provided 64 | 65 | 66 | org.apache.hbase 67 | hbase-protocol 68 | ${hbase10cdh.version} 69 | provided 70 | 71 | 72 | org.apache.hbase 73 | hbase-server 74 | ${hbase10cdh.version} 75 | provided 76 | 77 | 78 | 79 | 80 | co.cask.tephra 81 | tephra-core 82 | ${project.version} 83 | test-jar 84 | test 85 | 86 | 87 | junit 88 | junit 89 | 90 | 91 | org.apache.hbase 92 | hbase-server 93 | ${hbase10cdh.version} 94 | test-jar 95 | test 96 | 97 | 98 | org.apache.hbase 99 | hbase-testing-util 100 | ${hbase10cdh.version} 101 | test 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /tephra-hbase-compat-1.0-cdh/src/main/java/co/cask/tephra/hbase10cdh/HBase10ConfigurationProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.hbase10cdh; 18 | 19 | import co.cask.tephra.util.ConfigurationProvider; 20 | import org.apache.hadoop.conf.Configuration; 21 | import org.apache.hadoop.hbase.HBaseConfiguration; 22 | 23 | /** 24 | * HBase 1.0 version of {@link co.cask.tephra.util.ConfigurationProvider}. 25 | */ 26 | public class HBase10ConfigurationProvider extends ConfigurationProvider { 27 | @Override 28 | public Configuration get() { 29 | return HBaseConfiguration.create(); 30 | } 31 | 32 | @Override 33 | public Configuration get(Configuration baseConf) { 34 | return HBaseConfiguration.create(baseConf); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tephra-hbase-compat-1.0-cdh/src/main/java/co/cask/tephra/hbase10cdh/coprocessor/TransactionFilters.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2016 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.hbase10cdh.coprocessor; 18 | 19 | import co.cask.tephra.Transaction; 20 | import org.apache.hadoop.hbase.filter.Filter; 21 | import org.apache.hadoop.hbase.regionserver.ScanType; 22 | 23 | import java.util.Map; 24 | import javax.annotation.Nullable; 25 | 26 | /** 27 | * Factory class for providing {@link Filter} instances. 28 | */ 29 | public class TransactionFilters { 30 | /** 31 | * Creates a new {@link org.apache.hadoop.hbase.filter.Filter} for returning data only from visible transactions. 32 | * 33 | * @param tx the current transaction to apply. Only data visible to this transaction will be returned. 34 | * @param ttlByFamily map of time-to-live (TTL) (in milliseconds) by column family name 35 | * @param allowEmptyValues if {@code true} cells with empty {@code byte[]} values will be returned, if {@code false} 36 | * these will be interpreted as "delete" markers and the column will be filtered out 37 | * @param scanType the type of scan operation being performed 38 | */ 39 | public static Filter getVisibilityFilter(Transaction tx, Map ttlByFamily, boolean allowEmptyValues, 40 | ScanType scanType) { 41 | return new CellSkipFilter(new TransactionVisibilityFilter(tx, ttlByFamily, allowEmptyValues, scanType, null)); 42 | } 43 | 44 | /** 45 | * Creates a new {@link org.apache.hadoop.hbase.filter.Filter} for returning data only from visible transactions. 46 | * 47 | * @param tx the current transaction to apply. Only data visible to this transaction will be returned. 48 | * @param ttlByFamily map of time-to-live (TTL) (in milliseconds) by column family name 49 | * @param allowEmptyValues if {@code true} cells with empty {@code byte[]} values will be returned, if {@code false} 50 | * these will be interpreted as "delete" markers and the column will be filtered out 51 | * @param scanType the type of scan operation being performed 52 | * @param cellFilter if non-null, this filter will be applied to all cells visible to the current transaction, by 53 | * calling {@link Filter#filterKeyValue(org.apache.hadoop.hbase.Cell)}. If null, then 54 | * {@link Filter.ReturnCode#INCLUDE_AND_NEXT_COL} will be returned instead. 55 | */ 56 | public static Filter getVisibilityFilter(Transaction tx, Map ttlByFamily, boolean allowEmptyValues, 57 | ScanType scanType, @Nullable Filter cellFilter) { 58 | return new CellSkipFilter(new TransactionVisibilityFilter(tx, ttlByFamily, allowEmptyValues, scanType, cellFilter)); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /tephra-hbase-compat-1.0-cdh/src/test/java/co/cask/tephra/hbase10cdh/HBase10ConfigurationProviderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.hbase10cdh; 18 | 19 | import co.cask.tephra.util.AbstractConfigurationProviderTest; 20 | import co.cask.tephra.util.HBaseVersion; 21 | 22 | /** 23 | * Test for HBase 1.0 (CDH) version specific behavior. 24 | */ 25 | public class HBase10ConfigurationProviderTest extends AbstractConfigurationProviderTest { 26 | @Override 27 | protected HBaseVersion.Version getExpectedVersion() { 28 | return HBaseVersion.Version.HBASE_10_CDH; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tephra-hbase-compat-1.0/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | tephra 21 | co.cask.tephra 22 | 0.7.2-SNAPSHOT 23 | 24 | 4.0.0 25 | 26 | tephra-hbase-compat-1.0 27 | Tephra HBase 1.0 Compatibility 28 | 29 | 30 | 31 | 2.4.0 32 | 33 | 34 | 35 | 36 | co.cask.tephra 37 | tephra-api 38 | ${project.version} 39 | 40 | 41 | co.cask.tephra 42 | tephra-core 43 | ${project.version} 44 | 45 | 46 | org.apache.hbase 47 | hbase 48 | 49 | 50 | 51 | 52 | org.apache.hbase 53 | hbase-common 54 | ${hbase10.version} 55 | provided 56 | 57 | 58 | org.apache.hbase 59 | hbase-client 60 | ${hbase10.version} 61 | provided 62 | 63 | 64 | org.apache.hbase 65 | hbase-protocol 66 | ${hbase10.version} 67 | provided 68 | 69 | 70 | org.apache.hbase 71 | hbase-server 72 | ${hbase10.version} 73 | provided 74 | 75 | 76 | 77 | 78 | co.cask.tephra 79 | tephra-core 80 | ${project.version} 81 | test-jar 82 | test 83 | 84 | 85 | junit 86 | junit 87 | 88 | 89 | org.apache.hbase 90 | hbase-server 91 | ${hbase10.version} 92 | test-jar 93 | test 94 | 95 | 96 | org.apache.hbase 97 | hbase-testing-util 98 | ${hbase10.version} 99 | test 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /tephra-hbase-compat-1.0/src/main/java/co/cask/tephra/hbase10/HBase10ConfigurationProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.hbase10; 18 | 19 | import co.cask.tephra.util.ConfigurationProvider; 20 | import org.apache.hadoop.conf.Configuration; 21 | import org.apache.hadoop.hbase.HBaseConfiguration; 22 | 23 | /** 24 | * HBase 1.0 version of {@link co.cask.tephra.util.ConfigurationProvider}. 25 | */ 26 | public class HBase10ConfigurationProvider extends ConfigurationProvider { 27 | @Override 28 | public Configuration get() { 29 | return HBaseConfiguration.create(); 30 | } 31 | 32 | @Override 33 | public Configuration get(Configuration baseConf) { 34 | return HBaseConfiguration.create(baseConf); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tephra-hbase-compat-1.0/src/main/java/co/cask/tephra/hbase10/coprocessor/TransactionFilters.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2016 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.hbase10.coprocessor; 18 | 19 | import co.cask.tephra.Transaction; 20 | import org.apache.hadoop.hbase.filter.Filter; 21 | import org.apache.hadoop.hbase.regionserver.ScanType; 22 | 23 | import java.util.Map; 24 | import javax.annotation.Nullable; 25 | 26 | /** 27 | * Factory class for providing {@link Filter} instances. 28 | */ 29 | public class TransactionFilters { 30 | /** 31 | * Creates a new {@link org.apache.hadoop.hbase.filter.Filter} for returning data only from visible transactions. 32 | * 33 | * @param tx the current transaction to apply. Only data visible to this transaction will be returned. 34 | * @param ttlByFamily map of time-to-live (TTL) (in milliseconds) by column family name 35 | * @param allowEmptyValues if {@code true} cells with empty {@code byte[]} values will be returned, if {@code false} 36 | * these will be interpreted as "delete" markers and the column will be filtered out 37 | * @param scanType the type of scan operation being performed 38 | */ 39 | public static Filter getVisibilityFilter(Transaction tx, Map ttlByFamily, boolean allowEmptyValues, 40 | ScanType scanType) { 41 | return new CellSkipFilter(new TransactionVisibilityFilter(tx, ttlByFamily, allowEmptyValues, scanType, null)); 42 | } 43 | 44 | /** 45 | * Creates a new {@link org.apache.hadoop.hbase.filter.Filter} for returning data only from visible transactions. 46 | * 47 | * @param tx the current transaction to apply. Only data visible to this transaction will be returned. 48 | * @param ttlByFamily map of time-to-live (TTL) (in milliseconds) by column family name 49 | * @param allowEmptyValues if {@code true} cells with empty {@code byte[]} values will be returned, if {@code false} 50 | * these will be interpreted as "delete" markers and the column will be filtered out 51 | * @param scanType the type of scan operation being performed 52 | * @param cellFilter if non-null, this filter will be applied to all cells visible to the current transaction, by 53 | * calling {@link Filter#filterKeyValue(org.apache.hadoop.hbase.Cell)}. If null, then 54 | * {@link Filter.ReturnCode#INCLUDE_AND_NEXT_COL} will be returned instead. 55 | */ 56 | public static Filter getVisibilityFilter(Transaction tx, Map ttlByFamily, boolean allowEmptyValues, 57 | ScanType scanType, @Nullable Filter cellFilter) { 58 | return new CellSkipFilter(new TransactionVisibilityFilter(tx, ttlByFamily, allowEmptyValues, scanType, cellFilter)); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /tephra-hbase-compat-1.0/src/test/java/co/cask/tephra/hbase10/HBase10ConfigurationProviderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.hbase10; 18 | 19 | import co.cask.tephra.util.AbstractConfigurationProviderTest; 20 | import co.cask.tephra.util.HBaseVersion; 21 | 22 | /** 23 | * Test for HBase 1.0 version specific behavior. 24 | */ 25 | public class HBase10ConfigurationProviderTest extends AbstractConfigurationProviderTest { 26 | @Override 27 | protected HBaseVersion.Version getExpectedVersion() { 28 | return HBaseVersion.Version.HBASE_10; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tephra-hbase-compat-1.1/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | tephra 21 | co.cask.tephra 22 | 0.7.2-SNAPSHOT 23 | 24 | 4.0.0 25 | 26 | tephra-hbase-compat-1.1 27 | Tephra HBase 1.1 Compatibility 28 | 29 | 30 | 31 | 2.4.0 32 | 33 | 34 | 35 | 36 | co.cask.tephra 37 | tephra-api 38 | ${project.version} 39 | 40 | 41 | co.cask.tephra 42 | tephra-core 43 | ${project.version} 44 | 45 | 46 | org.apache.hbase 47 | hbase 48 | 49 | 50 | 51 | 52 | org.apache.hbase 53 | hbase-common 54 | ${hbase11.version} 55 | provided 56 | 57 | 58 | org.apache.hbase 59 | hbase-client 60 | ${hbase11.version} 61 | provided 62 | 63 | 64 | org.apache.hbase 65 | hbase-protocol 66 | ${hbase11.version} 67 | provided 68 | 69 | 70 | org.apache.hbase 71 | hbase-server 72 | ${hbase11.version} 73 | provided 74 | 75 | 76 | 77 | 78 | co.cask.tephra 79 | tephra-core 80 | ${project.version} 81 | test-jar 82 | test 83 | 84 | 85 | junit 86 | junit 87 | 88 | 89 | org.apache.hbase 90 | hbase-server 91 | ${hbase11.version} 92 | test-jar 93 | test 94 | 95 | 96 | org.apache.hbase 97 | hbase-testing-util 98 | ${hbase11.version} 99 | test 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /tephra-hbase-compat-1.1/src/main/java/co/cask/tephra/hbase11/HBase11ConfigurationProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.hbase11; 18 | 19 | import co.cask.tephra.util.ConfigurationProvider; 20 | import org.apache.hadoop.conf.Configuration; 21 | import org.apache.hadoop.hbase.HBaseConfiguration; 22 | 23 | /** 24 | * HBase 1.1 version of {@link ConfigurationProvider}. 25 | */ 26 | public class HBase11ConfigurationProvider extends ConfigurationProvider { 27 | @Override 28 | public Configuration get() { 29 | return HBaseConfiguration.create(); 30 | } 31 | 32 | @Override 33 | public Configuration get(Configuration baseConf) { 34 | return HBaseConfiguration.create(baseConf); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tephra-hbase-compat-1.1/src/main/java/co/cask/tephra/hbase11/coprocessor/TransactionFilters.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2016 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.hbase11.coprocessor; 18 | 19 | import co.cask.tephra.Transaction; 20 | import org.apache.hadoop.hbase.filter.Filter; 21 | import org.apache.hadoop.hbase.regionserver.ScanType; 22 | 23 | import java.util.Map; 24 | import javax.annotation.Nullable; 25 | 26 | /** 27 | * Factory class for providing {@link Filter} instances. 28 | */ 29 | public class TransactionFilters { 30 | /** 31 | * Creates a new {@link org.apache.hadoop.hbase.filter.Filter} for returning data only from visible transactions. 32 | * 33 | * @param tx the current transaction to apply. Only data visible to this transaction will be returned. 34 | * @param ttlByFamily map of time-to-live (TTL) (in milliseconds) by column family name 35 | * @param allowEmptyValues if {@code true} cells with empty {@code byte[]} values will be returned, if {@code false} 36 | * these will be interpreted as "delete" markers and the column will be filtered out 37 | * @param scanType the type of scan operation being performed 38 | */ 39 | public static Filter getVisibilityFilter(Transaction tx, Map ttlByFamily, boolean allowEmptyValues, 40 | ScanType scanType) { 41 | return new CellSkipFilter(new TransactionVisibilityFilter(tx, ttlByFamily, allowEmptyValues, scanType, null)); 42 | } 43 | 44 | /** 45 | * Creates a new {@link org.apache.hadoop.hbase.filter.Filter} for returning data only from visible transactions. 46 | * 47 | * @param tx the current transaction to apply. Only data visible to this transaction will be returned. 48 | * @param ttlByFamily map of time-to-live (TTL) (in milliseconds) by column family name 49 | * @param allowEmptyValues if {@code true} cells with empty {@code byte[]} values will be returned, if {@code false} 50 | * these will be interpreted as "delete" markers and the column will be filtered out 51 | * @param scanType the type of scan operation being performed 52 | * @param cellFilter if non-null, this filter will be applied to all cells visible to the current transaction, by 53 | * calling {@link Filter#filterKeyValue(org.apache.hadoop.hbase.Cell)}. If null, then 54 | * {@link Filter.ReturnCode#INCLUDE_AND_NEXT_COL} will be returned instead. 55 | */ 56 | public static Filter getVisibilityFilter(Transaction tx, Map ttlByFamily, boolean allowEmptyValues, 57 | ScanType scanType, @Nullable Filter cellFilter) { 58 | return new CellSkipFilter(new TransactionVisibilityFilter(tx, ttlByFamily, allowEmptyValues, scanType, cellFilter)); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /tephra-hbase-compat-1.1/src/test/java/co/cask/tephra/hbase11/HBase11ConfigurationProviderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015 Cask Data, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package co.cask.tephra.hbase11; 18 | 19 | import co.cask.tephra.util.AbstractConfigurationProviderTest; 20 | import co.cask.tephra.util.HBaseVersion; 21 | 22 | /** 23 | * Test for HBase 1.1 version specific behavior. 24 | */ 25 | public class HBase11ConfigurationProviderTest extends AbstractConfigurationProviderTest { 26 | @Override 27 | protected HBaseVersion.Version getExpectedVersion() { 28 | return HBaseVersion.Version.HBASE_11; 29 | } 30 | } 31 | --------------------------------------------------------------------------------