├── .gitignore ├── .travis.yml ├── AUTHORS ├── COPYING ├── HACKING ├── README.md ├── THANKS ├── assembly.xml ├── pom.xml ├── screwdriver.yaml ├── src ├── main │ └── java │ │ └── org │ │ └── hbase │ │ └── async │ │ ├── AppendRequest.java │ │ ├── AtomicIncrementRequest.java │ │ ├── BatchableRpc.java │ │ ├── BinaryPrefixComparator.java │ │ ├── BufferedIncrement.java │ │ ├── Bytes.java │ │ ├── ClientStats.java │ │ ├── ColumnPrefixFilter.java │ │ ├── CompareAndSetRequest.java │ │ ├── CompareFilter.java │ │ ├── Config.java │ │ ├── Counter.java │ │ ├── DeleteRequest.java │ │ ├── FilterComparator.java │ │ ├── FilterList.java │ │ ├── FuzzyRowFilter.java │ │ ├── GetRequest.java │ │ ├── GetResultOrException.java │ │ ├── HBaseClient.java │ │ ├── HBaseException.java │ │ ├── HBaseRpc.java │ │ ├── HasFailedRpcException.java │ │ ├── InvalidResponseException.java │ │ ├── KeyOnlyFilter.java │ │ ├── KeyRegexpFilter.java │ │ ├── KeyValue.java │ │ ├── NoSuchColumnFamilyException.java │ │ ├── NonRecoverableException.java │ │ ├── PleaseThrottleException.java │ │ ├── PutRequest.java │ │ ├── QualifierFilter.java │ │ ├── RecoverableException.java │ │ ├── RegexStringComparator.java │ │ ├── RegionClientStats.java │ │ ├── RegionLocation.java │ │ ├── RowLock.java │ │ ├── RowLockRequest.java │ │ ├── RpcTimedOutException.java │ │ ├── ScanFilter.java │ │ ├── Scanner.java │ │ ├── TableNotFoundException.java │ │ ├── UnknownScannerException.java │ │ └── jsr166e │ │ ├── LongAdder.java │ │ ├── README │ │ ├── Striped64.java │ │ └── package-info.java └── test │ ├── java │ └── org │ │ └── hbase │ │ └── async │ │ ├── DataGenerationHelper.java │ │ ├── FiltersTest.java │ │ ├── HBaseClientIT.java │ │ └── TestHBaseClient.java │ └── resources │ └── logback.xml └── test ├── Common.java ├── Test.java ├── TestIncrementCoalescing.java ├── TestIntegration.java ├── TestMETALookup.java └── TestNSREs.java /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | target/ 3 | 4 | # IntelliJ IDEA files 5 | .idea/ 6 | *.iml 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | 3 | # sudo-enabled environment has 7.5GB of RAM vs. 4GB of RAM for container-based 4 | # env: https://docs.travis-ci.com/user/ci-environment/#Virtualization-environments 5 | sudo: required 6 | 7 | dist: trusty 8 | 9 | jdk: 10 | - oraclejdk8 11 | 12 | env: 13 | # https://docs.travis-ci.com/user/environment-variables/#Global-Variables 14 | global: 15 | # Ignore the defaults from /etc/mavenrc 16 | - MAVEN_SKIP_RC=true 17 | # Add more RAM; Maven is running out during the build: 18 | # https://travis-ci.org/OpenTSDB/asyncbigtable/jobs/203079393 19 | - MAVEN_OPTS="-Xms2048m -Xmx4096m -XX:MaxPermSize=4096m -XX:-UseGCOverheadLimit -XX:+UseG1GC" 20 | 21 | install: 22 | - echo $JAVA_HOME 23 | - travis_wait mvn install -DskipTests=true -Dmaven.javadoc.skip=true -B -V 24 | 25 | script: 26 | - travis_wait mvn test -B 27 | 28 | cache: 29 | # https://docs.travis-ci.com/user/caching/#Arbitrary-directories 30 | directories: 31 | - $HOME/.m2 32 | 33 | notifications: 34 | email: false 35 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | The AsyncHBase Authors 2 | ---------------------- 3 | 4 | AsyncHBase ("asynchbase") was originally written by Benoit Sigoure. 5 | 6 | All contributors are required to sign a "Contributor License Agreement" at 7 | http://opentsdb.net/contributing.html 8 | 9 | The following organizations and people have contributed at least 0.5% of the 10 | current code of AsyncHBase. 11 | (Please keep both lists sorted alphabetically.) 12 | 13 | 14 | Arista Networks, Inc. 15 | StumbleUpon, Inc. 16 | 17 | 18 | Andrey Stepachev 19 | Benoit Sigoure 20 | Brandon Forehand 21 | Viral Bajaria 22 | 23 | 24 | 25 | This list can be obtained at any time with the following script: 26 | 27 | find src test -type f \ 28 | | while read i; do \ 29 | git blame -t $i 2>/dev/null; \ 30 | done \ 31 | | sed 's/^[0-9a-f]\{8\} [^(]*(\([^)]*\) [-+0-9 ]\{14,\}).*/\1/;s/ *$//' \ 32 | | awk '{a[$0]++; t++} END{for(n in a) if (a[n]*100.0/t > 0.5) print n}' \ 33 | | sort 34 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright (C) 2010-2012 The Async HBase Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | - Redistributions of source code must retain the above copyright notice, 6 | this list of conditions and the following disclaimer. 7 | - Redistributions in binary form must reproduce the above copyright notice, 8 | this list of conditions and the following disclaimer in the documentation 9 | and/or other materials provided with the distribution. 10 | - Neither the name of the StumbleUpon nor the names of its contributors 11 | may be used to endorse or promote products derived from this software 12 | without specific prior written permission. 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 17 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 23 | POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /HACKING: -------------------------------------------------------------------------------- 1 | Want to contribute? Great! This file will guide you through some of 2 | design decision / ideology you should try to adhere to. 3 | 4 | ------- 5 | This document is outdated and will be updated with the asyncbigtable details. 6 | 7 | The build process has changed and currently there are no unit tests to run. 8 | 9 | However, the basic programming principles and coding guidelines are always valid. 10 | ------- 11 | 12 | Getting started: 13 | 14 | # You need this & javac on $PATH. The first run will download dependencies. 15 | $ make 16 | 17 | # Run the unit tests 18 | $ make check 19 | 20 | # Run the integration tests. See also "Testing" below. 21 | $ HBASE_HOME=~/src/hbase make integration ARGS='test f' 22 | 23 | The basics: 24 | - Know the complexity of your algorithms. When you're calling a 25 | method in another library, make sure you're aware of the its 26 | complexity. Is it O(n2) or O(n log n)? How much memory will it 27 | allocate? For instance, Collections.sort() works in O(n log n) 28 | as expected but it does 3 array copies! So it's O(3n) = O(n) in 29 | space instead of O(1). 30 | - Avoid allocating objects whenever you can. If you can, re-use the 31 | same objects in a loop in order to avoid generating too much garbage 32 | for the GC to collect. Objects that are expected to be used very 33 | frequently should be create once and stored in an attribute. 34 | 35 | The build system: 36 | - No Ant / Ivy / Maven madness. Using XML to specify a build system 37 | is a dumb idea and those tools are way too slow and don't even do 38 | proper dependency tracking out of the box. They don't come with a 39 | set of standard rules that make packaging easy. 40 | - Don't add new dependencies unless you have a compelling reason to do 41 | so. The code of any dependency will be audited before we can allow 42 | this new dependency. 43 | 44 | Code: 45 | - The #1 rule is to write readable code. How much time will it take 46 | for someone else to understand that method? If something is not 47 | obvious, it should be commented. 48 | - Stick to the coding style in the files you're editing. 49 | - Avoid lines longer than 80 characters. There are a few cases where 50 | Java is so verbose that trying to wrap things around to avoid long 51 | lines makes the code unnecessarily hard to read. 52 | - Everything should be properly Javadoc'ed. Everything. Including 53 | private stuff (except maybe 1-line private helper functions). 54 | Document the RuntimeExceptions one should expect to handle. 55 | All javadoc comments are to be written in proper English. 56 | - The javadoc (internal and user-facing) must document the 57 | synchronization requirements. What is thread-safe? Which monitor 58 | needs to be acquired before accessing this attribute? 59 | - No checked exceptions. People should RTFM and handle whatever 60 | exceptions they want to handle. There's a disagreement in the 61 | community about the usefulness and effectiveness of checked 62 | exceptions. I haven't been convinced about the pros so I chose 63 | to not use them. 64 | - Use fine-grained exception types. Everything must derive from 65 | HBaseException. Exceptions should contain all the data required to 66 | help the user code recover from them. HBase's own code is a very 67 | good example of how to not (ab)use IOException. 68 | - Local variables are named_like_this, I think it's more readable 69 | compared to somethingLikeThis. I think there's a reason why latin 70 | languages put a space between words. 71 | 72 | Testing: 73 | - Write unit tests whenever possible, especially regression tests. 74 | - Integration tests need to exercise the functionality against a real 75 | HBase instance. You can run them with this command: 76 | $ HBASE_HOME=~/src/hbase make integration ARGS='test f' 77 | This will run the tests against a set of tables that all have names 78 | starting with `test' and families starting with `f'. The tables will 79 | be created / dropped when needed. 80 | - Tip: After you've run the integration tests once, you can speed up 81 | subsequent runs by passing TEST_NO_TRUNCATE=1 before HBASE_HOME on 82 | the command above. This will skip truncating the table in between 83 | tests, which makes them run much faster. 84 | - Tip: You can also specify only one integration test to run, by adding 85 | the following before HBASE_HOME on the command above: TEST_NAME=XXX. 86 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AsyncBigtable 2 | 3 | [![Travis CI status][travis-shield]][travis-link] 4 | [![Maven][maven-shield]][maven-link] 5 | [![Stack Overflow][stackoverflow-shield]][stackoverflow-link] 6 | 7 | This is an HBase library intended to work as a drop in replacement for the 8 | fantastic AsyncHBase library and integrate OpenTSDB with Google Bigtable. 9 | It is using the Apache HBase 1.0 API linking the Google Bigtable 10 | libraries. 11 | 12 | This library started out as a fork of the asynchbase 1.5.0 library, therefore one may 13 | find code that at first sight may look strange. We are working on cleaning 14 | up the code base and removing irrelevant dependencies. 15 | 16 | ## Basic Installation 17 | 18 | Contrary to the original `asynchbase` library, `asyncbigtable` has adopted Maven 19 | as the building tool for this project. 20 | 21 | To produce the jar file, simply run: 22 | 23 | mvn clean package 24 | 25 | Maven will produce the following two jar files under the `target/` directory: 26 | 27 | 1. `asyncbigtable-.jar` which is the compiled jar file 28 | 2. `asyncbigtable--jar-with-dependencies.jar` which is an assembly jar containing 29 | all dependencies required for asyncbigtable to run with OpenTSDB. Please note that this 30 | jar does not include all dependencies but only the ones for OpenTSDB. 31 | 32 | ## Javadoc 33 | 34 | Since AsyncBigtable tries to be 100% compatible with AsyncHBase, please read the 35 | [AsyncHBase javadoc](http://opentsdb.github.io/asynchbase/javadoc/index.html). 36 | 37 | ## Integration Tests 38 | 39 | Integration tests can be run as follows: 40 | 41 | mvn clean verify -Pbt-integration-test -Dgoogle.bigtable.project.id= -Dgoogle.bigtable.instance.id= 42 | 43 | ## Changelog 44 | 45 | This project uses [Semantic Versioning](http://semver.org/). 46 | 47 | ### 0.4.3 48 | 49 | - Updated dependency to `com.google.cloud.bigtable:bigtable-hbase-2.x-hadoop:1.23.0` 50 | - Added `FilterList.size()` to fix compatibility with asynchbase. 51 | 52 | ### 0.4.2 53 | 54 | - Updated dependency to `com.google.cloud.bigtable:bigtable-hbase-2.x-hadoop:1.9.0` 55 | 56 | ### 0.4.1 57 | 58 | - Updated dependency to `com.google.cloud.bigtable:bigtable-hbase-2.x-hadoop:1.8.0` 59 | 60 | ### 0.4.0 61 | 62 | - Updated dependency to `com.google.cloud.bigtable:bigtable-hbase-2.x:1.4.0` 63 | - Updated Java version to 1.8 64 | - Implemented true async support using HBase 2.0 async client API 65 | - Fixed concurrency issues 66 | - Added integration tests 67 | - Many more changes, since last release was long time ago 68 | 69 | ### 0.3.0 70 | 71 | - Updated dependency to `com.google.cloud.bigtable:bigtable-hbase-1.2:0.9.6` 72 | - Updated dependency to `protobuf-java:3.0.2` 73 | - Updated dependency to `netty-all 4.1.0.Final` 74 | 75 | ### 0.2.1 76 | 77 | - This is the first public release of the asyncbigtable library, that 78 | started out as a fork of the asynchbase 1.5.0 library. 79 | - Modified all HBase access operations to use the standard HBase 1.0 API calls 80 | - Added Google Bigtable 0.2.2 dependency 81 | - Changed project build system from Make to Maven 82 | - Added assembly Maven plugin to build uber jar for distribution with OpenTSDB 83 | 84 | ## Disclaimer 85 | 86 | Please note that the library is still under development and it was never meant 87 | to replace AsyncHBase when running with an HBase backend or be a general 88 | purpose HBase library. 89 | 90 | 91 | 92 | [travis-shield]: https://travis-ci.org/OpenTSDB/asyncbigtable.svg 93 | [travis-link]: https://travis-ci.org/OpenTSDB/asyncbigtable 94 | [maven-shield]: https://img.shields.io/maven-central/v/com.pythian.opentsdb/asyncbigtable.svg 95 | [maven-link]: https://search.maven.org/#search%7Cga%7C1%7Ccom.pythian.opentsdb 96 | [stackoverflow-shield]: https://img.shields.io/badge/stackoverflow-opentsdb-green.svg 97 | [stackoverflow-link]: https://stackoverflow.com/questions/tagged/opentsdb 98 | -------------------------------------------------------------------------------- /THANKS: -------------------------------------------------------------------------------- 1 | AsyncHBase THANKS File 2 | ---------------------- 3 | 4 | The following persons contributed to the library by reporting problems, 5 | suggesting improvements, submitting patches or proofreading the code. 6 | 7 | Andrey Stepachev 8 | Arthur van Hoff 9 | Berk D. Demir 10 | Brandon Forehand 11 | Guo Sijie 12 | Ishan Chhabra 13 | James Baldassari 14 | Jonathan Payne 15 | Michael Rose 16 | Michael Stack 17 | Nicolas Thiébaud 18 | Phil Smith 19 | Shrijeet Paliwal 20 | Michael Stack 21 | Viral Bajaria 22 | Xun Liu 23 | 24 | This list can be obtained at any time with the following one-liner: 25 | git log --pretty=format:'%an' | sort -u 26 | -------------------------------------------------------------------------------- /assembly.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | jar-with-dependencies 7 | 8 | jar 9 | 10 | false 11 | 12 | 13 | / 14 | true 15 | true 16 | runtime 17 | 18 | com.google.guava:guava 19 | com.stumbleupon:async 20 | org.slf4j:slf4j-api 21 | org.slf4j:log4j-over-slf4j 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | com.pythian.opentsdb 5 | asyncbigtable 6 | 0.4.3 7 | jar 8 | 9 | Async Bigtable library 10 | 11 | Pythian 12 | http://www.pythian.com 13 | 14 | 15 | A drop in replacement for the AsyncHBase library and integrate OpenTSDB with Google Bigtable. 16 | 17 | https://github.com/OpenTSDB/asyncbigtable 18 | 19 | 20 | BSD 21 | http://www.opensource.org/licenses/BSD-3-Clause 22 | repo 23 | 24 | 25 | 26 | scm:git:git@github.com:OpenTSDB/asyncbigtable.git 27 | scm:git:git@github.com:OpenTSDB/asyncbigtable.git 28 | https://github.com/OpenTSDB/asyncbigtable 29 | HEAD 30 | 31 | 32 | GitHub 33 | https://github.com/OpenTSDB/asyncbigtable/issues 34 | 35 | 36 | 37 | 38 | tsuna 39 | Benoit "tsuna" Sigoure 40 | tsunanet@gmail.com 41 | 42 | developer 43 | 44 | -8 45 | 46 | 47 | csoulios 48 | Christos Soulios 49 | soulios@pythian.com 50 | 51 | developer 52 | 53 | +2 54 | 55 | 56 | sduskis 57 | Solomon Duskios 58 | sduskis@google.com 59 | 60 | developer 61 | 62 | -5 63 | 64 | 65 | 2010 66 | 67 | 68 | 69 | ossrh 70 | https://oss.sonatype.org/content/repositories/snapshots 71 | 72 | 73 | ossrh 74 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 75 | 76 | 77 | 78 | 79 | 80 | doclint-java8-disable 81 | 82 | [1.8,) 83 | 84 | 85 | -Xdoclint:none 86 | 87 | 88 | 89 | 90 | release 91 | 92 | 93 | 94 | org.apache.maven.plugins 95 | maven-source-plugin 96 | 2.2.1 97 | 98 | 99 | attach-sources 100 | 101 | jar 102 | 103 | 104 | 105 | 106 | 107 | 108 | org.apache.maven.plugins 109 | maven-javadoc-plugin 110 | 2.10.3 111 | 112 | 113 | attach-javadocs 114 | 115 | jar 116 | 117 | 118 | ${javadoc.opts} 119 | 120 | 121 | 122 | 123 | true 124 | true 125 | 126 | Copyright © {inceptionYear}-{currentYear}, 127 | ${project.organization.name} 128 | 129 | 130 | 131 | 132 | 133 | org.apache.maven.plugins 134 | maven-gpg-plugin 135 | 3.0.1 136 | 137 | 138 | sign-artifacts 139 | verify 140 | 141 | sign 142 | 143 | 144 | 145 | 146 | 147 | 148 | org.sonatype.plugins 149 | nexus-staging-maven-plugin 150 | 1.6.8 151 | true 152 | 153 | ossrh 154 | https://oss.sonatype.org/ 155 | true 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | bt-integration-test 164 | 165 | bt-integration-test 166 | 167 | 168 | 169 | 170 | maven-failsafe-plugin 171 | 2.18.1 172 | 173 | 174 | 175 | integration-test 176 | verify 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | org.apache.maven.plugins 195 | maven-compiler-plugin 196 | 2.5.1 197 | 198 | 1.8 199 | 1.8 200 | -Xlint 201 | 202 | 203 | 204 | 205 | org.apache.maven.plugins 206 | maven-assembly-plugin 207 | 2.5.5 208 | 209 | 210 | assembly.xml 211 | 212 | 213 | 214 | 215 | make-assembly 216 | package 217 | 218 | single 219 | 220 | 221 | 222 | 223 | 224 | 225 | org.apache.maven.plugins 226 | maven-release-plugin 227 | 2.5.3 228 | 229 | 230 | 231 | 232 | 233 | 234 | com.stumbleupon 235 | async 236 | 1.4.1 237 | 238 | 239 | 240 | org.slf4j 241 | slf4j-api 242 | 1.7.7 243 | 244 | 245 | 246 | 247 | com.google.guava 248 | guava 249 | 18.0 250 | 251 | 252 | 253 | com.google.cloud.bigtable 254 | bigtable-hbase-2.x-hadoop 255 | 1.23.0 256 | 257 | 258 | 259 | 260 | 261 | org.slf4j 262 | log4j-over-slf4j 263 | 1.7.7 264 | runtime 265 | 266 | 267 | 268 | commons-lang 269 | commons-lang 270 | 2.6 271 | 272 | 273 | 274 | commons-configuration 275 | commons-configuration 276 | 1.10 277 | 278 | 279 | 280 | 281 | 282 | org.hamcrest 283 | hamcrest-core 284 | 1.3 285 | test 286 | 287 | 288 | 289 | junit 290 | junit 291 | 4.13.1 292 | test 293 | 294 | 295 | 296 | org.javassist 297 | javassist 298 | 3.18.1-GA 299 | test 300 | 301 | 302 | 303 | org.mockito 304 | mockito-all 305 | 1.9.5 306 | test 307 | 308 | 309 | 310 | org.objenesis 311 | objenesis 312 | 2.1 313 | test 314 | 315 | 316 | 317 | org.powermock 318 | powermock-module-junit4 319 | 1.5.4 320 | test 321 | 322 | 323 | 324 | org.powermock 325 | powermock-api-mockito 326 | 1.5.4 327 | test 328 | 329 | 330 | 331 | 332 | 333 | UTF-8 334 | 335 | 336 | 337 | -------------------------------------------------------------------------------- /screwdriver.yaml: -------------------------------------------------------------------------------- 1 | shared: 2 | image: maven:3-adoptopenjdk-8 3 | 4 | jobs: 5 | pr: 6 | steps: 7 | - run_arbitrary_script: mvn clean test --quiet 8 | main: 9 | requires: [~pr, ~commit] 10 | steps: 11 | - run_arbitrary_script: mvn clean test --quiet 12 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/AppendRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 The Async BigTable Authors. All rights reserved. 3 | * This file is part of Async BigTable. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | /** 30 | * Appends data to one or more columns in BigTable, creating the columns if they 31 | * do not exist. The {@code value} is simply concatenated with whatever is 32 | * already in the column. An append operation will acquire a lock on the row 33 | * so that all column operations are atomic with respect to writers. However 34 | * reads across the row are not atomic and therefore readers may see partially 35 | * completed operations. 36 | *

37 | * Note that the results of the append operation 38 | * are not returned at this time. Issue a {@link GetRequest} to fetch the results. 39 | *

40 | *

A note on passing {@code byte} arrays in argument

41 | * None of the method that receive a {@code byte[]} in argument will copy it. 42 | * For more info, please refer to the documentation of {@link HBaseRpc}. 43 | *

A note on passing {@code String}s in argument

44 | * All strings are assumed to use the platform's default charset. 45 | *

A note on passing {@code timestamp}s in argument

46 | * BigTable orders all the writes based on timestamps from {@code AppendRequest} 47 | * irrespective of the actual order in which they're received or stored by 48 | * a RegionServer. In other words, if you send a first {@code AppendRequest} 49 | * with timestamp T, and then later send another one for the same table, 50 | * key, family and qualifier, but with timestamp T - 1, then the second 51 | * write will look like it was applied before the first one when you read 52 | * this cell back from BigTable. When manually setting timestamps, it is thus 53 | * strongly recommended to use real UNIX timestamps in milliseconds, e.g. 54 | * from {@link System#currentTimeMillis}. 55 | *

56 | * If you want to let BigTable set the timestamp on a write at the time it's 57 | * applied within the RegionServer, then use {@link KeyValue#TIMESTAMP_NOW} 58 | * as a timestamp. The timestamp is set right before being written to the WAL 59 | * (Write Ahead Log). Note however that this has a subtle consequence: if a 60 | * write succeeds from the server's point of view, but fails from the client's 61 | * point of view (maybe because the client got disconnected from the server 62 | * before the server could acknowledge the write), then if the client retries 63 | * the write it will create another version of the cell with a different 64 | * timestamp. 65 | * @since 1.7 66 | */ 67 | public final class AppendRequest extends BatchableRpc 68 | implements HBaseRpc.HasTable, HBaseRpc.HasKey, HBaseRpc.HasFamily, 69 | HBaseRpc.HasQualifiers, HBaseRpc.HasValues, HBaseRpc.IsEdit, 70 | /* legacy: */ HBaseRpc.HasQualifier, HBaseRpc.HasValue { 71 | 72 | /** 73 | * Invariants: 74 | * - qualifiers.length == values.length 75 | * - qualifiers.length > 0 76 | */ 77 | private final byte[][] qualifiers; 78 | private final byte[][] values; 79 | 80 | /** Whether or not to return the result of the append request */ 81 | private boolean return_result = false; 82 | 83 | /** 84 | * Constructor using current time. 85 | * These byte arrays will NOT be copied. 86 | *

87 | * Note: If you want to set your own timestamp, use 88 | * {@link #AppendRequest(byte[], byte[], byte[], byte[], byte[], long)} 89 | * instead. This constructor will let the RegionServer assign the timestamp 90 | * to this write at the time using {@link System#currentTimeMillis} right 91 | * before the write is persisted to the WAL. 92 | * @param table The table to edit. 93 | * @param key The key of the row to edit in that table. 94 | * @param family The column family to edit in that table. 95 | * @param qualifier The column qualifier to edit in that family. 96 | * @param value The value to store. 97 | */ 98 | public AppendRequest(final byte[] table, 99 | final byte[] key, 100 | final byte[] family, 101 | final byte[] qualifier, 102 | final byte[] value) { 103 | this(table, key, family, qualifier, value, KeyValue.TIMESTAMP_NOW); 104 | } 105 | 106 | /** 107 | * Constructor for multiple columns using current time. 108 | * These byte arrays will NOT be copied. 109 | *

110 | * Note: If you want to set your own timestamp, use 111 | * {@link #AppendRequest(byte[], byte[], byte[], byte[][], byte[][], long)} 112 | * instead. This constructor will let the RegionServer assign the timestamp 113 | * to this write at the time using {@link System#currentTimeMillis} right 114 | * before the write is persisted to the WAL. 115 | * @param table The table to edit. 116 | * @param key The key of the row to edit in that table. 117 | * @param family The column family to edit in that table. 118 | * @param qualifiers The column qualifiers to edit in that family. 119 | * @param values The corresponding values to store. 120 | * @throws IllegalArgumentException if {@code qualifiers.length == 0} 121 | * or if {@code qualifiers.length != values.length} 122 | */ 123 | public AppendRequest(final byte[] table, 124 | final byte[] key, 125 | final byte[] family, 126 | final byte[][] qualifiers, 127 | final byte[][] values) { 128 | this(table, key, family, qualifiers, values, KeyValue.TIMESTAMP_NOW, false); 129 | } 130 | 131 | /** 132 | * Constructor for a specific timestamp. 133 | * These byte arrays will NOT be copied. 134 | * @param table The table to edit. 135 | * @param key The key of the row to edit in that table. 136 | * @param family The column family to edit in that table. 137 | * @param qualifier The column qualifier to edit in that family. 138 | * @param value The value to store. 139 | * @param timestamp The timestamp to set on this edit. 140 | */ 141 | public AppendRequest(final byte[] table, 142 | final byte[] key, 143 | final byte[] family, 144 | final byte[] qualifier, 145 | final byte[] value, 146 | final long timestamp) { 147 | this(table, key, family, new byte[][] { qualifier }, 148 | new byte[][] { value }, timestamp, false); 149 | } 150 | 151 | /** 152 | * Constructor for multiple columns with a specific timestamp. 153 | * These byte arrays will NOT be copied. 154 | * @param table The table to edit. 155 | * @param key The key of the row to edit in that table. 156 | * @param family The column family to edit in that table. 157 | * @param qualifiers The column qualifiers to edit in that family. 158 | * @param values The corresponding values to store. 159 | * @param timestamp The timestamp to set on this edit. 160 | * @throws IllegalArgumentException if {@code qualifiers.length == 0} 161 | * or if {@code qualifiers.length != values.length} 162 | */ 163 | public AppendRequest(final byte[] table, 164 | final byte[] key, 165 | final byte[] family, 166 | final byte[][] qualifiers, 167 | final byte[][] values, 168 | final long timestamp) { 169 | this(table, key, family, qualifiers, values, timestamp, false); 170 | } 171 | 172 | /** 173 | * Constructor from a {@link KeyValue}. 174 | * @param table The table to edit. 175 | * @param kv The {@link KeyValue} to store. 176 | */ 177 | public AppendRequest(final byte[] table, 178 | final KeyValue kv) { 179 | super(table, kv.key(), kv.family(), kv.timestamp(), RowLock.NO_LOCK); 180 | this.qualifiers = new byte[][] { kv.qualifier() }; 181 | this.values = new byte[][] { kv.value() }; 182 | } 183 | 184 | /** Private constructor. */ 185 | private AppendRequest(final byte[] table, 186 | final byte[] key, 187 | final byte[] family, 188 | final byte[][] qualifiers, 189 | final byte[][] values, 190 | final long timestamp, 191 | final boolean return_result) { 192 | super(table, key, family, timestamp, RowLock.NO_LOCK); 193 | KeyValue.checkFamily(family); 194 | 195 | if (qualifiers.length != values.length) { 196 | throw new IllegalArgumentException("Have " + qualifiers.length 197 | + " qualifiers and " + values.length + " values. Should be equal."); 198 | } else if (qualifiers.length == 0) { 199 | throw new IllegalArgumentException("Need at least one qualifier/value."); 200 | } 201 | for (int i = 0; i < qualifiers.length; i++) { 202 | KeyValue.checkQualifier(qualifiers[i]); 203 | KeyValue.checkValue(values[i]); 204 | } 205 | this.qualifiers = qualifiers; 206 | this.values = values; 207 | } 208 | 209 | @Override 210 | public byte[] table() { 211 | return table; 212 | } 213 | 214 | @Override 215 | public byte[] key() { 216 | return key; 217 | } 218 | 219 | /** 220 | * Returns the first qualifier of the set of edits in this RPC. 221 | * {@inheritDoc} 222 | */ 223 | @Override 224 | public byte[] qualifier() { 225 | return qualifiers[0]; 226 | } 227 | 228 | /** 229 | * {@inheritDoc} 230 | */ 231 | @Override 232 | public byte[][] qualifiers() { 233 | return qualifiers; 234 | } 235 | 236 | /** 237 | * Returns the first value of the set of edits in this RPC. 238 | * {@inheritDoc} 239 | */ 240 | @Override 241 | public byte[] value() { 242 | return values[0]; 243 | } 244 | 245 | /** 246 | * {@inheritDoc} 247 | */ 248 | @Override 249 | public byte[][] values() { 250 | return values; 251 | } 252 | 253 | public String toString() { 254 | return super.toStringWithQualifiers("AppendRequest", 255 | family, qualifiers, values, 256 | ", timestamp=" + timestamp 257 | + ", lockid=" + lockid 258 | + ", durable=" + durable 259 | + ", return_result=" + return_result 260 | + ", bufferable=" + super.bufferable); 261 | } 262 | 263 | /** @param return_result Whether or not to fetch the results of the append 264 | * from HBase. */ 265 | public void returnResult(boolean return_result) { 266 | this.return_result = return_result; 267 | } 268 | 269 | /** @return Whether or not to fetch the results of the append from HBase. */ 270 | public boolean returnResult() { 271 | return return_result; 272 | } 273 | 274 | } -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/AtomicIncrementRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 The Async BigTable Authors. All rights reserved. 3 | * This file is part of Async BigTable. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | /** 30 | * Atomically increments a value in BigTable. 31 | * 32 | *

A note on passing {@code byte} arrays in argument

33 | * None of the method that receive a {@code byte[]} in argument will copy it. 34 | * For more info, please refer to the documentation of {@link HBaseRpc}. 35 | *

A note on passing {@code String}s in argument

36 | * All strings are assumed to use the platform's default charset. 37 | */ 38 | public final class AtomicIncrementRequest extends HBaseRpc 39 | implements HBaseRpc.HasTable, HBaseRpc.HasKey, 40 | HBaseRpc.HasFamily, HBaseRpc.HasQualifier, HBaseRpc.IsEdit { 41 | 42 | 43 | private final byte[] family; 44 | private final byte[] qualifier; 45 | private long amount; 46 | private boolean durable = true; 47 | 48 | /** 49 | * Constructor. 50 | * These byte arrays will NOT be copied. 51 | * @param table The non-empty name of the table to use. 52 | * @param key The row key of the value to increment. 53 | * @param family The column family of the value to increment. 54 | * @param qualifier The column qualifier of the value to increment. 55 | * @param amount Amount by which to increment the value in BigTable. 56 | * If negative, the value in BigTable will be decremented. 57 | */ 58 | public AtomicIncrementRequest(final byte[] table, 59 | final byte[] key, 60 | final byte[] family, 61 | final byte[] qualifier, 62 | final long amount) { 63 | super(table, key); 64 | KeyValue.checkFamily(family); 65 | KeyValue.checkQualifier(qualifier); 66 | this.family = family; 67 | this.qualifier = qualifier; 68 | this.amount = amount; 69 | } 70 | 71 | /** 72 | * Constructor. This is equivalent to: 73 | * {@link #AtomicIncrementRequest(byte[], byte[], byte[], byte[], long) 74 | * AtomicIncrementRequest}{@code (table, key, family, qualifier, 1)} 75 | *

76 | * These byte arrays will NOT be copied. 77 | * @param table The non-empty name of the table to use. 78 | * @param key The row key of the value to increment. 79 | * @param family The column family of the value to increment. 80 | * @param qualifier The column qualifier of the value to increment. 81 | */ 82 | public AtomicIncrementRequest(final byte[] table, 83 | final byte[] key, 84 | final byte[] family, 85 | final byte[] qualifier) { 86 | this(table, key, family, qualifier, 1); 87 | } 88 | 89 | /** 90 | * Constructor. 91 | * All strings are assumed to use the platform's default charset. 92 | * @param table The non-empty name of the table to use. 93 | * @param key The row key of the value to increment. 94 | * @param family The column family of the value to increment. 95 | * @param qualifier The column qualifier of the value to increment. 96 | * @param amount Amount by which to increment the value in BigTable. 97 | * If negative, the value in BigTable will be decremented. 98 | */ 99 | public AtomicIncrementRequest(final String table, 100 | final String key, 101 | final String family, 102 | final String qualifier, 103 | final long amount) { 104 | this(table.getBytes(), key.getBytes(), family.getBytes(), 105 | qualifier.getBytes(), amount); 106 | } 107 | 108 | /** 109 | * Constructor. This is equivalent to: 110 | * All strings are assumed to use the platform's default charset. 111 | * {@link #AtomicIncrementRequest(String, String, String, String, long) 112 | * AtomicIncrementRequest}{@code (table, key, family, qualifier, 1)} 113 | * @param table The non-empty name of the table to use. 114 | * @param key The row key of the value to increment. 115 | * @param family The column family of the value to increment. 116 | * @param qualifier The column qualifier of the value to increment. 117 | */ 118 | public AtomicIncrementRequest(final String table, 119 | final String key, 120 | final String family, 121 | final String qualifier) { 122 | this(table.getBytes(), key.getBytes(), family.getBytes(), 123 | qualifier.getBytes(), 1); 124 | } 125 | 126 | /** 127 | * Returns the amount by which the value is going to be incremented. 128 | */ 129 | public long getAmount() { 130 | return amount; 131 | } 132 | 133 | /** 134 | * Changes the amount by which the value is going to be incremented. 135 | * @param amount The new amount. If negative, the value will be decremented. 136 | */ 137 | public void setAmount(final long amount) { 138 | this.amount = amount; 139 | } 140 | 141 | 142 | @Override 143 | public byte[] table() { 144 | return table; 145 | } 146 | 147 | @Override 148 | public byte[] key() { 149 | return key; 150 | } 151 | 152 | @Override 153 | public byte[] family() { 154 | return family; 155 | } 156 | 157 | @Override 158 | public byte[] qualifier() { 159 | return qualifier; 160 | } 161 | 162 | public String toString() { 163 | return super.toStringWithQualifier("AtomicIncrementRequest", 164 | family, qualifier, 165 | ", amount=" + amount); 166 | } 167 | 168 | // ---------------------- // 169 | // Package private stuff. // 170 | // ---------------------- // 171 | 172 | /** 173 | * Changes whether or not this atomic increment should use the WAL. 174 | * @param durable {@code true} to use the WAL, {@code false} otherwise. 175 | */ 176 | void setDurable(final boolean durable) { 177 | this.durable = durable; 178 | } 179 | 180 | boolean isDurable() { 181 | return this.durable; 182 | } 183 | 184 | } 185 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/BatchableRpc.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 The Async BigTable Authors. All rights reserved. 3 | * This file is part of Async BigTable. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | /** 30 | * An intermediate abstract class for all RPC requests that can be batched. 31 | *

32 | * This class is internal only and doesn't provide any user-facing API other 33 | * than guaranteeing that the RPC has a family and a timestamp. 34 | */ 35 | abstract class BatchableRpc extends HBaseRpc 36 | implements HBaseRpc.HasFamily, HBaseRpc.HasTimestamp { 37 | 38 | // Attributes should have `protected' visibility, but doing so exposes 39 | // them as part of the public API and in Javadoc, which we don't want. 40 | // So instead we make them package-private so that subclasses can still 41 | // access them directly. 42 | 43 | /** Family affected by this RPC. */ 44 | final byte[] family; 45 | 46 | /** The timestamp to use for {@link KeyValue}s of this RPC. */ 47 | final long timestamp; 48 | 49 | /** 50 | * Explicit row lock to use, if any. 51 | * @see RowLock 52 | */ 53 | final long lockid; 54 | 55 | /** 56 | * Whether or not this batchable RPC can be buffered on the client side. 57 | * Please call {@link #canBuffer} to check if this RPC can be buffered, 58 | * don't test this field directly. 59 | */ 60 | boolean bufferable = true; 61 | 62 | /** 63 | * Whether or not the RegionServer must write to its WAL (Write Ahead Log). 64 | */ 65 | boolean durable = true; 66 | 67 | /** 68 | * Package private constructor. 69 | * @param table The name of the table this RPC is for. 70 | * @param row The name of the row this RPC is for. 71 | * @param family The column family to edit in that table. Subclass must 72 | * validate, this class doesn't perform any validation on the family. 73 | * @param timestamp The timestamp to use for {@link KeyValue}s of this RPC. 74 | * @param lockid Explicit row lock to use, or {@link RowLock#NO_LOCK}. 75 | */ 76 | BatchableRpc(final byte[] table, 77 | final byte[] key, final byte[] family, 78 | final long timestamp, final long lockid) { 79 | super(table, key); 80 | this.family = family; 81 | this.timestamp = timestamp; 82 | this.lockid = lockid; 83 | } 84 | 85 | /** 86 | * Sets whether or not this RPC is can be buffered on the client side. 87 | * The default is {@code true}. 88 | *

89 | * Setting this to {@code false} bypasses the client-side buffering, which 90 | * is used to send RPCs in batches for greater throughput, and causes this 91 | * RPC to be sent directly to the server. 92 | * @param bufferable Whether or not this RPC can be buffered (i.e. delayed) 93 | * before being sent out to BigTable. 94 | * @see HBaseClient#setFlushInterval 95 | */ 96 | public final void setBufferable(final boolean bufferable) { 97 | this.bufferable = bufferable; 98 | } 99 | 100 | /** 101 | * Changes the durability setting of this edit. 102 | * The default is {@code true}. 103 | * Make sure you've read and understood the 104 | * data durability section before 105 | * setting this to {@code false}. 106 | * @param durable Whether or not this edit should be stored with data 107 | * durability guarantee. 108 | */ 109 | public final void setDurable(final boolean durable) { 110 | this.durable = durable; 111 | } 112 | 113 | @Override 114 | public final byte[] family() { 115 | return family; 116 | } 117 | 118 | @Override 119 | public final long timestamp() { 120 | return timestamp; 121 | } 122 | 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/BinaryPrefixComparator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014-2017 The Async HBase Authors. All rights reserved. 3 | * This file is part of Async HBase. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | import java.lang.reflect.Field; 30 | 31 | import org.apache.hadoop.hbase.filter.ByteArrayComparable; 32 | import org.apache.hadoop.hbase.filter.RegexStringComparator; 33 | 34 | /** 35 | * A binary comparator used in comparison filters. Compares byte arrays 36 | * lexicographically up to the length of the provided byte array. 37 | * @since 1.6 38 | */ 39 | public final class BinaryPrefixComparator extends FilterComparator { 40 | 41 | private static final byte[] NAME = 42 | Bytes.UTF8("org.apache.hadoop.hbase.filter.BinaryPrefixComparator"); 43 | private static final byte CODE = 47; 44 | 45 | private final byte[] value; 46 | 47 | public BinaryPrefixComparator(byte[] value) { 48 | this.value = value; 49 | } 50 | 51 | public byte[] value() { 52 | return value.clone(); 53 | } 54 | 55 | @Override 56 | byte[] name() { 57 | return NAME; 58 | } 59 | 60 | @Override 61 | public String toString() { 62 | return String.format("%s(%s)", 63 | getClass().getSimpleName(), 64 | Bytes.pretty(value)); 65 | } 66 | 67 | public ByteArrayComparable getBigtableFilter() { 68 | // NOTE: Bigtable doesn't support the BinaryPrefixComparator (grrrr). 69 | // Se https://cloud.google.com/bigtable/docs/hbase-differences#filters. 70 | // So we have to convert it to a regex filter. 71 | StringBuilder buf = new StringBuilder() 72 | .append("(?s)\\Q"); 73 | 74 | for (int i = 0; i < value.length; i++) { 75 | buf.append((char) (value[i] & 0xFF)); 76 | } 77 | buf.append("\\E.*"); 78 | try { 79 | // WARNING: This is some ugly ass code. It WILL break at some point. 80 | // Bigtable uses RE2 and runs in raw byte mode. TSDB writes regex with 81 | // byte values but when passing it through the HTable APIs it's converted 82 | // to UTF and serializes differently than the old AsyncHBase client. The 83 | // native BigTable client will pass the regex along properly BUT we need 84 | // to bypass the RegexStringComparator methods and inject our ASCII regex 85 | // directly into the underlying comparator object. Hopefully this is 86 | // temporary (famous last words) until we get to a native Bigtable wrapper. 87 | RegexStringComparator comparator = new RegexStringComparator(buf.toString()); 88 | final Field field = ByteArrayComparable.class.getDeclaredField("value"); 89 | field.setAccessible(true); 90 | field.set(comparator, buf.toString().getBytes(HBaseClient.ASCII)); 91 | field.setAccessible(false); 92 | return comparator; 93 | } catch (NoSuchFieldException e) { 94 | throw new RuntimeException("ByteArrayComparator must have changed, " 95 | + "can't find the field", e); 96 | } catch (IllegalAccessException e) { 97 | throw new RuntimeException("Access denied when hacking the " 98 | + "regex comparator field", e); 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/ColumnPrefixFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014-2017 The Async HBase Authors. All rights reserved. 3 | * This file is part of Async HBase. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | import org.apache.hadoop.hbase.filter.Filter; 30 | 31 | public final class ColumnPrefixFilter extends ScanFilter { 32 | 33 | private static final byte[] NAME = 34 | Bytes.UTF8("org.apache.hadoop.hbase.filter.ColumnPrefixFilter"); 35 | private final byte[] prefix; 36 | 37 | public byte[] getPrefix() { 38 | return this.prefix; 39 | } 40 | 41 | public ColumnPrefixFilter(byte[] prefix) { 42 | this.prefix = prefix; 43 | } 44 | 45 | Filter getBigtableFilter() { 46 | return new org.apache.hadoop.hbase.filter.ColumnPrefixFilter(prefix); 47 | } 48 | 49 | @Override 50 | byte[] name() { 51 | return NAME; 52 | } 53 | 54 | public String toString() { 55 | return "ColumnPrefixFilter(" + Bytes.pretty(prefix) + ")"; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/CompareAndSetRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 The Async BigTable Authors. All rights reserved. 3 | * This file is part of Async BigTable. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | /** 30 | * Atomically executes a Compare-And-Set (CAS) on an HBase cell. 31 | *

32 | * This class is package-private just to reduce the amount of public API, 33 | * but it could be exposed if needed. 34 | */ 35 | final class CompareAndSetRequest extends HBaseRpc 36 | implements HBaseRpc.HasTable, HBaseRpc.HasKey, 37 | HBaseRpc.HasFamily, HBaseRpc.HasQualifier, HBaseRpc.HasValue, 38 | HBaseRpc.IsEdit { 39 | 40 | /** New value. */ 41 | private final PutRequest put; 42 | 43 | /** Expected value. */ 44 | private final byte[] expected; 45 | 46 | /** 47 | * Constructor. 48 | * @param put Put request to execute if value matches. 49 | * @param value The expected value to compare against. 50 | * This byte array will NOT be copied. 51 | */ 52 | public CompareAndSetRequest(final PutRequest put, 53 | final byte[] expected) { 54 | super(put.table(), put.key()); 55 | KeyValue.checkValue(expected); 56 | this.put = put; 57 | this.expected = expected; 58 | } 59 | 60 | 61 | @Override 62 | public byte[] table() { 63 | return put.table(); 64 | } 65 | 66 | @Override 67 | public byte[] key() { 68 | return put.key(); 69 | } 70 | 71 | @Override 72 | public byte[] family() { 73 | return put.family(); 74 | } 75 | 76 | @Override 77 | public byte[] qualifier() { 78 | return put.qualifier(); 79 | } 80 | 81 | /** 82 | * Returns the expected value. 83 | *

84 | * DO NOT MODIFY THE CONTENTS OF THE ARRAY RETURNED. 85 | */ 86 | public byte[] expectedValue() { 87 | return expected; 88 | } 89 | 90 | /** 91 | * Returns the new value. 92 | * {@inheritDoc} 93 | */ 94 | @Override 95 | public byte[] value() { 96 | return put.value(); 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/CompareFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014-2017 The Async HBase Authors. All rights reserved. 3 | * This file is part of Async HBase. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | /** 30 | * A generic scan filter to be used to filter by comparison. It takes an 31 | * operator (equal, greater, not equal, etc) and a filter comparator. 32 | * @since 1.6 33 | */ 34 | public abstract class CompareFilter extends ScanFilter { 35 | 36 | /** Comparison operators. */ 37 | public enum CompareOp { 38 | /** less than */ 39 | LESS, 40 | /** less than or equal to */ 41 | LESS_OR_EQUAL, 42 | /** equals */ 43 | EQUAL, 44 | /** not equal */ 45 | NOT_EQUAL, 46 | /** greater than or equal to */ 47 | GREATER_OR_EQUAL, 48 | /** greater than */ 49 | GREATER, 50 | /** no operation */ 51 | NO_OP; 52 | 53 | static org.apache.hadoop.hbase.filter.CompareFilter.CompareOp convert(final CompareOp op) { 54 | switch(op) { 55 | case LESS: 56 | return org.apache.hadoop.hbase.filter.CompareFilter.CompareOp.LESS; 57 | case LESS_OR_EQUAL: 58 | return org.apache.hadoop.hbase.filter.CompareFilter.CompareOp.LESS_OR_EQUAL; 59 | case EQUAL: 60 | return org.apache.hadoop.hbase.filter.CompareFilter.CompareOp.EQUAL; 61 | case NOT_EQUAL: 62 | return org.apache.hadoop.hbase.filter.CompareFilter.CompareOp.NOT_EQUAL; 63 | case GREATER_OR_EQUAL: 64 | return org.apache.hadoop.hbase.filter.CompareFilter.CompareOp.GREATER_OR_EQUAL; 65 | case GREATER: 66 | return org.apache.hadoop.hbase.filter.CompareFilter.CompareOp.GREATER; 67 | default: 68 | return org.apache.hadoop.hbase.filter.CompareFilter.CompareOp.NO_OP; 69 | } 70 | } 71 | } 72 | 73 | protected final CompareOp compare_op; 74 | protected final FilterComparator comparator; 75 | 76 | public CompareFilter(final CompareOp compareOp, 77 | final FilterComparator comparator) { 78 | this.compare_op = compareOp; 79 | this.comparator = comparator; 80 | } 81 | 82 | public CompareOp compareOperation() { 83 | return compare_op; 84 | } 85 | 86 | public FilterComparator comparator() { 87 | return comparator; 88 | } 89 | 90 | @Override 91 | public String toString() { 92 | return String.format("%s(%s, %s)", 93 | getClass().getSimpleName(), 94 | compare_op.name(), 95 | comparator.toString()); 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/Counter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 The Async BigTable Authors. All rights reserved. 3 | * This file is part of Async BigTable. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | import org.hbase.async.jsr166e.LongAdder; 30 | 31 | /** 32 | * An atomic counter to replace {@link java.util.concurrent.atomic.AtomicLong}. 33 | *

34 | * This is based on JSR 166e's sharded counter, which is slated for JDK8. 35 | * This class is part of the public interface of asynchbase, and code 36 | * depending on asynchbase is encouraged to use it for their concurrent 37 | * counter needs. 38 | */ 39 | public final class Counter extends LongAdder { 40 | 41 | /** 42 | * Returns the current value of the counter. 43 | */ 44 | public final long get() { 45 | return super.sum(); 46 | } 47 | 48 | private static final long serialVersionUID = 1333661542; 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/FilterComparator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014-2017 The Async HBase Authors. All rights reserved. 3 | * This file is part of Async HBase. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | import org.apache.hadoop.hbase.filter.ByteArrayComparable; 30 | import org.apache.hbase.thirdparty.io.netty.buffer.ByteBuf; 31 | 32 | /** 33 | * Abstract base class for {@link ScanFilter} comparators. 34 | *

35 | * These comparators are used by scan filters. 36 | *

37 | * Subclasses are guaranteed to be immutable and are thus 38 | * thread-safe as well as usable concurrently on multiple 39 | * {@link Scanner} instances. 40 | * @since 1.6 41 | */ 42 | public abstract class FilterComparator { 43 | 44 | // This class is the equivalent of HBase's WritableByteArrayComparable. 45 | // We don't need this class to be Writable or Comparable, so 46 | // FilterComparator is a more appropriate name. 47 | 48 | final static byte CODE = 54; 49 | 50 | /** 51 | * Returns the name of this scanner on the wire. 52 | *

53 | * This method is only used with HBase 0.95 and newer. 54 | * The contents of the array returned MUST NOT be modified. 55 | */ 56 | abstract byte[] name(); 57 | 58 | /** 59 | * Serializes the byte representation to the RPC channel buffer. 60 | *

61 | * This method is only used with HBase 0.94 and before. 62 | * @param buf The RPC channel buffer to which the byte array is serialized 63 | */ 64 | void serializeOld(ByteBuf buf) { 65 | buf.writeByte(CODE); // 1 66 | } 67 | 68 | /** 69 | * Returns the number of bytes that it will write to the RPC channel buffer 70 | * when {@code serialize} is called. This method helps predict the initial 71 | * size of the byte array 72 | *

73 | * This method is only used with HBase 0.94 and before. 74 | * @return A strictly positive integer 75 | */ 76 | int predictSerializedSize() { 77 | return 1; 78 | } 79 | 80 | /** 81 | * Converts the filter for Bigtable's HBase interface. 82 | * @return The converted filter. 83 | */ 84 | abstract ByteArrayComparable getBigtableFilter(); 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/FilterList.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015-2017 The Async BigTable Authors. All rights reserved. 3 | * This file is part of Async BigTable. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | import org.apache.hadoop.hbase.filter.Filter; 30 | 31 | import com.google.common.collect.ImmutableList; 32 | import com.google.common.collect.Lists; 33 | 34 | import java.util.List; 35 | 36 | /** 37 | * Combines a list of filters into one. 38 | * Since 1.5 39 | */ 40 | public final class FilterList extends ScanFilter { 41 | 42 | private static final byte[] NAME = Bytes.ISO88591("org.apache.hadoop" 43 | + ".hbase.filter.FilterList"); 44 | 45 | private final List scan_filters; 46 | private final List filters; 47 | private final Operator op; 48 | 49 | /** 50 | * Operator to combine the list of filters together. 51 | * since 1.5 52 | */ 53 | public enum Operator { 54 | /** All the filters must pass ("and" semantic). */ 55 | MUST_PASS_ALL, 56 | /** At least one of the filters must pass ("or" semantic). */ 57 | MUST_PASS_ONE; 58 | 59 | static org.apache.hadoop.hbase.filter.FilterList.Operator convert(final Operator op) { 60 | switch(op) { 61 | case MUST_PASS_ALL: 62 | return org.apache.hadoop.hbase.filter.FilterList.Operator.MUST_PASS_ALL; 63 | default: 64 | return org.apache.hadoop.hbase.filter.FilterList.Operator.MUST_PASS_ONE; 65 | } 66 | } 67 | } 68 | 69 | /** 70 | * Constructor. 71 | * Equivalent to {@link #FilterList(List, Operator) 72 | * FilterList}{@code (filters, }{@link Operator#MUST_PASS_ALL}{@code )} 73 | */ 74 | public FilterList(final List filters) { 75 | this(filters, Operator.MUST_PASS_ALL); 76 | } 77 | 78 | /** 79 | * Constructor. 80 | * @param filters The filters to combine. This list does not get 81 | * copied, do not mutate it after passing it to this object. 82 | * @param op The operator to use to combine the filters together. 83 | * @throws IllegalArgumentException if the list of filters is empty. 84 | */ 85 | public FilterList(final List filters, final Operator op) { 86 | if (filters.isEmpty()) { 87 | throw new IllegalArgumentException("Empty filter list"); 88 | } 89 | scan_filters = filters; 90 | this.filters = Lists.newArrayListWithCapacity(filters.size()); 91 | for (final ScanFilter f : filters) { 92 | this.filters.add(f.getBigtableFilter()); 93 | } 94 | this.op = op; 95 | } 96 | 97 | /** @return the number of filters in the filter list 98 | * @since 1.8 */ 99 | public int size() { 100 | // filter's can't be null here and shouldn't even be empty 101 | return filters.size(); 102 | } 103 | 104 | @Override 105 | byte[] name() { 106 | return NAME; 107 | } 108 | 109 | public String toString() { 110 | final StringBuilder buf = new StringBuilder(32 + filters.size() * 48); 111 | buf.append("FilterList(filters=["); 112 | for (final Filter filter : filters) { 113 | buf.append(filter.toString()); 114 | buf.append(", "); 115 | } 116 | buf.setLength(buf.length() - 2); // Remove the last ", " 117 | buf.append("], op=").append(op).append(")"); 118 | return buf.toString(); 119 | } 120 | 121 | /** @return An immutable copy of the filter list (though each filter could 122 | * still be modified) 123 | * @since 1.8 */ 124 | public List filters() { 125 | return ImmutableList.copyOf(scan_filters); 126 | } 127 | 128 | List getFilters() { 129 | return filters; 130 | } 131 | 132 | @Override 133 | Filter getBigtableFilter() { 134 | org.apache.hadoop.hbase.filter.FilterList list = 135 | new org.apache.hadoop.hbase.filter.FilterList(Operator.convert(op)); 136 | for (final Filter f : filters) { 137 | list.addFilter(f); 138 | } 139 | return list; 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/FuzzyRowFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015-2017 The Async BigTable Authors. All rights reserved. 3 | * This file is part of Async BigTable. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | import java.lang.IllegalArgumentException; 30 | import java.util.Collection; 31 | import java.util.List; 32 | 33 | import org.apache.hadoop.hbase.filter.Filter; 34 | import org.apache.hadoop.hbase.util.Pair; 35 | 36 | import com.google.common.collect.Lists; 37 | 38 | /** 39 | * FuzzyRowFilter is a server-side fast-forward filter that allows skipping 40 | * whole range of rows when scanning. The feature is available in HBase 41 | * 0.94.5 and above. 42 | *

43 | * It takes two byte array to match a rowkey, one to hold the fixed value 44 | * and one to hold a mask indicating which bytes of the rowkey must match the 45 | * fixed value. The two arrays must have the same length. 46 | *

47 | * Bytes in the mask can take two values, 0 meaning that the corresponding byte 48 | * in the rowkey must match the corresponding fixed byte and 1 meaning that the 49 | * corresponding byte in the rowkey can take any value. 50 | *

51 | * One can combine several {@link FuzzyFilterPair} to match multiple patterns at 52 | * once. 53 | *

54 | * Example : 55 | * You store logs with this rowkey design : 56 | * group(3bytes)timestamp(4bytes)severity(1byte) 57 | * 58 | * You want to get all FATAL("5") logs : 59 | * * Build a FuzzyFilterPair with 60 | * - rowkey : "????????5" 61 | * - fuzzy mask : "111111110" 62 | * And CRITICAL("4") logs only for web servers : 63 | * * Add another FuzzyFilterPair with 64 | * - rowkey : "web????4" 65 | * - fuzzy mask : "00011110" 66 | * 67 | * @since 1.7 68 | */ 69 | public final class FuzzyRowFilter extends ScanFilter { 70 | 71 | private static final byte[] NAME = 72 | Bytes.UTF8("org.apache.hadoop.hbase.filter.FuzzyRowFilter"); 73 | 74 | private final Collection filter_pairs; 75 | 76 | /** 77 | * Holds a pair of (row_key,fuzzy_mask) to use with {@link FuzzyRowFilter} 78 | */ 79 | public static class FuzzyFilterPair { 80 | private final byte[] row_key; 81 | private final byte[] fuzzy_mask; 82 | 83 | /** 84 | * Default Ctor 85 | * @param row_key The row key to use for matching 86 | * @param fuzzy_mask The row key mask to determine which of the bytes in 87 | * {@code row_key} should be matched. 88 | * @throws IllegalArgumentException if the keys are not the same length 89 | */ 90 | public FuzzyFilterPair(final byte[] row_key, final byte[] fuzzy_mask) { 91 | if ( row_key.length != fuzzy_mask.length ) { 92 | throw new IllegalArgumentException("Row key and fuzzy mask length " + 93 | "must match"); 94 | } 95 | this.row_key = row_key; 96 | this.fuzzy_mask = fuzzy_mask; 97 | } 98 | 99 | /** @return the row key base filter */ 100 | public byte[] getRowKey() { 101 | return row_key; 102 | } 103 | 104 | /** @return the row key mask */ 105 | public byte[] getFuzzyMask() { 106 | return fuzzy_mask; 107 | } 108 | 109 | @Override 110 | public String toString() { 111 | final StringBuilder buf = new StringBuilder(); 112 | buf.append("FuzzyFilterPair{row_key=") 113 | .append(Bytes.pretty(row_key)) 114 | .append(", mask=") 115 | .append(Bytes.pretty(fuzzy_mask)) 116 | .append("}"); 117 | return buf.toString(); 118 | } 119 | } 120 | 121 | /** 122 | * Default ctor that applies a single fuzzy filter against all row keys 123 | * @param filter_pair A single filter to apply to all row keys 124 | */ 125 | public FuzzyRowFilter(final FuzzyFilterPair filter_pair) { 126 | this.filter_pairs = java.util.Collections.singleton(filter_pair); 127 | } 128 | 129 | /** 130 | * Ctor to take a list of filters to apply against row keys 131 | * @param filter_pairs One or more filter pairs in a collection to apply 132 | * against the row keys 133 | */ 134 | public FuzzyRowFilter(final Collection filter_pairs) { 135 | this.filter_pairs = filter_pairs; 136 | } 137 | 138 | @Override 139 | byte[] name() { 140 | return NAME; 141 | } 142 | 143 | @Override 144 | public String toString() { 145 | final StringBuilder buf = new StringBuilder(); 146 | buf.append("FuzzyFilter{") 147 | .append(filter_pairs) 148 | .append("}"); 149 | return buf.toString(); 150 | } 151 | 152 | @Override 153 | Filter getBigtableFilter() { 154 | List> pairs = Lists.newArrayListWithCapacity(filter_pairs.size()); 155 | for (final FuzzyFilterPair pair : filter_pairs) { 156 | pairs.add(new Pair(pair.row_key, pair.fuzzy_mask)); 157 | } 158 | return new org.apache.hadoop.hbase.filter.FuzzyRowFilter(pairs); 159 | } 160 | 161 | } -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/GetRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 The Async BigTable Authors. All rights reserved. 3 | * This file is part of Async BigTable. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | /** 30 | * Reads something from BigTable. 31 | * 32 | *

A note on passing {@code byte} arrays in argument

33 | * None of the method that receive a {@code byte[]} in argument will copy it. 34 | * For more info, please refer to the documentation of {@link HBaseRpc}. 35 | *

A note on passing {@code String}s in argument

36 | * All strings are assumed to use the platform's default charset. 37 | */ 38 | public final class GetRequest extends HBaseRpc 39 | implements HBaseRpc.HasTable, HBaseRpc.HasKey, 40 | HBaseRpc.HasFamily, HBaseRpc.HasQualifiers { 41 | 42 | private byte[] family; // TODO(tsuna): Handle multiple families? 43 | private byte[][] qualifiers; 44 | 45 | /** 46 | * How many versions of each cell to retrieve. 47 | * The least significant bit is used as a flag to indicate when 48 | * this Get request is in fact an Exist request (i.e. like Get 49 | * except that instead of returning a result the RPC returns a 50 | * boolean indicating whether the row exists or not). 51 | */ 52 | private int versions = 1 << 1; 53 | 54 | /** When set in the `versions' field, this is an Exist RPC. */ 55 | private static final int EXIST_FLAG = 0x1; 56 | 57 | /** 58 | * Constructor. 59 | * These byte arrays will NOT be copied. 60 | * @param table The non-empty name of the table to use. 61 | * @param key The row key to get in that table. 62 | */ 63 | public GetRequest(final byte[] table, final byte[] key) { 64 | super(table, key); 65 | } 66 | 67 | /** 68 | * Constructor. 69 | * @param table The non-empty name of the table to use. 70 | * @param key The row key to get in that table. 71 | * This byte array will NOT be copied. 72 | */ 73 | public GetRequest(final String table, final byte[] key) { 74 | this(table.getBytes(), key); 75 | } 76 | 77 | /** 78 | * Constructor. 79 | * @param table The non-empty name of the table to use. 80 | * @param key The row key to get in that table. 81 | */ 82 | public GetRequest(final String table, final String key) { 83 | this(table.getBytes(), key.getBytes()); 84 | } 85 | 86 | /** 87 | * Constructor. 88 | * These byte arrays will NOT be copied. 89 | * @param table The non-empty name of the table to use. 90 | * @param key The row key to get in that table. 91 | * @param family The column family. 92 | */ 93 | public GetRequest(final byte[] table, 94 | final byte[] key, 95 | final byte[] family) { 96 | super(table, key); 97 | this.family(family); 98 | } 99 | 100 | /** 101 | * Constructor. 102 | * @param table The non-empty name of the table to use. 103 | * @param key The row key to get in that table. 104 | * @param family The column family. 105 | */ 106 | public GetRequest(final String table, 107 | final String key, 108 | final String family) { 109 | this(table, key); 110 | this.family(family); 111 | } 112 | 113 | /** 114 | * Constructor. 115 | * These byte arrays will NOT be copied. 116 | * @param table The non-empty name of the table to use. 117 | * @param key The row key to get in that table. 118 | * @param family The column family. 119 | * @param qualifier The column qualifier. 120 | */ 121 | public GetRequest(final byte[] table, 122 | final byte[] key, 123 | final byte[] family, 124 | final byte[] qualifier) { 125 | super(table, key); 126 | this.family(family); 127 | this.qualifier(qualifier); 128 | } 129 | 130 | /** 131 | * Constructor. 132 | * @param table The non-empty name of the table to use. 133 | * @param key The row key to get in that table. 134 | * @param family The column family. 135 | * @param qualifier The column qualifier. 136 | */ 137 | public GetRequest(final String table, 138 | final String key, 139 | final String family, 140 | final String qualifier) { 141 | this(table, key); 142 | this.family(family); 143 | this.qualifier(qualifier); 144 | } 145 | 146 | /** 147 | * Private constructor to build an "exists" RPC. 148 | * @param unused Unused, simply used to help the compiler find this ctor. 149 | * @param table The non-empty name of the table to use. 150 | * @param key The row key to get in that table. 151 | */ 152 | private GetRequest(final float unused, 153 | final byte[] table, 154 | final byte[] key) { 155 | super(table, key); 156 | this.versions |= EXIST_FLAG; 157 | } 158 | 159 | /** 160 | * Package-private factory method to build an "exists" RPC. 161 | * @param table The non-empty name of the table to use. 162 | * @param key The row key to get in that table. 163 | * @return An {@link HBaseRpc} that will return a {@link Boolean} 164 | * indicating whether or not the given table / key exists. 165 | */ 166 | static HBaseRpc exists(final byte[] table, final byte[] key) { 167 | return new GetRequest(0F, table, key); 168 | } 169 | 170 | /** 171 | * Package-private factory method to build an "exists" RPC. 172 | * @param table The non-empty name of the table to use. 173 | * @param key The row key to get in that table. 174 | * @param family The column family to get in the table. 175 | * @return An {@link HBaseRpc} that will return a {@link Boolean} 176 | * indicating whether or not the given table / key exists. 177 | */ 178 | static HBaseRpc exists(final byte[] table, 179 | final byte[] key, final byte[] family) { 180 | final GetRequest rpc = new GetRequest(0F, table, key); 181 | rpc.family(family); 182 | return rpc; 183 | } 184 | 185 | /** Returns true if this is actually an "Get" RPC. */ 186 | private boolean isGetRequest() { 187 | return (versions & EXIST_FLAG) == 0; 188 | } 189 | 190 | /** 191 | * Specifies a particular column family to get. 192 | * @param family The column family. 193 | * This byte array will NOT be copied. 194 | * @return {@code this}, always. 195 | */ 196 | public GetRequest family(final byte[] family) { 197 | KeyValue.checkFamily(family); 198 | this.family = family; 199 | return this; 200 | } 201 | 202 | /** Specifies a particular column family to get. */ 203 | public GetRequest family(final String family) { 204 | return family(family.getBytes()); 205 | } 206 | 207 | /** 208 | * Specifies a particular column qualifier to get. 209 | * @param qualifier The column qualifier. 210 | * This byte array will NOT be copied. 211 | * @return {@code this}, always. 212 | */ 213 | public GetRequest qualifier(final byte[] qualifier) { 214 | if (qualifier == null) { 215 | throw new NullPointerException("qualifier"); 216 | } 217 | KeyValue.checkQualifier(qualifier); 218 | this.qualifiers = new byte[][] { qualifier }; 219 | return this; 220 | } 221 | 222 | /** 223 | * Specifies a particular set of column qualifiers to get. 224 | * @param qualifiers The column qualifiers. 225 | * This byte array will NOT be copied. 226 | * @return {@code this}, always. 227 | */ 228 | public GetRequest qualifiers(final byte[][] qualifiers) { 229 | if (qualifiers == null) { 230 | throw new NullPointerException("qualifiers"); 231 | } 232 | for (final byte[] qualifier : qualifiers) { 233 | KeyValue.checkQualifier(qualifier); 234 | } 235 | this.qualifiers = qualifiers; 236 | return this; 237 | } 238 | 239 | /** Specifies a particular column qualifier to get. */ 240 | public GetRequest qualifier(final String qualifier) { 241 | return qualifier(qualifier.getBytes()); 242 | } 243 | 244 | /** Specifies an explicit row lock to use with this request. */ 245 | public GetRequest withRowLock(final RowLock lock) { 246 | throw new UnsupportedOperationException( 247 | "Locking is not supported in the BigTable client"); 248 | } 249 | 250 | /** 251 | * Sets the maximum number of versions to return for each cell read. 252 | *

253 | * By default only the most recent version of each cell is read. 254 | * If you want to get all possible versions available, pass 255 | * {@link Integer#MAX_VALUE} in argument. 256 | * @param versions A strictly positive number of versions to return. 257 | * @return {@code this}, always. 258 | * @throws IllegalArgumentException if {@code versions <= 0} 259 | */ 260 | public GetRequest maxVersions(final int versions) { 261 | if (versions <= 0) { 262 | throw new IllegalArgumentException("Need a strictly positive number: " 263 | + versions); 264 | } 265 | this.versions = (versions << 1) | (this.versions & EXIST_FLAG); 266 | return this; 267 | } 268 | 269 | /** 270 | * Returns the maximum number of versions to return for each cell scanned. 271 | * @return A strictly positive integer. 272 | */ 273 | public int maxVersions() { 274 | return versions >>> 1; 275 | } 276 | 277 | @Override 278 | public byte[] table() { 279 | return table; 280 | } 281 | 282 | @Override 283 | public byte[] key() { 284 | return key; 285 | } 286 | 287 | @Override 288 | public byte[] family() { 289 | return family; 290 | } 291 | 292 | @Override 293 | public byte[][] qualifiers() { 294 | return qualifiers; 295 | } 296 | 297 | public String toString() { 298 | final String klass = isGetRequest() ? "GetRequest" : "Exists"; 299 | return super.toStringWithQualifiers(klass, family, qualifiers); 300 | } 301 | 302 | } 303 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/GetResultOrException.java: -------------------------------------------------------------------------------- 1 | package org.hbase.async; 2 | 3 | import java.util.ArrayList; 4 | 5 | public class GetResultOrException { 6 | final private ArrayList cells; 7 | final private Exception exception; 8 | 9 | public GetResultOrException(final ArrayList cells) { 10 | this.cells = cells; 11 | this.exception = null; 12 | } 13 | 14 | public GetResultOrException(final Exception exp) { 15 | this.exception = exp; 16 | this.cells = null; 17 | } 18 | 19 | public ArrayList getCells() { 20 | return this.cells; 21 | } 22 | 23 | public Exception getException() { 24 | return this.exception; 25 | } 26 | 27 | public String toString() { 28 | StringBuilder sb = new StringBuilder(); 29 | sb.append("{"); 30 | sb.append("cells : ").append(this.cells == null ? "null" : this.cells); 31 | sb.append("; exception: ").append(this.exception == null ? "null" : this.exception); 32 | sb.append("}"); 33 | return sb.toString(); 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/HBaseException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 The Async BigTable Authors. All rights reserved. 3 | * This file is part of Async BigTable. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | /** 30 | * The parent class of all {@link RuntimeException} created by this package. 31 | */ 32 | public abstract class HBaseException extends RuntimeException { 33 | 34 | /** 35 | * Constructor. 36 | * @param msg The message of the exception, potentially including a stack 37 | * trace. 38 | */ 39 | HBaseException(final String msg) { 40 | super(msg); 41 | } 42 | 43 | /** 44 | * Constructor. 45 | * @param msg The message of the exception, potentially including a stack 46 | * trace. 47 | * @param cause The exception that caused this one to be thrown. 48 | */ 49 | HBaseException(final String msg, final Throwable cause) { 50 | super(msg, cause); 51 | } 52 | 53 | private static final long serialVersionUID = 1280638842; 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/HasFailedRpcException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 The Async BigTable Authors. All rights reserved. 3 | * This file is part of Async BigTable. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | /** 30 | * Interface implemented by {@link HBaseException}s that can tell you which 31 | * RPC failed. 32 | */ 33 | public interface HasFailedRpcException { 34 | 35 | /** 36 | * Returns the RPC that caused this exception. 37 | */ 38 | HBaseRpc getFailedRpc(); 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/InvalidResponseException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 The Async BigTable Authors. All rights reserved. 3 | * This file is part of Async BigTable. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | /** 30 | * Exception used when the server sends an invalid response to an RPC. 31 | */ 32 | public final class InvalidResponseException extends NonRecoverableException { 33 | 34 | private final Object response; 35 | 36 | /** 37 | * Constructor. 38 | * @param msg The message of the exception, potentially including a stack 39 | * trace. 40 | * @param response The response that was received from the server. 41 | */ 42 | InvalidResponseException(final String msg, final Object response) { 43 | super(msg); 44 | this.response = response; 45 | } 46 | 47 | /** 48 | * Constructor. 49 | * @param msg The message of the exception. 50 | * @param cause The exception explaining why the response is invalid. 51 | */ 52 | InvalidResponseException(final String msg, final Exception cause) { 53 | super(msg, cause); 54 | this.response = null; 55 | } 56 | 57 | /** 58 | * Constructor for unexpected response types. 59 | * @param expected The type of the response that was expected. 60 | * @param response The response that was received from the server. 61 | */ 62 | InvalidResponseException(final Class expected, final Object response) { 63 | super("Unexpected response type. Expected: " + expected.getName() 64 | + ", got: " + (response == null ? "null" 65 | : response.getClass() + ", value=" + response)); 66 | this.response = response; 67 | } 68 | 69 | /** 70 | * Returns the possibly {@code null} response received from the server. 71 | */ 72 | public Object getResponse() { 73 | return response; 74 | } 75 | 76 | private static final long serialVersionUID = 1280883942; 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/KeyOnlyFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014-2017 The Async HBase Authors. All rights reserved. 3 | * This file is part of Async HBase. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | import org.apache.hadoop.hbase.filter.Filter; 30 | 31 | public class KeyOnlyFilter extends ScanFilter { 32 | 33 | private static final byte[] NAME = 34 | Bytes.UTF8("org.apache.hadoop.hbase.filter.KeyOnlyFilter"); 35 | private final boolean lenAsVal; 36 | 37 | public KeyOnlyFilter() { 38 | this(false); 39 | } 40 | 41 | public KeyOnlyFilter(boolean lenAsVal) { 42 | this.lenAsVal = lenAsVal; 43 | } 44 | 45 | Filter getBigtableFilter() { 46 | return new org.apache.hadoop.hbase.filter.KeyOnlyFilter(lenAsVal); 47 | } 48 | 49 | @Override 50 | byte[] name() { 51 | return NAME; 52 | } 53 | 54 | @Override 55 | public String toString() { 56 | return this.getClass().getSimpleName() + " " 57 | + "lenAsVal: " + (lenAsVal ? "true" : "false"); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/KeyRegexpFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015-2017 The Async BigTable Authors. All rights reserved. 3 | * This file is part of Async BigTable. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | import org.apache.hadoop.hbase.filter.ByteArrayComparable; 30 | import org.apache.hadoop.hbase.filter.CompareFilter; 31 | import org.apache.hadoop.hbase.filter.Filter; 32 | import org.apache.hadoop.hbase.filter.RegexStringComparator; 33 | import org.apache.hadoop.hbase.filter.RowFilter; 34 | import org.apache.hbase.thirdparty.io.netty.util.CharsetUtil; 35 | 36 | import java.lang.reflect.Field; 37 | import java.nio.charset.Charset; 38 | import java.util.Arrays; 39 | 40 | /** 41 | * Filters rows based on an expression applied to the row key. 42 | *

43 | * The regular expression will be applied on the server-side, on the row 44 | * key. Rows for which the key doesn't match will not be returned to the 45 | * scanner, which can be useful to carefully select which rows are matched 46 | * when you can't just do a prefix match, and cut down the amount of data 47 | * transfered on the network. 48 | *

49 | * Don't use an expensive regular expression, because Java's implementation 50 | * uses backtracking and matching will happen on the server side, potentially 51 | * on many many row keys. 52 | * See Regular Expression 53 | * Matching Can Be Simple And Fast for more details on regular expression 54 | * performance (or lack thereof) and what "backtracking" means. 55 | *

56 | * This means you need to be careful about using regular 57 | * expressions supplied by users as that would allow them to easily DDoS 58 | * HBase by sending prohibitively expensive regexps that would consume all 59 | * CPU cycles and cause the entire HBase node to time out. 60 | * @since 1.5 61 | */ 62 | public final class KeyRegexpFilter extends ScanFilter { 63 | 64 | private static final byte[] ROWFILTER = Bytes.ISO88591("org.apache.hadoop" 65 | + ".hbase.filter.RowFilter"); 66 | private static final byte[] REGEXSTRINGCOMPARATOR = Bytes.ISO88591("org.apache.hadoop" 67 | + ".hbase.filter.RegexStringComparator"); 68 | private static final byte[] EQUAL = new byte[] { 'E', 'Q', 'U', 'A', 'L' }; 69 | 70 | private final byte[] regexp; 71 | private final byte[] charset; 72 | private final String regexp_string; 73 | private final Charset charset_object; 74 | 75 | /** 76 | * Sets a regular expression to filter results based on the row key. 77 | *

78 | * This is equivalent to calling {@link #KeyRegexpFilter(String, Charset)} 79 | * with the ISO-8859-1 charset in argument. 80 | * @param regexp The regular expression with which to filter the row keys. 81 | */ 82 | public KeyRegexpFilter(final String regexp) { 83 | this(regexp, CharsetUtil.ISO_8859_1); 84 | } 85 | 86 | /** 87 | * Sets a regular expression to filter results based on the row key. 88 | * @param regexp The regular expression with which to filter the row keys. 89 | * @param charset The charset used to decode the bytes of the row key into a 90 | * string. The RegionServer must support this charset, otherwise it will 91 | * unexpectedly close the connection the first time you attempt to use this 92 | * scanner. 93 | * @see #KeyRegexpFilter(byte[], Charset) 94 | */ 95 | public KeyRegexpFilter(final String regexp, final Charset charset) { 96 | this(regexp.getBytes(charset), charset); 97 | } 98 | 99 | /** 100 | * Sets a regular expression to filter results based on the row key. 101 | *

102 | * This is equivalent to calling {@link #KeyRegexpFilter(byte[], Charset)} 103 | * with the ISO-8859-1 charset in argument. 104 | * @param regexp The binary regular expression with which to filter 105 | * the row keys. 106 | */ 107 | public KeyRegexpFilter(final byte[] regexp) { 108 | this(regexp, CharsetUtil.ISO_8859_1); 109 | } 110 | 111 | /** 112 | * Sets a regular expression to filter results based on the row key. 113 | * @param regexp The regular expression with which to filter the row keys. 114 | * @param charset The charset used to decode the bytes of the row key into a 115 | * string. The RegionServer must support this charset, otherwise it will 116 | * unexpectedly close the connection the first time you attempt to use this 117 | * scanner. 118 | */ 119 | public KeyRegexpFilter(final byte[] regexp, final Charset charset) { 120 | this.regexp = regexp; 121 | this.charset = Bytes.UTF8(charset.name()); 122 | regexp_string = new String(regexp, charset); 123 | charset_object = charset; 124 | } 125 | 126 | @Override 127 | byte[] name() { 128 | return ROWFILTER; 129 | } 130 | 131 | public String toString() { 132 | return "KeyRegexpFilter(\"" + new String(regexp, CharsetUtil.UTF_8) 133 | + "\", " + new String(charset, CharsetUtil.UTF_8) + ')'; 134 | } 135 | 136 | /** @return the regular expression, a copy of the byte array 137 | * @since 1.8 */ 138 | public byte[] getRegexp() { 139 | return Arrays.copyOf(regexp, regexp.length); 140 | } 141 | 142 | /** @return the character set for this regular expression 143 | * @since 1.8 */ 144 | public Charset getCharset() { 145 | return Charset.forName(new String(charset)); 146 | } 147 | 148 | @Override 149 | Filter getBigtableFilter() { 150 | RegexStringComparator comparator = new RegexStringComparator(regexp_string); 151 | comparator.setCharset(charset_object); 152 | try { 153 | // WARNING: This is some ugly ass code. It WILL break at some point. 154 | // Bigtable uses RE2 and runs in raw byte mode. TSDB writes regex with 155 | // byte values but when passing it through the HTable APIs it's converted 156 | // to UTF and serializes differently than the old AsyncHBase client. The 157 | // native BigTable client will pass the regex along properly BUT we need 158 | // to bypass the RegexStringComparator methods and inject our ASCII regex 159 | // directly into the underlying comparator object. Hopefully this is 160 | // temporary (famous last words) until we get to a native Bigtable wrapper. 161 | final Field field = ByteArrayComparable.class.getDeclaredField("value"); 162 | field.setAccessible(true); 163 | field.set(comparator, regexp_string.getBytes(HBaseClient.ASCII)); 164 | field.setAccessible(false); 165 | return new RowFilter(CompareFilter.CompareOp.EQUAL, comparator); 166 | } catch (NoSuchFieldException e) { 167 | throw new RuntimeException("ByteArrayComparator must have changed, " 168 | + "can't find the field", e); 169 | } catch (IllegalAccessException e) { 170 | throw new RuntimeException("Access denied when hacking the " 171 | + "regex comparator field", e); 172 | } 173 | } 174 | 175 | } 176 | 177 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/KeyValue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 The Async BigTable Authors. All rights reserved. 3 | * This file is part of Async BigTable. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | import java.util.Arrays; 30 | 31 | /** 32 | * A "cell" in an HBase table. 33 | *

34 | * This represents one unit of HBase data, one "record". 35 | * 36 | *

A note {@code byte} arrays

37 | * This class will never copy any {@code byte[]} that's given to it, neither 38 | * will it create a copy before returning one to you. 39 | * Changing a byte array get from or pass to this class will have 40 | * unpredictable consequences. In particular, multiple 41 | * {@link KeyValue} instances may share the same byte arrays, so changing 42 | * one instance may also unexpectedly affect others. 43 | */ 44 | public final class KeyValue implements Comparable { 45 | 46 | /** 47 | * Timestamp value to let the server set the timestamp at processing time. 48 | * When this value is used as a timestamp on a {@code KeyValue}, the server 49 | * will substitute a real timestamp at the time it processes it. HBase uses 50 | * current UNIX time in milliseconds. 51 | */ 52 | public static final long TIMESTAMP_NOW = Long.MAX_VALUE; 53 | 54 | //private static final Logger LOG = LoggerFactory.getLogger(KeyValue.class); 55 | 56 | private final byte[] key; // Max length: Short.MAX_VALUE = 32768 57 | private final byte[] family; // Max length: Byte.MAX_VALUE = 128 58 | private final byte[] qualifier; 59 | private final byte[] value; 60 | private final long timestamp; 61 | 62 | /** 63 | * Constructor. 64 | * @param key The row key. Length must fit in 16 bits. 65 | * @param family The column family. Length must fit in 8 bits. 66 | * @param qualifier The column qualifier. 67 | * @param timestamp Timestamp on the value. This timestamp can be set to 68 | * guarantee ordering of values or operations. It is strongly advised to 69 | * use a UNIX timestamp in milliseconds, e.g. from a source such as 70 | * {@link System#currentTimeMillis}. This value must be strictly positive. 71 | * @param value The value, the contents of the cell. 72 | * @throws IllegalArgumentException if any argument is invalid (e.g. array 73 | * size is too long) or if the timestamp is negative. 74 | */ 75 | public KeyValue(final byte[] key, 76 | final byte[] family, final byte[] qualifier, 77 | final long timestamp, 78 | //final byte type, 79 | final byte[] value) { 80 | checkKey(key); 81 | checkFamily(family); 82 | checkQualifier(qualifier); 83 | checkTimestamp(timestamp); 84 | checkValue(value); 85 | this.key = key; 86 | this.family = family; 87 | this.qualifier = qualifier; 88 | this.value = value; 89 | this.timestamp = timestamp; 90 | //this.type = type; 91 | } 92 | 93 | /** 94 | * Constructor. 95 | *

96 | * This {@code KeyValue} will be timestamped by the server at the time 97 | * the server processes it. 98 | * @param key The row key. Length must fit in 16 bits. 99 | * @param family The column family. Length must fit in 8 bits. 100 | * @param qualifier The column qualifier. 101 | * @param value The value, the contents of the cell. 102 | * @throws IllegalArgumentException if any argument is invalid (e.g. array 103 | * size is too long). 104 | * @see #TIMESTAMP_NOW 105 | */ 106 | public KeyValue(final byte[] key, 107 | final byte[] family, final byte[] qualifier, 108 | final byte[] value) { 109 | this(key, family, qualifier, TIMESTAMP_NOW, value); 110 | } 111 | 112 | /** Returns the row key. */ 113 | public byte[] key() { 114 | return key; 115 | } 116 | 117 | /** Returns the column family. */ 118 | public byte[] family() { 119 | return family; 120 | } 121 | 122 | /** Returns the column qualifier. */ 123 | public byte[] qualifier() { 124 | return qualifier; 125 | } 126 | 127 | /** 128 | * Returns the timestamp stored in this {@code KeyValue}. 129 | * @see #TIMESTAMP_NOW 130 | */ 131 | public long timestamp() { 132 | return timestamp; 133 | } 134 | 135 | /** Returns the value, the contents of the cell. */ 136 | public byte[] value() { 137 | return value; 138 | } 139 | 140 | @Override 141 | public int compareTo(final KeyValue other) { 142 | int d; 143 | if ((d = Bytes.memcmp(key, other.key)) != 0) { 144 | return d; 145 | } else if ((d = Bytes.memcmp(family, other.family)) != 0) { 146 | return d; 147 | } else if ((d = Bytes.memcmp(qualifier, other.qualifier)) != 0) { 148 | return d; 149 | //} else if ((d = Bytes.memcmp(value, other.value)) != 0) { 150 | // return d; 151 | } else if ((d = Long.signum(timestamp - other.timestamp)) != 0) { 152 | return d; 153 | } else { 154 | // d = type - other.type; 155 | d = Bytes.memcmp(value, other.value); 156 | } 157 | return d; 158 | } 159 | 160 | public boolean equals(final Object other) { 161 | if (other == null || !(other instanceof KeyValue)) { 162 | return false; 163 | } 164 | return compareTo((KeyValue) other) == 0; 165 | } 166 | 167 | public int hashCode() { 168 | return Arrays.hashCode(key) 169 | ^ Arrays.hashCode(family) 170 | ^ Arrays.hashCode(qualifier) 171 | ^ Arrays.hashCode(value) 172 | ^ (int) (timestamp ^ (timestamp >>> 32)) 173 | //^ type 174 | ; 175 | } 176 | 177 | public String toString() { 178 | final StringBuilder buf = new StringBuilder(84 // Boilerplate + timestamp 179 | // the row key is likely to contain non-ascii characters, so 180 | // let's multiply its length by 2 to avoid re-allocations. 181 | + key.length * 2 + family.length + qualifier.length + value.length); 182 | buf.append("KeyValue(key="); 183 | Bytes.pretty(buf, key); 184 | buf.append(", family="); 185 | Bytes.pretty(buf, family); 186 | buf.append(", qualifier="); 187 | Bytes.pretty(buf, qualifier); 188 | buf.append(", value="); 189 | Bytes.pretty(buf, value); 190 | buf.append(", timestamp=").append(timestamp); 191 | // .append(", type=").append(type); 192 | buf.append(')'); 193 | return buf.toString(); 194 | } 195 | 196 | // OK this isn't technically part of a KeyValue but since all the similar 197 | // functions are here, let's keep things together in one place. 198 | /** 199 | * Validates a table name. 200 | * @throws IllegalArgumentException if the table name is too big or 201 | * malformed. 202 | * @throws NullPointerException if the table name is {@code null}. 203 | */ 204 | static void checkTable(final byte[] table) { 205 | if (table.length > Byte.MAX_VALUE) { 206 | throw new IllegalArgumentException("Table name too long: " 207 | + table.length + " bytes long " + Bytes.pretty(table)); 208 | } else if (table.length == 0) { 209 | throw new IllegalArgumentException("empty table name"); 210 | } 211 | } 212 | 213 | /** 214 | * Validates a row key. 215 | * @throws IllegalArgumentException if the key is too big. 216 | * @throws NullPointerException if the key is {@code null}. 217 | */ 218 | static void checkKey(final byte[] key) { 219 | if (key.length > Short.MAX_VALUE) { 220 | throw new IllegalArgumentException("row key too long: " 221 | + key.length + " bytes long " + Bytes.pretty(key)); 222 | } 223 | } 224 | 225 | /** 226 | * Validates a column family. 227 | * @throws IllegalArgumentException if the family name is too big. 228 | * @throws NullPointerException if the family is {@code null}. 229 | */ 230 | static void checkFamily(final byte[] family) { 231 | if (family.length > Byte.MAX_VALUE) { 232 | throw new IllegalArgumentException("column family too long: " 233 | + family.length + " bytes long " + Bytes.pretty(family)); 234 | } 235 | } 236 | 237 | /** 238 | * Validates a column qualifier. 239 | * @throws IllegalArgumentException if the qualifier name is too big. 240 | * @throws NullPointerException if the qualifier is {@code null}. 241 | */ 242 | static void checkQualifier(final byte[] qualifier) { 243 | HBaseRpc.checkArrayLength(qualifier); 244 | } 245 | 246 | /** 247 | * Validates a timestamp. 248 | * @throws IllegalArgumentException if the timestamp is zero or negative. 249 | */ 250 | static void checkTimestamp(final long timestamp) { 251 | if (timestamp < 0) { 252 | throw new IllegalArgumentException("Negative timestamp: " + timestamp); 253 | } 254 | } 255 | 256 | /** 257 | * Validates a value (the contents of an HBase cell). 258 | * @throws IllegalArgumentException if the value is too big. 259 | * @throws NullPointerException if the value is {@code null}. 260 | */ 261 | static void checkValue(final byte[] value) { 262 | HBaseRpc.checkArrayLength(value); 263 | } 264 | 265 | } 266 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/NoSuchColumnFamilyException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 The Async BigTable Authors. All rights reserved. 3 | * This file is part of Async BigTable. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | /** 30 | * Exception thrown when attempting to use a nonexistent column family. 31 | */ 32 | public final class NoSuchColumnFamilyException extends NonRecoverableException 33 | { 34 | 35 | static final String REMOTE_CLASS = 36 | "org.apache.hadoop.hbase.regionserver.NoSuchColumnFamilyException"; 37 | 38 | final HBaseRpc failed_rpc; 39 | 40 | /** 41 | * Constructor. 42 | * @param msg The message of the exception, potentially with a stack trace. 43 | * @param failed_rpc The RPC that caused this exception, if known, or null. 44 | */ 45 | NoSuchColumnFamilyException(final String msg, final HBaseRpc failed_rpc) { 46 | super(msg + "\nCaused by RPC: " + failed_rpc); 47 | this.failed_rpc = failed_rpc; 48 | } 49 | 50 | 51 | 52 | private static final long serialVersionUID = 1280993542; 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/NonRecoverableException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 The Async BigTable Authors. All rights reserved. 3 | * This file is part of Async BigTable. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | /** 30 | * An exception for which it's typically pointless to retry 31 | * (such as {@link TableNotFoundException}). 32 | */ 33 | public class NonRecoverableException extends HBaseException { 34 | 35 | /** 36 | * Constructor. 37 | * @param msg The message of the exception, potentially including a stack 38 | * trace. 39 | */ 40 | NonRecoverableException(final String msg) { 41 | super(msg); 42 | } 43 | 44 | /** 45 | * Constructor. 46 | * @param msg The message of the exception, potentially including a stack 47 | * trace. 48 | * @param cause The exception that caused this one to be thrown. 49 | */ 50 | NonRecoverableException(final String msg, final Throwable cause) { 51 | super(msg, cause); 52 | } 53 | 54 | private static final long serialVersionUID = 1280638547; 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/PleaseThrottleException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 The Async BigTable Authors. All rights reserved. 3 | * This file is part of Async BigTable. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | import com.stumbleupon.async.Deferred; 30 | 31 | /** 32 | * This exception notifies the application to throttle its use of HBase. 33 | *

34 | * Since all APIs of {@link HBaseClient} are asynchronous and non-blocking, 35 | * it's possible that the application would produce RPCs at a rate higher 36 | * than HBase is able to handle. When this happens, {@link HBaseClient} 37 | * will typically do some buffering up to a certain point beyond which RPCs 38 | * will fail-fast with this exception, to prevent the application from 39 | * running itself out of memory. 40 | *

41 | * This exception is expected to be handled by having the application 42 | * throttle or pause itself for a short period of time before retrying the 43 | * RPC that failed with this exception as well as before sending other RPCs. 44 | * The reason this exception inherits from {@link NonRecoverableException} 45 | * instead of {@link RecoverableException} is that the usual course of action 46 | * when handling a {@link RecoverableException} is to retry right away, which 47 | * would defeat the whole purpose of this exception. Here, we want the 48 | * application to retry after a reasonable delay as well as throttle 49 | * the pace of creation of new RPCs. What constitutes a "reasonable 50 | * delay" depends on the nature of RPCs and rate at which they're produced. 51 | * For a write-heavy high-throughput application, this exception will 52 | * typically be used when HBase is in the process of splitting a region or 53 | * migrating a region to another server, in which case the application should 54 | * stop producing new writes for typically at least 1 second (or significantly 55 | * slow down its pace, to let {@link HBaseClient} buffer the writes). 56 | *

57 | * When {@link HBaseClient} buffers RPCs, it typically uses this exception 58 | * with a low watermark and a high watermark. When the buffer hits the low 59 | * watermark, the next (unlucky) RPC that wants to be buffered will be failed 60 | * with a {@code PleaseThrottleException}, to send an "advisory warning" to 61 | * the application that it needs to throttle itself. All subsequent RPCs 62 | * that need to be buffered will be buffered until the buffer hits the high 63 | * watermark. Once the high watermark has been hit, all subsequent RPCs that 64 | * need to be buffered will fail-fast with a {@code PleaseThrottleException}. 65 | *

66 | * One effective strategy to handle this exception is to set a flag to true 67 | * when this exception is first emitted that causes the application to pause 68 | * or throttle its use of HBase. Then you can retry the RPC that failed 69 | * (which is accessible through {@link #getFailedRpc}) and add a callback to 70 | * it in order to unset the flag once the RPC completes successfully. 71 | * Note that low-throughput applications will typically rarely (if ever) 72 | * hit the low watermark and should never hit the high watermark, so they 73 | * don't need complex throttling logic. 74 | */ 75 | public final class PleaseThrottleException extends NonRecoverableException 76 | implements HasFailedRpcException { 77 | 78 | /** The RPC that was failed with this exception. */ 79 | private final HBaseRpc rpc; 80 | 81 | /** A deferred one can wait on before retrying the failed RPC. */ 82 | private final Deferred deferred; 83 | 84 | /** 85 | * Constructor. 86 | * @param msg A message explaining why the application has to throttle. 87 | * @param cause The exception that requires the application to throttle 88 | * itself (can be {@code null}). 89 | * @param rpc The RPC that was made to fail with this exception. 90 | * @param deferred A deferred one can wait on before retrying the failed RPC. 91 | */ 92 | PleaseThrottleException(final String msg, 93 | final HBaseException cause, 94 | final HBaseRpc rpc, 95 | final Deferred deferred) { 96 | super(msg, cause); 97 | this.rpc = rpc; 98 | this.deferred = deferred; 99 | } 100 | 101 | /** 102 | * The RPC that was made to fail with this exception. 103 | */ 104 | public HBaseRpc getFailedRpc() { 105 | return rpc; 106 | } 107 | 108 | /** 109 | * Returns a deferred one can wait on before retrying the failed RPC. 110 | * @since 1.3 111 | */ 112 | public Deferred getDeferred() { 113 | return deferred; 114 | } 115 | 116 | PleaseThrottleException make(final Object msg, final HBaseRpc rpc) { 117 | // This is only called from HBaseClient.sendRpcToRegion(), more precisely 118 | // from RetryRpc.call(), where we need to report the correct RPC that has 119 | // failed when it's a META or ROOT lookup that failed. 120 | if (msg instanceof PleaseThrottleException) { 121 | final PleaseThrottleException e = (PleaseThrottleException) msg; 122 | return new PleaseThrottleException(e.getMessage(), e, rpc, 123 | e.getDeferred()); 124 | } 125 | // Thus we never expect to be here since the only call site is passing us 126 | // a PleaseThrottleException in argument. Not very clean, I agree. 127 | throw new AssertionError("Should never be here!"); 128 | } 129 | 130 | private static final long serialVersionUID = 1286782542; 131 | 132 | } 133 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/QualifierFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014-2017 The Async HBase Authors. All rights reserved. 3 | * This file is part of Async HBase. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | import org.apache.hadoop.hbase.filter.Filter; 30 | 31 | /** 32 | * Filter columns based on the qualifier. Takes an operator (equal, greater, 33 | * not equal, etc). and a filter comparator. 34 | * @since 1.6 35 | */ 36 | public final class QualifierFilter extends CompareFilter { 37 | 38 | private static final byte[] NAME = 39 | Bytes.UTF8("org.apache.hadoop.hbase.filter.QualifierFilter"); 40 | 41 | public QualifierFilter(final CompareOp op, 42 | final FilterComparator qualifierComparator) { 43 | super(op, qualifierComparator); 44 | } 45 | 46 | @Override 47 | byte[] name() { 48 | return NAME; 49 | } 50 | 51 | Filter getBigtableFilter() { 52 | return new org.apache.hadoop.hbase.filter.QualifierFilter( 53 | CompareOp.convert(compare_op), comparator.getBigtableFilter()); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/RecoverableException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 The Async BigTable Authors. All rights reserved. 3 | * This file is part of Async BigTable. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | /** 30 | * An exception for which it's typically useful to retry 31 | *

32 | * The retry strategy is up to you, but it's typically recommended to put an 33 | * upper bound on the number of retries and to use some kind of an exponential 34 | * backoff. 35 | */ 36 | public abstract class RecoverableException extends HBaseException { 37 | 38 | /** 39 | * Constructor. 40 | * @param msg The message of the exception, potentially including a stack 41 | * trace. 42 | */ 43 | RecoverableException(final String msg) { 44 | super(msg); 45 | } 46 | 47 | /** 48 | * Constructor. 49 | * @param msg The message of the exception, potentially including a stack 50 | * trace. 51 | * @param cause The exception that caused this one to be thrown. 52 | */ 53 | RecoverableException(final String msg, final Exception cause) { 54 | super(msg, cause); 55 | } 56 | 57 | private static final long serialVersionUID = 1280641142; 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/RegexStringComparator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014-2017 The Async HBase Authors. All rights reserved. 3 | * This file is part of Async HBase. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | import java.nio.charset.Charset; 30 | 31 | import org.apache.hadoop.hbase.filter.ByteArrayComparable; 32 | 33 | import com.google.common.base.Charsets; 34 | 35 | /** 36 | * A regular expression comparator used in comparison filters such as RowFilter, 37 | * QualifierFilter, and ValueFilter. 38 | *

39 | * Don't use an expensive regular expression, because Java's implementation 40 | * uses backtracking and matching will happen on the server side, potentially 41 | * on many many row keys, columns, or values. 42 | * See Regular Expression 43 | * Matching Can Be Simple And Fast for more details on regular expression 44 | * performance (or lack thereof) and what "backtracking" means. 45 | *

46 | * This means you need to be careful about using regular 47 | * expressions supplied by users as that would allow them to easily DDoS 48 | * HBase by sending prohibitively expensive regexps that would consume all 49 | * CPU cycles and cause the entire HBase node to time out. 50 | *

51 | * Only EQUAL and NOT_EQUAL comparisons are valid with this comparator. 52 | * @since 1.6 53 | */ 54 | public final class RegexStringComparator extends FilterComparator { 55 | 56 | private static final byte[] NAME = 57 | Bytes.UTF8("org.apache.hadoop.hbase.filter.RegexStringComparator"); 58 | 59 | private final String expr; 60 | private final Charset charset; 61 | 62 | /** 63 | * Create a regular expression filter with the specified regular expression. 64 | *

65 | * This is equivalent to calling {@link #RegexStringComparator(String, Charset)} 66 | * with the UTF-8 charset in argument. 67 | * 68 | * @param expr The regular expression with which to filter. 69 | */ 70 | public RegexStringComparator(String expr) { 71 | this(expr, Charsets.UTF_8); 72 | } 73 | 74 | /** 75 | * Create a regular expression filter with the specified regular expression 76 | * and charset. 77 | * 78 | * @param expr The regular expression with which to filter. 79 | * @param charset The character set. 80 | */ 81 | public RegexStringComparator(final String expr, final Charset charset) { 82 | this.expr = expr; 83 | this.charset = charset; 84 | } 85 | 86 | public String expression() { 87 | return expr; 88 | } 89 | 90 | public Charset charset() { 91 | return charset; 92 | } 93 | 94 | @Override 95 | byte[] name() { 96 | return NAME; 97 | } 98 | 99 | @Override 100 | public String toString() { 101 | return String.format("%s(%s, %s)", 102 | getClass().getSimpleName(), 103 | Bytes.pretty(expr.getBytes(charset)), 104 | charset.name()); 105 | } 106 | 107 | @Override 108 | ByteArrayComparable getBigtableFilter() { 109 | return new org.apache.hadoop.hbase.filter.RegexStringComparator(expr); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/RegionClientStats.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 The Async HBase Authors. All rights reserved. 3 | * This file is part of Async HBase. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | /** 30 | * NOT APPLICABLE TO CLOUD BIGTABLE 31 | *

32 | * This is an immutable snapshot of usage statistics of the region client. 33 | * Please note that not all the numbers in the snapshot are collected 34 | * atomically, so although each individual number is up-to-date as of 35 | * the time this object is created, small inconsistencies between numbers 36 | * can arise. 37 | */ 38 | public final class RegionClientStats { 39 | 40 | private final long rpcs_sent; 41 | private final int inflight_rpcs; 42 | private final int pending_rpcs; 43 | private final long rpcid; 44 | private final boolean dead; 45 | private final String remote_endpoint; 46 | private final int pending_batched_rpcs; 47 | private final long rpcs_timedout; 48 | private final long writes_blocked; 49 | private final long rpc_response_timedout; 50 | private final long rpc_response_unknown; 51 | private final long inflight_breached; 52 | private final long pending_breached; 53 | 54 | /** Package-private constructor. */ 55 | RegionClientStats( 56 | final long rpcs_sent, 57 | final int rpcs_inflight, 58 | final int pending_rpcs, 59 | final long rpcid, 60 | final boolean dead, 61 | final String remote_endpoint, 62 | final int pending_batched_rpcs, 63 | final long rpcs_timedout, 64 | final long writes_blocked, 65 | final long rpc_response_timedout, 66 | final long rpc_response_unknown, 67 | final long inflight_breached, 68 | final long pending_breached 69 | ) { 70 | this.rpcs_sent = rpcs_sent; 71 | this.inflight_rpcs = rpcs_inflight; 72 | this.pending_rpcs = pending_rpcs; 73 | this.rpcid = rpcid; 74 | this.dead = dead; 75 | this.remote_endpoint = remote_endpoint; 76 | this.pending_batched_rpcs = pending_batched_rpcs; 77 | this.writes_blocked = writes_blocked; 78 | this.rpcs_timedout = rpcs_timedout; 79 | this.rpc_response_timedout = rpc_response_timedout; 80 | this.rpc_response_unknown = rpc_response_unknown; 81 | this.inflight_breached = inflight_breached; 82 | this.pending_breached = pending_breached; 83 | } 84 | 85 | /** 86 | * Represents the total number of RPCs sent from this client to the server, 87 | * whether they were successful or not. 88 | * @return The number of RPCs sent over TCP to the server 89 | */ 90 | public long rpcsSent() { 91 | return rpcs_sent; 92 | } 93 | 94 | /** 95 | * Represents the number of RPCs that have been sent to the region client 96 | * and are currently waiting for a response. If this value increases then the 97 | * region server is likely overloaded. 98 | * @return the number of RPCs sent to region client waiting for response. 99 | */ 100 | public int inflightRPCs() { 101 | return inflight_rpcs; 102 | } 103 | 104 | /** 105 | * The number of RPCs that are queued up and ready to be sent to the region 106 | * server. When an RPC is sent, this number should be decremented and 107 | * {@code rpcsInFlight} incremented. 108 | * @return the number of RPCs queued and ready to be sent to region server. 109 | */ 110 | public int pendingRPCs() { 111 | return pending_rpcs; 112 | } 113 | 114 | /** 115 | * The current RPC ID. This can be used to track the number of RPC requests 116 | * sent from this region client. Note that the counter is initialized at -1 117 | * when a new client has been instantiated but no RPCs sent. It increments 118 | * from there and may rollover quickly, returning negative values. This is 119 | * acceptable as HBase doesn't care about the RPC ID as long as it's unique. 120 | * @return the current RPC ID. 121 | */ 122 | public long rpcID() { 123 | return rpcid; 124 | } 125 | 126 | /** 127 | * Whether or not this region client has been marked as dead and should not 128 | * be used for requests. This likely means the host or server has failed or 129 | * we simply can't connect any more. 130 | * @return whether this region client has been marked as dead and should not 131 | * be used for requests. 132 | */ 133 | public boolean isDead() { 134 | return dead; 135 | } 136 | 137 | /** 138 | * The remote endpoint of the region server this client is connecting to. 139 | * @return the host name (or IP address) of the region server this client is 140 | * connecting to. 141 | */ 142 | public String remoteEndpoint() { 143 | return remote_endpoint; 144 | } 145 | 146 | /** 147 | * The number of batched RPCs waiting to be sent to the server. 148 | * @return the number of batched RPCs waiting to be sent to the server. 149 | */ 150 | public int pendingBatchedRPCs() { 151 | return pending_batched_rpcs; 152 | } 153 | 154 | /** 155 | * The number of RPCs that timed out due to not receiving a response from 156 | * HBase in a configurable amount of time. 157 | * @return The number of RPCs timedout 158 | */ 159 | public long rpcsTimedout() { 160 | return rpcs_timedout; 161 | } 162 | 163 | /** 164 | * The number of times sending an RPC was blocked due to the socket send 165 | * buffer being full. This means HBase was not consuming RPCs fast enough. 166 | * @return The number of writes blocked due to a full buffer. 167 | */ 168 | public long writesBlocked() { 169 | return writes_blocked; 170 | } 171 | 172 | /** 173 | * Represents the number of responses that were received from HBase for RPCs 174 | * that were already timed out by the client. A fairly high number means 175 | * HBase is busy but recovered. 176 | * @return The number of late responses received from HBase 177 | */ 178 | public long rpcResponsesTimedout() { 179 | return rpc_response_timedout; 180 | } 181 | 182 | /** 183 | * Represents the number of responses that were received from HBase that 184 | * were for RPCs the region client supposedly did not send. This means 185 | * something really strange happened, i.e. we had a corrupt packet or 186 | * HBase is sending responses for another connection. 187 | * @return The number of unknown responses from HBase 188 | */ 189 | public long rpcResponsesUnknown() { 190 | return rpc_response_unknown; 191 | } 192 | 193 | /** 194 | * The number of times RPCs were rejected due to there being too many RPCs 195 | * in flight and waiting for responses from the HBase server. Failed RPCs 196 | * throw a {@link PleaseThrottleException} 197 | * @return The number of times we rejected RPCs due to a full inflight queue. 198 | */ 199 | public long inflightBreached() { 200 | return inflight_breached; 201 | } 202 | 203 | /** 204 | * The number of times RPCs were rejected due to there being too many RPCs 205 | * in the pending queue, i.e. while we were waiting for HBase to respond to 206 | * the connection request. Failed RPCs throw a 207 | * {@link PleaseThrottleException} 208 | * @return The number of times we rejected RPCs due to a full pending queue. 209 | */ 210 | public long pendingBreached() { 211 | return pending_breached; 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/RegionLocation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 The Async Bigtable Authors. All rights reserved. 3 | * This file is part of Async BigTable. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | /** 30 | * Used here only for backwards API compatibility with AsyncHBase. 31 | * @deprecated 32 | */ 33 | public final class RegionLocation { 34 | 35 | /** 36 | * Used here only for backwards API compatibility with AsyncHBase. 37 | * @deprecated 38 | * @return an empty array 39 | */ 40 | public byte[] startKey() { 41 | return HBaseClient.EMPTY_ARRAY; 42 | } 43 | 44 | /** 45 | * Used here only for backwards API compatibility with AsyncHBase. 46 | * @deprecated 47 | * @return an empty array 48 | */ 49 | public byte[] stopKey() { 50 | return HBaseClient.EMPTY_ARRAY; 51 | } 52 | 53 | /** 54 | * Used here only for backwards API compatibility with AsyncHBase. 55 | * @deprecated 56 | * @return an empty string 57 | */ 58 | public String getHostname() { 59 | return ""; 60 | } 61 | 62 | /** 63 | * Used here only for backwards API compatibility with AsyncHBase. 64 | * @deprecated 65 | * @return zero 66 | */ 67 | public int getPort() { 68 | return 0; 69 | } 70 | 71 | /** 72 | * Used here only for backwards API compatibility with AsyncHBase. 73 | * @deprecated 74 | * @return an empty array 75 | */ 76 | public byte[] getTable() { 77 | return HBaseClient.EMPTY_ARRAY; 78 | } 79 | 80 | /** 81 | * Used here only for backwards API compatibility with AsyncHBase. 82 | * @deprecated 83 | * @return an empty array 84 | */ 85 | public byte[] getRegionName() { 86 | return HBaseClient.EMPTY_ARRAY; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/RowLock.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 The Async BigTable Authors. All rights reserved. 3 | * This file is part of Async BigTable. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | 30 | /** 31 | * A leftover from early AsyncHBase days. This class should not be used and all 32 | * methods throw unsupported operation exceptions. 33 | * @deprecated 34 | */ 35 | public final class RowLock { 36 | 37 | /** Lock ID used to indicate that there's no explicit row lock. */ 38 | static final long NO_LOCK = -1L; 39 | 40 | /** 41 | * CTor that always throws an UnsupportedOperationException as locking is 42 | * no longer supported 43 | * @param region_name unused 44 | * @param lockid unused 45 | * @throws UnsupportedOperationException 46 | */ 47 | RowLock(final byte[] region_name, final long lockid) { 48 | throw new UnsupportedOperationException( 49 | "Locking is not supported in Big Table"); 50 | } 51 | 52 | /** 53 | * @return UnsupportedOperationException as locking is no longer used 54 | * @throws UnsupportedOperationException 55 | */ 56 | public long holdNanoTime() { 57 | throw new UnsupportedOperationException( 58 | "Locking is not supported in Big Table"); 59 | } 60 | 61 | public String toString() { 62 | return "UnsupportedLockObject"; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/RowLockRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 The Async BigTable Authors. All rights reserved. 3 | * This file is part of Async BigTable. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | /** 30 | * A leftover from early AsyncHBase days. This class should not be used and all 31 | * methods throw unsupported operation exceptions. 32 | * @deprecated 33 | */ 34 | public final class RowLockRequest extends HBaseRpc 35 | implements HBaseRpc.HasTable, HBaseRpc.HasKey { 36 | 37 | /** 38 | * CTor that always throws an UnsupportedOperationException as locking is 39 | * no longer supported 40 | * @param table Unused 41 | * @param key Unused 42 | * @throws UnsupportedOperationException all the time 43 | */ 44 | public RowLockRequest(final byte[] table, final byte[] key) { 45 | throw new UnsupportedOperationException("Locking is not supported in BigTable"); 46 | } 47 | 48 | /** 49 | * CTor that always throws an UnsupportedOperationException as locking is 50 | * no longer supported 51 | * @param table Unused 52 | * @param key Unused 53 | * @throws UnsupportedOperationException all the time 54 | */ 55 | public RowLockRequest(final String table, final String key) { 56 | this(table.getBytes(), key.getBytes()); 57 | } 58 | 59 | @Override 60 | public byte[] table() { 61 | return table; 62 | } 63 | 64 | @Override 65 | public byte[] key() { 66 | return key; 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/RpcTimedOutException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 The Async HBase Authors. All rights reserved. 3 | * This file is part of Async HBase. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | /** 30 | * An exception where we haven't received a response for an in-flight RPC 31 | * @since 1.7 32 | */ 33 | public class RpcTimedOutException extends HBaseException { 34 | 35 | /** 36 | * Constructor. 37 | * @param msg The message of the exception, potentially including a stack 38 | * trace. 39 | */ 40 | RpcTimedOutException(final String msg) { 41 | super(msg); 42 | } 43 | 44 | /** 45 | * Constructor. 46 | * @param msg The message of the exception, potentially including a stack 47 | * trace. 48 | * @param cause The exception that caused this one to be thrown. 49 | */ 50 | RpcTimedOutException(final String msg, final Throwable cause) { 51 | super(msg, cause); 52 | } 53 | 54 | private static final long serialVersionUID = -6245448564580938789L; 55 | 56 | } 57 | 58 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/ScanFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 The Async BigTable Authors. All rights reserved. 3 | * This file is part of Async BigTable. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | import org.apache.hadoop.hbase.filter.Filter; 30 | 31 | /** 32 | * Abstract base class for {@link org.hbase.async.Scanner} filters. 33 | *

34 | * These filters are executed on the server side, inside the 35 | * {@code RegionServer}, while scanning. They are useful to 36 | * prune uninteresting data before it gets to the network, 37 | * but remember that the {@code RegionServer} still has to 38 | * load the data before it can know whether the filter passes 39 | * or not, so it's generally not efficient to filter out large 40 | * amounts of data. 41 | *

42 | * Subclasses are guaranteed to be immutable and are thus 43 | * thread-safe as well as usable concurrently on multiple 44 | * {@link org.hbase.async.Scanner} instances. 45 | */ 46 | public abstract class ScanFilter { 47 | 48 | /** Package-private constructor to avoid sub-classing outside this package. */ 49 | ScanFilter() { 50 | } 51 | 52 | /** 53 | * Returns the name of this scanner on the wire. 54 | *

55 | * This method is only used with HBase 0.95 and newer. 56 | * The contents of the array returned MUST NOT be modified. 57 | */ 58 | abstract byte[] name(); 59 | 60 | abstract Filter getBigtableFilter(); 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/TableNotFoundException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 The Async BigTable Authors. All rights reserved. 3 | * This file is part of Async BigTable. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | /** 30 | * Exception thrown when an attempt to use an inexistent table was made. 31 | */ 32 | public final class TableNotFoundException extends NonRecoverableException { 33 | 34 | private final byte[] table; 35 | 36 | /** 37 | * Constructor. 38 | */ 39 | TableNotFoundException() { 40 | super("(unknown table)"); 41 | table = null; 42 | } 43 | 44 | /** 45 | * Constructor. 46 | * @param table The table that wasn't found. 47 | */ 48 | TableNotFoundException(final byte[] table) { 49 | super(Bytes.pretty(table)); 50 | this.table = table; 51 | } 52 | 53 | /** 54 | * Returns the table that was doesn't exist. 55 | */ 56 | public byte[] getTable() { 57 | return table; 58 | } 59 | 60 | private static final long serialVersionUID = 1280638742; 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/UnknownScannerException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 The Async BigTable Authors. All rights reserved. 3 | * This file is part of Async BigTable. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | /** 30 | * Exception thrown when we try to use an invalid or expired scanner ID. 31 | */ 32 | public final class UnknownScannerException extends RecoverableException { 33 | 34 | static final String REMOTE_CLASS = 35 | "org.apache.hadoop.hbase.UnknownScannerException"; 36 | 37 | /** 38 | * Constructor. 39 | * @param msg The message of the exception, potentially with a stack trace. 40 | * @param failed_rpc The RPC that caused this exception, if known, or null. 41 | */ 42 | UnknownScannerException(final String msg) { 43 | super(msg + "\nCaused by RPC: " ); 44 | // this.failed_rpc = failed_rpc; 45 | } 46 | 47 | private static final long serialVersionUID = 1281457342; 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/jsr166e/LongAdder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Written by Doug Lea with assistance from members of JCP JSR-166 3 | * Expert Group and released to the public domain, as explained at 4 | * http://creativecommons.org/publicdomain/zero/1.0/ 5 | */ 6 | 7 | package org.hbase.async.jsr166e; 8 | import java.util.concurrent.atomic.AtomicLong; 9 | import java.io.IOException; 10 | import java.io.Serializable; 11 | import java.io.ObjectInputStream; 12 | import java.io.ObjectOutputStream; 13 | 14 | /** 15 | * One or more variables that together maintain an initially zero 16 | * {@code long} sum. When updates (method {@link #add}) are contended 17 | * across threads, the set of variables may grow dynamically to reduce 18 | * contention. Method {@link #sum} (or, equivalently, {@link 19 | * #longValue}) returns the current total combined across the 20 | * variables maintaining the sum. 21 | * 22 | *

This class is usually preferable to {@link AtomicLong} when 23 | * multiple threads update a common sum that is used for purposes such 24 | * as collecting statistics, not for fine-grained synchronization 25 | * control. Under low update contention, the two classes have similar 26 | * characteristics. But under high contention, expected throughput of 27 | * this class is significantly higher, at the expense of higher space 28 | * consumption. 29 | * 30 | *

This class extends {@link Number}, but does not define 31 | * methods such as {@code hashCode} and {@code compareTo} because 32 | * instances are expected to be mutated, and so are not useful as 33 | * collection keys. 34 | * 35 | *

jsr166e note: This class is targeted to be placed in 36 | * java.util.concurrent.atomic 37 | * 38 | * @since 1.8 39 | * @author Doug Lea 40 | */ 41 | public class LongAdder extends Striped64 implements Serializable { 42 | private static final long serialVersionUID = 7249069246863182397L; 43 | 44 | /** 45 | * Version of plus for use in retryUpdate 46 | */ 47 | final long fn(long v, long x) { return v + x; } 48 | 49 | /** 50 | * Creates a new adder with initial sum of zero. 51 | */ 52 | public LongAdder() { 53 | } 54 | 55 | /** 56 | * Adds the given value. 57 | * 58 | * @param x the value to add 59 | */ 60 | public void add(long x) { 61 | Cell[] as; long b, v; HashCode hc; Cell a; int n; 62 | if ((as = cells) != null || !casBase(b = base, b + x)) { 63 | boolean uncontended = true; 64 | int h = (hc = threadHashCode.get()).code; 65 | if (as == null || (n = as.length) < 1 || 66 | (a = as[(n - 1) & h]) == null || 67 | !(uncontended = a.cas(v = a.value, v + x))) 68 | retryUpdate(x, hc, uncontended); 69 | } 70 | } 71 | 72 | /** 73 | * Equivalent to {@code add(1)}. 74 | */ 75 | public void increment() { 76 | add(1L); 77 | } 78 | 79 | /** 80 | * Equivalent to {@code add(-1)}. 81 | */ 82 | public void decrement() { 83 | add(-1L); 84 | } 85 | 86 | /** 87 | * Returns the current sum. The returned value is NOT an 88 | * atomic snapshot: Invocation in the absence of concurrent 89 | * updates returns an accurate result, but concurrent updates that 90 | * occur while the sum is being calculated might not be 91 | * incorporated. 92 | * 93 | * @return the sum 94 | */ 95 | public long sum() { 96 | long sum = base; 97 | Cell[] as = cells; 98 | if (as != null) { 99 | int n = as.length; 100 | for (int i = 0; i < n; ++i) { 101 | Cell a = as[i]; 102 | if (a != null) 103 | sum += a.value; 104 | } 105 | } 106 | return sum; 107 | } 108 | 109 | /** 110 | * Resets variables maintaining the sum to zero. This method may 111 | * be a useful alternative to creating a new adder, but is only 112 | * effective if there are no concurrent updates. Because this 113 | * method is intrinsically racy, it should only be used when it is 114 | * known that no threads are concurrently updating. 115 | */ 116 | public void reset() { 117 | internalReset(0L); 118 | } 119 | 120 | /** 121 | * Equivalent in effect to {@link #sum} followed by {@link 122 | * #reset}. This method may apply for example during quiescent 123 | * points between multithreaded computations. If there are 124 | * updates concurrent with this method, the returned value is 125 | * not guaranteed to be the final value occurring before 126 | * the reset. 127 | * 128 | * @return the sum 129 | */ 130 | public long sumThenReset() { 131 | long sum = base; 132 | Cell[] as = cells; 133 | base = 0L; 134 | if (as != null) { 135 | int n = as.length; 136 | for (int i = 0; i < n; ++i) { 137 | Cell a = as[i]; 138 | if (a != null) { 139 | sum += a.value; 140 | a.value = 0L; 141 | } 142 | } 143 | } 144 | return sum; 145 | } 146 | 147 | /** 148 | * Returns the String representation of the {@link #sum}. 149 | * @return the String representation of the {@link #sum} 150 | */ 151 | public String toString() { 152 | return Long.toString(sum()); 153 | } 154 | 155 | /** 156 | * Equivalent to {@link #sum}. 157 | * 158 | * @return the sum 159 | */ 160 | public long longValue() { 161 | return sum(); 162 | } 163 | 164 | /** 165 | * Returns the {@link #sum} as an {@code int} after a narrowing 166 | * primitive conversion. 167 | */ 168 | public int intValue() { 169 | return (int)sum(); 170 | } 171 | 172 | /** 173 | * Returns the {@link #sum} as a {@code float} 174 | * after a widening primitive conversion. 175 | */ 176 | public float floatValue() { 177 | return (float)sum(); 178 | } 179 | 180 | /** 181 | * Returns the {@link #sum} as a {@code double} after a widening 182 | * primitive conversion. 183 | */ 184 | public double doubleValue() { 185 | return (double)sum(); 186 | } 187 | 188 | private void writeObject(java.io.ObjectOutputStream s) 189 | throws java.io.IOException { 190 | s.defaultWriteObject(); 191 | s.writeLong(sum()); 192 | } 193 | 194 | private void readObject(ObjectInputStream s) 195 | throws IOException, ClassNotFoundException { 196 | s.defaultReadObject(); 197 | busy = 0; 198 | cells = null; 199 | base = s.readLong(); 200 | } 201 | 202 | } 203 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/jsr166e/README: -------------------------------------------------------------------------------- 1 | The contents of this directory contains code from JSR 166e. 2 | ** THIS IS NOT PART OF THE PUBLIC INTERFACE OF ASYNCHBASE ** 3 | 4 | Code was downloaded from: 5 | http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/ 6 | 7 | The code was released to the public domain, as explained at 8 | http://creativecommons.org/publicdomain/zero/1.0/ 9 | 10 | The code is bundled in asynchbase as it is not available until JDK8 11 | becomes a reality, which is expected to take years (at time of writing). 12 | Ideally another library, such as Google Guava, would provide this 13 | code until JDK8 becomes the norm. But in the mean time it's here 14 | for asynchbase's internal use. 15 | -------------------------------------------------------------------------------- /src/main/java/org/hbase/async/jsr166e/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010-2012 The Async HBase Authors. All rights reserved. 3 | * This file is part of Async HBase. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | /** 29 | *

This package is not part of asynchbase's public interface.

30 | * Use {@link org.hbase.async.Counter} instead. 31 | */ 32 | package org.hbase.async.jsr166e; 33 | -------------------------------------------------------------------------------- /src/test/java/org/hbase/async/DataGenerationHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 The Async BigTable Authors. All rights reserved. 3 | * This file is part of Async BigTable. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | import org.apache.commons.lang.RandomStringUtils; 30 | import org.apache.hadoop.hbase.util.Bytes; 31 | 32 | /** 33 | * Methods to generate test data. 34 | */ 35 | public class DataGenerationHelper { 36 | 37 | public byte[] randomData(String prefix) { 38 | return randomData(prefix, ""); 39 | } 40 | 41 | public byte[] randomData(String prefix, String suffix) { 42 | return Bytes.toBytes(randomString(prefix, suffix)); 43 | } 44 | 45 | public String randomString(String prefix) { 46 | return randomString(prefix, ""); 47 | } 48 | 49 | public String randomString(String prefix, String suffix) { 50 | return prefix + RandomStringUtils.randomAlphanumeric(8) + suffix; 51 | } 52 | 53 | public byte[][] randomData(String prefix, int count) { 54 | byte[][] result = new byte[count][]; 55 | for (int i = 0; i < count; ++i) { 56 | result[i] = Bytes.toBytes(prefix + RandomStringUtils.randomAlphanumeric(8)); 57 | } 58 | return result; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/test/java/org/hbase/async/FiltersTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014-2017 The Async HBase Authors. All rights reserved. 3 | * This file is part of Async HBase. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | import org.apache.hadoop.hbase.shaded.protobuf.generated.FilterProtos; 30 | import org.junit.Assert; 31 | import org.junit.Test; 32 | import org.junit.runner.RunWith; 33 | import org.junit.runners.JUnit4; 34 | 35 | @RunWith(JUnit4.class) 36 | public class FiltersTest { 37 | 38 | @Test 39 | public void ensureKeyOnlyFilterIsCorrectlyCreated() { 40 | KeyOnlyFilter keyOnlyFilter = new KeyOnlyFilter(); 41 | org.apache.hadoop.hbase.filter.KeyOnlyFilter filter = (org.apache.hadoop.hbase.filter.KeyOnlyFilter) keyOnlyFilter.getBigtableFilter(); 42 | Assert.assertNotNull(filter); 43 | Assert.assertArrayEquals(filter.toByteArray(), keyOnlyToByteArray(false)); 44 | } 45 | 46 | @Test 47 | public void ensureKeyOnlyFilterIsCorrectlyCreatedWithArgs() { 48 | KeyOnlyFilter keyOnlyFilter = new KeyOnlyFilter(true); 49 | org.apache.hadoop.hbase.filter.KeyOnlyFilter filter = (org.apache.hadoop.hbase.filter.KeyOnlyFilter) keyOnlyFilter.getBigtableFilter(); 50 | Assert.assertNotNull(filter); 51 | Assert.assertArrayEquals(filter.toByteArray(), keyOnlyToByteArray(true)); 52 | } 53 | 54 | @Test 55 | public void ensureColumnPrefixFilterIsCorrectlyCreated() { 56 | final byte[] prefix = Bytes.UTF8("aoeu"); 57 | ColumnPrefixFilter columnPrefixFilter = new ColumnPrefixFilter(prefix); 58 | org.apache.hadoop.hbase.filter.ColumnPrefixFilter filter = (org.apache.hadoop.hbase.filter.ColumnPrefixFilter) columnPrefixFilter.getBigtableFilter(); 59 | Assert.assertNotNull(filter); 60 | Assert.assertArrayEquals(filter.getPrefix(), prefix); 61 | } 62 | 63 | private byte[] keyOnlyToByteArray(boolean value) { 64 | FilterProtos.KeyOnlyFilter.Builder builder = org.apache.hadoop.hbase.shaded.protobuf.generated.FilterProtos.KeyOnlyFilter.newBuilder(); 65 | builder.setLenAsVal(value); 66 | return builder.build().toByteArray(); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/test/java/org/hbase/async/HBaseClientIT.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 The Async BigTable Authors. All rights reserved. 3 | * This file is part of Async BigTable. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */package org.hbase.async; 27 | 28 | import java.util.ArrayList; 29 | import java.util.UUID; 30 | import java.util.concurrent.CompletableFuture; 31 | import java.util.concurrent.Executors; 32 | import java.util.concurrent.TimeUnit; 33 | 34 | import org.apache.commons.lang.ArrayUtils; 35 | import org.apache.hadoop.hbase.TableName; 36 | import org.apache.hadoop.hbase.TableNotFoundException; 37 | import org.apache.hadoop.hbase.client.AsyncAdmin; 38 | import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; 39 | import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 40 | import org.apache.hadoop.hbase.util.Bytes; 41 | import org.junit.AfterClass; 42 | import org.junit.Assert; 43 | import org.junit.BeforeClass; 44 | import org.junit.Test; 45 | import org.junit.runner.RunWith; 46 | import org.junit.runners.JUnit4; 47 | 48 | import com.google.cloud.bigtable.hbase.BigtableConfiguration; 49 | import com.stumbleupon.async.Callback; 50 | import com.stumbleupon.async.Deferred; 51 | 52 | @RunWith(JUnit4.class) 53 | public class HBaseClientIT { 54 | 55 | private static TableName TABLE_NAME = 56 | TableName.valueOf("test_table-" + UUID.randomUUID().toString()); 57 | private static byte[] FAMILY = Bytes.toBytes("cf"); 58 | private static final DataGenerationHelper dataHelper = new DataGenerationHelper(); 59 | private static HBaseClient client; 60 | 61 | @BeforeClass 62 | public static void createTable() throws Exception { 63 | String projectId = System.getProperty("google.bigtable.project.id"); 64 | String instanceId = System.getProperty("google.bigtable.instance.id"); 65 | client = new HBaseClient(BigtableConfiguration.configure(projectId, instanceId), 66 | Executors.newCachedThreadPool()); 67 | AsyncAdmin admin = client.getBigtableAsyncConnection().getAdmin(); 68 | admin 69 | .createTable(TableDescriptorBuilder.newBuilder(TABLE_NAME) 70 | .addColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder(FAMILY).build()).build()) 71 | .get(10, TimeUnit.SECONDS); 72 | } 73 | 74 | @AfterClass 75 | public static void deleteTable() throws Exception { 76 | AsyncAdmin admin = client.getBigtableAsyncConnection().getAdmin(); 77 | admin.deleteTable(TABLE_NAME).get(10, TimeUnit.SECONDS); 78 | } 79 | 80 | @Test 81 | public void testEnsureTableFamilyExists() throws Exception { 82 | client.ensureTableFamilyExists(TABLE_NAME.toBytes(), FAMILY).join(); 83 | Assert.assertTrue(true); 84 | } 85 | 86 | @Test(expected=NoSuchColumnFamilyException.class) 87 | public void testEnsureTableFamilyExists_nocf() throws Exception { 88 | client.ensureTableFamilyExists(TABLE_NAME.toBytes(), Bytes.toBytes("nonExistingCF")).join(); 89 | } 90 | 91 | @Test(expected=TableNotFoundException.class) 92 | public void testEnsureTableFamilyExists_noTable() throws Exception { 93 | client.ensureTableFamilyExists("nonExistingTable".getBytes(), Bytes.toBytes("nonexistingCF")).join(); 94 | } 95 | 96 | @Test 97 | public void atomicIncrement() throws Exception { 98 | byte[] rowKey = dataHelper.randomData("putKey-"); 99 | byte[] qualifier = Bytes.toBytes("qual"); 100 | byte[] value = Bytes.toBytes(5l); 101 | 102 | Deferred deferredPut = client.put(new PutRequest(TABLE_NAME.getName(), rowKey, FAMILY, qualifier, value)); 103 | client.flush().join(); 104 | deferredPut.join(); 105 | 106 | AtomicIncrementRequest req = new AtomicIncrementRequest(TABLE_NAME.toBytes(), rowKey, FAMILY, qualifier, 2); 107 | Assert.assertEquals((Long)7L, client.atomicIncrement(req).join()); 108 | assertGetEquals(rowKey, qualifier, Bytes.toBytes(7l)); 109 | } 110 | 111 | @Test 112 | public void atomicIncrement_nonexisting() throws Exception { 113 | byte[] rowKey = dataHelper.randomData("putKey-"); 114 | byte[] qualifier = Bytes.toBytes("qual"); 115 | 116 | AtomicIncrementRequest req = new AtomicIncrementRequest(TABLE_NAME.toBytes(), rowKey, FAMILY, qualifier, 1); 117 | Assert.assertEquals((Long)1L, client.atomicIncrement(req).join()); 118 | assertGetEquals(rowKey, qualifier, Bytes.toBytes(1l)); 119 | } 120 | 121 | @Test 122 | public void compareAndSet() throws Exception { 123 | byte[] rowKey = dataHelper.randomData("putKey-"); 124 | byte[] qualifier = Bytes.toBytes("qual"); 125 | byte[] value = Bytes.toBytes(1l); 126 | 127 | //add new when empty 128 | PutRequest putRequest = new PutRequest(TABLE_NAME.toBytes(), rowKey, FAMILY, qualifier, value); 129 | Assert.assertTrue(client.compareAndSet(putRequest, new byte[0]).join()); 130 | assertGetEquals(rowKey, qualifier, Bytes.toBytes(1l)); 131 | 132 | putRequest = new PutRequest(TABLE_NAME.toBytes(), rowKey, FAMILY, qualifier, Bytes.toBytes(9l)); 133 | Assert.assertTrue(client.compareAndSet(putRequest, value).join()); 134 | assertGetEquals(rowKey, qualifier, Bytes.toBytes(9l)); 135 | } 136 | 137 | /** 138 | * Really basic test to make sure that put, get and delete work. 139 | */ 140 | @Test 141 | public void testBasics() throws Exception { 142 | byte[] rowKey = dataHelper.randomData("putKey-"); 143 | byte[] qualifier = Bytes.toBytes("qual"); 144 | byte[] value = dataHelper.randomData("value-"); 145 | 146 | // Write the value, and make sure it's written 147 | Deferred deferredPut = client.put(new PutRequest(TABLE_NAME.getName(), rowKey, FAMILY, qualifier, value)); 148 | client.flush().join(); 149 | deferredPut.join(); 150 | 151 | // Make sure that the value is as expected 152 | assertGetEquals(rowKey, qualifier, value); 153 | 154 | // Delete the value 155 | Deferred deferredDelete = client.delete(new DeleteRequest(TABLE_NAME.getName(), rowKey)); 156 | client.flush().join(); 157 | deferredDelete.join(); 158 | 159 | // Make sure that the value is deleted 160 | Assert.assertEquals(0, get(rowKey).size()); 161 | } 162 | 163 | @Test 164 | public void testAppendAndScan() throws Exception { 165 | byte[] rowKey = dataHelper.randomData("appendKey-"); 166 | byte[] rowKey2 = dataHelper.randomData("appendKey2-"); 167 | byte[] qualifier = dataHelper.randomData("qualifier-"); 168 | byte[] value1 = dataHelper.randomData("value1-"); 169 | byte[] value2 = dataHelper.randomData("value1-"); 170 | byte[] value1And2 = ArrayUtils.addAll(value1, value2); 171 | 172 | // Write the value, and make sure it's written 173 | Deferred deferredPut = client.put(new PutRequest(TABLE_NAME.getName(), rowKey, FAMILY, qualifier, value1)); 174 | client.flush().join(); 175 | deferredPut.join(); 176 | 177 | client 178 | .append( 179 | new AppendRequest(TABLE_NAME.getName(), new KeyValue(rowKey, FAMILY, qualifier, value2))) 180 | .join(); 181 | 182 | ArrayList response = get(rowKey); 183 | Assert.assertEquals(1, response.size()); 184 | Assert.assertTrue(Bytes.equals(value1And2, response.get(0).value())); 185 | 186 | 187 | deferredPut = client.put(new PutRequest(TABLE_NAME.getName(), rowKey2, FAMILY, qualifier, value1)); 188 | client.flush().join(); 189 | deferredPut.join(); 190 | 191 | Scanner scanner = new Scanner(client, TABLE_NAME.toBytes()); 192 | client.openScanner(scanner); 193 | 194 | ArrayList> nextRows = scanner.nextRows(2).join(); 195 | Assert.assertEquals(2, nextRows.size()); 196 | } 197 | 198 | private void assertGetEquals(byte[] key, byte[] qual, byte[] val) 199 | throws Exception { 200 | ArrayList response = get(key); 201 | Assert.assertEquals(1, response.size()); 202 | KeyValue result = response.get(0); 203 | 204 | Assert.assertTrue(Bytes.equals(FAMILY, result.family())); 205 | Assert.assertTrue(Bytes.equals(qual, result.qualifier())); 206 | Assert.assertTrue(Bytes.equals(val, result.value())); 207 | } 208 | 209 | private ArrayList get(byte[] key) throws Exception { 210 | return client.get(new GetRequest(TABLE_NAME.getName(), key)).join(); 211 | } 212 | 213 | @Test 214 | public void testConvertToDeferred() throws Exception { 215 | CompletableFuture f = CompletableFuture.supplyAsync(() -> { 216 | return 100; 217 | }); 218 | 219 | Deferred deferred = HBaseClient.convertToDeferred(f) 220 | .addCallback(new Callback() { 221 | 222 | @Override 223 | public Integer call(Integer arg) throws Exception { 224 | return 2 * arg; 225 | } 226 | }); 227 | 228 | Assert.assertEquals((Integer) (100 * 2), deferred.join()); 229 | } 230 | 231 | @Test 232 | public void testConvertVoidToDeferred() throws Exception { 233 | CompletableFuture f = CompletableFuture.runAsync(() -> { 234 | // 235 | }); 236 | 237 | HBaseClient.convertToDeferred(f).join(); 238 | Assert.assertTrue(true); 239 | } 240 | 241 | @Test(expected = Exception.class) 242 | public void testConvertToDeferred_exception() throws Exception { 243 | CompletableFuture f = CompletableFuture.supplyAsync(() -> { 244 | throw new RuntimeException(); 245 | }); 246 | 247 | HBaseClient.convertToDeferred(f).join(); 248 | } 249 | } 250 | -------------------------------------------------------------------------------- /src/test/java/org/hbase/async/TestHBaseClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 The Async BigTable Authors. All rights reserved. 3 | * This file is part of Async BigTable. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */package org.hbase.async; 27 | 28 | import org.apache.hadoop.conf.Configuration; 29 | import org.junit.Test; 30 | import org.junit.runner.RunWith; 31 | import org.junit.runners.JUnit4; 32 | 33 | import com.google.cloud.bigtable.hbase.BigtableConfiguration; 34 | 35 | @RunWith(JUnit4.class) 36 | public class TestHBaseClient { 37 | 38 | /** 39 | * Really basic test to make sure that Cloud Bigtable connections can be made. 40 | */ 41 | @Test 42 | public void testConnect() { 43 | Configuration conf = BigtableConfiguration.configure("someProjectId", "someInstanceId"); 44 | @SuppressWarnings("unused") 45 | HBaseClient client = new HBaseClient(conf, null); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %d{ISO8601} %-5level [%thread] %logger{0}: %msg%n 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /test/Common.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 The Async HBase Authors. All rights reserved. 3 | * This file is part of Async HBase. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async.test; 28 | 29 | import org.jboss.netty.logging.InternalLoggerFactory; 30 | import org.jboss.netty.logging.Slf4JLoggerFactory; 31 | 32 | import org.slf4j.Logger; 33 | import org.slf4j.LoggerFactory; 34 | 35 | import org.hbase.async.HBaseClient; 36 | 37 | final class Common { 38 | 39 | static { 40 | InternalLoggerFactory.setDefaultFactory(new Slf4JLoggerFactory()); 41 | } 42 | 43 | static Logger logger(final Class klass) { 44 | return LoggerFactory.getLogger(klass); 45 | } 46 | 47 | static HBaseClient getOpt(final Class klass, final String[] args) { 48 | if (args.length < 2) { 49 | System.err.println("Usage: " + klass.getSimpleName() 50 | + " [zkquorum] [znode]"); 51 | System.exit(1); 52 | } 53 | final String zkquorum; 54 | if (args.length > 2) { 55 | zkquorum = args[2]; 56 | } else { 57 | zkquorum = "localhost"; 58 | } 59 | final HBaseClient client; 60 | if (args.length > 3) { 61 | return new HBaseClient(zkquorum, args[3]); 62 | } else { 63 | return new HBaseClient(zkquorum); // Default znode 64 | } 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /test/TestIncrementCoalescing.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 The Async HBase Authors. All rights reserved. 3 | * This file is part of Async HBase. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async.test; 28 | 29 | import java.util.ArrayList; 30 | import java.util.Random; 31 | 32 | import com.google.common.cache.CacheStats; 33 | 34 | import org.slf4j.Logger; 35 | 36 | import org.hbase.async.AtomicIncrementRequest; 37 | import org.hbase.async.Bytes; 38 | import org.hbase.async.DeleteRequest; 39 | import org.hbase.async.HBaseClient; 40 | import org.hbase.async.KeyValue; 41 | import org.hbase.async.Scanner; 42 | 43 | import com.stumbleupon.async.Callback; 44 | 45 | import org.hbase.async.test.Common; 46 | 47 | /** 48 | * Integration test for increment coalescing. 49 | * 50 | * Requires a locally running HBase cluster. 51 | */ 52 | final class TestIncrementCoalescing { 53 | 54 | private static final Logger LOG = 55 | Common.logger(TestIncrementCoalescing.class); 56 | 57 | public static void main(final String[] args) throws Exception { 58 | if (LOG.isDebugEnabled()) { 59 | LOG.warn("Debug logging enabled, this test will flood it pretty hard."); 60 | } 61 | if (Runtime.getRuntime().maxMemory() < 1992294400L) { 62 | LOG.error("This test requires at least 2GB of RAM to run."); 63 | LOG.error("Use JVM_ARGS='-Xmx2g -Xms2g'."); 64 | System.exit(3); 65 | } 66 | final HBaseClient client = Common.getOpt(TestIncrementCoalescing.class, 67 | args); 68 | final byte[] table = args[0].getBytes(); 69 | final byte[] family = args[1].getBytes(); 70 | try { 71 | test(client, table, family); 72 | } finally { 73 | client.shutdown().join(); 74 | } 75 | } 76 | 77 | private static volatile boolean failed = false; 78 | private static final Callback LOG_ERROR = 79 | new Callback() { 80 | public Exception call(final Exception e) { 81 | LOG.error("RPC failed", e); 82 | failed = true; 83 | return e; 84 | } 85 | }; 86 | 87 | /** Number of increments for each row. */ 88 | private static final int ICV_PER_ROW = 1000; 89 | 90 | /** Number of different keys we'll do increments on. */ 91 | private static final int NUM_ROWS = 1000; 92 | 93 | private static final byte[] QUALIFIER = {'c', 'n', 't'}; 94 | 95 | private static void test(final HBaseClient client, 96 | final byte[] table, 97 | final byte[] family) throws Exception { 98 | final Random rnd = new Random(); 99 | 100 | final class IncrementThread extends Thread { 101 | 102 | private final int num; 103 | 104 | IncrementThread(final int num) { 105 | super("IncrementThread-" + num); 106 | this.num = num; 107 | } 108 | 109 | public void run() { 110 | for (int iteration = 0; iteration < ICV_PER_ROW; iteration++) { 111 | final int r = rnd.nextInt(NUM_ROWS); 112 | final int n = r + NUM_ROWS; 113 | for (int i = r; i < n; i++) { 114 | icv(i); 115 | } 116 | } 117 | } 118 | 119 | private void icv(final int i) { 120 | final byte[] key = key(i); 121 | final AtomicIncrementRequest incr = 122 | new AtomicIncrementRequest(table, key, family, QUALIFIER); 123 | client.bufferAtomicIncrement(incr).addErrback(LOG_ERROR); 124 | } 125 | 126 | } 127 | 128 | client.ensureTableFamilyExists(table, family).join(); 129 | 130 | LOG.info("Deleting existing rows..."); 131 | for (int i = 0; i < NUM_ROWS; i++) { 132 | client.delete(new DeleteRequest(table, key(i), family, QUALIFIER)) 133 | .addErrback(LOG_ERROR); 134 | } 135 | client.flush().join(); 136 | LOG.info("Done deleting existing rows."); 137 | 138 | final int nthreads = Runtime.getRuntime().availableProcessors() * 2; 139 | final IncrementThread[] threads = new IncrementThread[nthreads]; 140 | for (int i = 0; i < nthreads; i++) { 141 | threads[i] = new IncrementThread(i); 142 | } 143 | long timing = System.nanoTime(); 144 | for (int i = 0; i < nthreads; i++) { 145 | threads[i].start(); 146 | } 147 | for (int i = 0; i < nthreads; i++) { 148 | threads[i].join(); 149 | } 150 | client.flush().join(); 151 | timing = (System.nanoTime() - timing) / 1000000; 152 | final int nrpcs = nthreads * ICV_PER_ROW * NUM_ROWS; 153 | LOG.info(nrpcs + " increments in " + timing + "ms = " 154 | + (nrpcs * 1000L / timing) + "/s"); 155 | final CacheStats stats = client.stats().incrementBufferStats(); 156 | LOG.info("Increments coalesced: " + stats.hitCount()); 157 | LOG.info("Increments sent to HBase: " + stats.missCount()); 158 | LOG.info(" due to cache evictions: " + stats.evictionCount()); 159 | 160 | LOG.info("Reading all counters back from HBase and checking values..."); 161 | final Scanner scanner = client.newScanner(table); 162 | scanner.setStartKey(key(0)); 163 | scanner.setStopKey(key(NUM_ROWS)); 164 | scanner.setFamily(family); 165 | scanner.setQualifier(QUALIFIER); 166 | ArrayList> rows; 167 | final long expected = nthreads * ICV_PER_ROW; 168 | while ((rows = scanner.nextRows().join()) != null) { 169 | for (final ArrayList row : rows) { 170 | final long value = Bytes.getLong(row.get(0).value()); 171 | if (value != expected) { 172 | LOG.error("Invalid count in " + row.get(0) + ": " + value); 173 | failed = true; 174 | } 175 | } 176 | } 177 | LOG.info("Done checking counter values."); 178 | 179 | if (failed) { 180 | LOG.error("At least one counter increment failed!"); 181 | System.exit(2); 182 | } 183 | } 184 | 185 | /** Returns the key to increment for a given number. */ 186 | private static final byte[] key(final int i) { 187 | return new byte[] { 'c', 'n', 't', 188 | (byte) ((i / 100 % 10) + '0'), 189 | (byte) ((i / 10 % 10) + '0'), 190 | (byte) ((i % 10) + '0') 191 | }; 192 | } 193 | 194 | } 195 | -------------------------------------------------------------------------------- /test/TestMETALookup.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 The Async HBase Authors. All rights reserved. 3 | * This file is part of Async HBase. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * - Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * - Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * - Neither the name of the StumbleUpon nor the names of its contributors 13 | * may be used to endorse or promote products derived from this software 14 | * without specific prior written permission. 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | package org.hbase.async; 28 | 29 | import java.util.Comparator; 30 | 31 | import org.junit.Test; 32 | import org.junit.runner.RunWith; 33 | import static org.junit.Assert.fail; 34 | 35 | import org.powermock.core.classloader.annotations.PrepareForTest; 36 | import org.powermock.modules.junit4.PowerMockRunner; 37 | 38 | /** 39 | * Unit tests for META lookups and associated regressions. 40 | */ 41 | @RunWith(PowerMockRunner.class) 42 | @PrepareForTest 43 | final class TestMETALookup { 44 | 45 | private static final Comparator cmp = RegionInfo.REGION_NAME_CMP; 46 | 47 | @Test 48 | public void testRegionCmp() { 49 | // Different table names. 50 | assertGreater("table,,1234567890", ".META.,,1234567890"); 51 | // Any key is greater than the start key. 52 | assertGreater("table,foo,1234567890", "table,,1234567890"); 53 | // Different keys. 54 | assertGreater("table,foo,1234567890", "table,bar,1234567890"); 55 | // Shorter key is smaller than longer key. 56 | assertGreater("table,fool,1234567890", "table,foo,1234567890"); 57 | // Properly handle keys that contain commas. 58 | assertGreater("table,a,,c,1234567890", "table,a,,b,1234567890"); 59 | // If keys are equal, then start code should break the tie. 60 | assertGreater("table,foo,1234567891", "table,foo,1234567890"); 61 | // Make sure that a start code being a prefix of another is handled. 62 | assertGreater("table,foo,1234567890", "table,foo,123456789"); 63 | // If both are start keys, then start code should break the tie. 64 | assertGreater("table,,1234567891", "table,,1234567890"); 65 | // The value `:' is always greater than any start code. 66 | assertGreater("table,foo,:", "table,foo,9999999999"); 67 | // Issue 27: searching for key "8,\001" and region key is "8". 68 | assertGreater("table,8,\001,:", "table,8,1339667458224"); 69 | } 70 | 71 | /** Ensures that {@code sa > sb} in the META cache. */ 72 | private static void assertGreater(final String sa, final String sb) { 73 | final byte[] a = sa.getBytes(); 74 | final byte[] b = sb.getBytes(); 75 | int c = cmp.compare(a, b); 76 | if (c <= 0) { 77 | fail("compare(" + Bytes.pretty(a) + ", " + Bytes.pretty(b) + ")" 78 | + " returned " + c + ", but was expected to return > 0"); 79 | } 80 | c = cmp.compare(b, a); 81 | if (c >= 0) { 82 | fail("compare(" + Bytes.pretty(b) + ", " + Bytes.pretty(a) + ")" 83 | + " returned " + c + ", but was expected to return < 0"); 84 | } 85 | } 86 | 87 | } 88 | --------------------------------------------------------------------------------