diff --git a/.gitattributes b/.gitattributes index f03238ebf5d7..9e4b13956500 100644 --- a/.gitattributes +++ b/.gitattributes @@ -22,4 +22,5 @@ # Declare files that will always have CRLF line endings on checkout. *.sln text eol=crlf - +*.bat text eol=crlf +*.cmd text eol=crlf diff --git a/NOTICE.txt b/NOTICE.txt index 337c93beafcd..f03367f86154 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -18,3 +18,9 @@ for details: https://github.com/jruby/jruby/blob/master/COPYING The JRuby community went out of their way to make JRuby compatible with Apache projects: See https://issues.apache.org/jira/browse/HBASE-3374) + +AsyncHBase (https://github.com/OpenTSDB/asynchbase) is a fully asynchronous, +non-blocking, thread-safe, high-performance HBase client. + +Gradle (http://www.gradle.org/) is used to build the native HBase client +under ASL v2.0. See http://www.gradle.org/license. diff --git a/hbase-assembly/pom.xml b/hbase-assembly/pom.xml index 08526425b4b0..08563d0c0e7a 100644 --- a/hbase-assembly/pom.xml +++ b/hbase-assembly/pom.xml @@ -107,4 +107,26 @@ ${project.version} + + + + hbase-native-client + + false + + + + org.apache.hbase + hbase-native-client + ${project.version} + + + org.hbase + asynchbase + + + + + + diff --git a/hbase-assembly/src/main/assembly/hadoop-two-compat.xml b/hbase-assembly/src/main/assembly/hadoop-two-compat.xml index f8ebcda458fb..ffe80259149a 100644 --- a/hbase-assembly/src/main/assembly/hadoop-two-compat.xml +++ b/hbase-assembly/src/main/assembly/hadoop-two-compat.xml @@ -23,7 +23,7 @@ bin - tar.gz + dir src/main/assembly/components.xml @@ -33,12 +33,17 @@ true + + org.apache.hbase:hbase-native-client lib false - + + org.apache.hbase:hbase-native-client + diff --git a/hbase-native-client/.gitignore b/hbase-native-client/.gitignore index f14b3be32d3e..dfda88cab5a6 100644 --- a/hbase-native-client/.gitignore +++ b/hbase-native-client/.gitignore @@ -1,38 +1,14 @@ -# Compiled Object files -*.slo -*.lo -*.o - -# Compiled Dynamic libraries -*.so - -# Compiled Static libraries -*.lai -*.la -*.a - -#python -*.pyc - -# CMake Generated Files -CMakeCache.txt -CMakeFiles -Makefile -cmake_install.CMakeCache -cmake_install.cmake -install_manifest.txt -CTestTestfile.cmake +.classpath +.cproject +.debug_dll +.debug_exe +.gradle +.perf_test +.project +.settings build -Testing - - - -# Thirdparty dirs - -thirdparty/glog-* -thirdparty/gtest-* -thirdparty/gtest -thirdparty/protobuf-* -thirdparty/libevent-* -thirdparty/libev-* -thirdparty/installed +gradle-wrapper.properties +gradle-wrapper.jar +target +*~ +*.patch diff --git a/hbase-native-client/CMakeLists.txt b/hbase-native-client/CMakeLists.txt deleted file mode 100644 index be872df9c620..000000000000 --- a/hbase-native-client/CMakeLists.txt +++ /dev/null @@ -1,153 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -cmake_minimum_required(VERSION 2.6) - -# generate CTest input files -enable_testing() - -# where to find cmake modules -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake_modules") - -# if no build build type is specified, default to debug builds -if (NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Debug) -endif(NOT CMAKE_BUILD_TYPE) - -STRING(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE) - -set(CXX_COMMON_FLAGS "-Wall -Wextra -std=c++11") -set(C_COMMON_FLAGS "-Wall -Wextra -std=c11") - -set(CXX_FLAGS_DEBUG "-ggdb -g") -set(C_FLAGS_DEBUG "-ggdb") - -set(CXX_FLAGS_FASTDEBUG "-ggdb -O1") -set(C_FLAGS_FASTDEBUG "-ggdb -O1") - -set(CXX_FLAGS_RELEASE "-O3 -g -DNDEBUG -Wno-strict-aliasing") -set(C_FLAGS_RELEASE "-O3 -g -DNDEBUG -Wno-strict-aliasing") - -# if no build build type is specified, default to debug builds -if (NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Debug) -endif(NOT CMAKE_BUILD_TYPE) - -string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE) - -# Set compile flags based on the build type. -message("Configured for ${CMAKE_BUILD_TYPE} build (set with cmake -DCMAKE_BUILD_TYPE={release,debug,...})") -if ("${CMAKE_BUILD_TYPE}" STREQUAL "DEBUG") - set(CMAKE_CXX_FLAGS ${CXX_FLAGS_DEBUG}) - set(CMAKE_C_FLAGS ${C_FLAGS_DEBUG}) -elseif ("${CMAKE_BUILD_TYPE}" STREQUAL "FASTDEBUG") - set(CMAKE_CXX_FLAGS ${CXX_FLAGS_FASTDEBUG}) - set(CMAKE_C_FLAGS ${C_FLAGS_FASTDEBUG}) -elseif ("${CMAKE_BUILD_TYPE}" STREQUAL "RELEASE") - set(CMAKE_CXX_FLAGS ${CXX_FLAGS_RELEASE}) - set(CMAKE_C_FLAGS ${C_FLAGS_RELEASE}) -else() - message(FATAL_ERROR "Unknown build type: ${CMAKE_BUILD_TYPE}") -endif () - -set(CMAKE_CXX_FLAGS "${CXX_COMMON_FLAGS} ${CMAKE_CXX_FLAGS}") -set(CMAKE_C_FLAGS "${C_COMMON_FLAGS} ${CMAKE_C_FLAGS}") - - -# set compile output directory -string(TOLOWER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_LOWERCASE) -set(BUILD_OUTPUT_ROOT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/build/${CMAKE_BUILD_TYPE_LOWERCASE}/") - -# Link build/latest to the current build directory, to avoid developers -# accidentally running the latest debug build when in fact they're building -# release builds. -file(MAKE_DIRECTORY ${BUILD_OUTPUT_ROOT_DIRECTORY}) -execute_process(COMMAND rm -f ${CMAKE_CURRENT_SOURCE_DIR}/build/latest) -execute_process(COMMAND ln -sf ${BUILD_OUTPUT_ROOT_DIRECTORY} - ${CMAKE_CURRENT_SOURCE_DIR}/build/latest) - -# where to put generated libraries -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${BUILD_OUTPUT_ROOT_DIRECTORY}") -set(ARCHIVE_OUTPUT_DIRECTORY "${BUILD_OUTPUT_ROOT_DIRECTORY}") -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${BUILD_OUTPUT_ROOT_DIRECTORY}") - -# where to put generated binaries -set(EXECUTABLE_OUTPUT_PATH "${BUILD_OUTPUT_ROOT_DIRECTORY}") - -include_directories(src) - -##################### -# Third Party -##################### - -# find boost headers and libs -set(Boost_DEBUG TRUE) -set(Boost_USE_MULTITHREADED ON) -find_package(Boost REQUIRED COMPONENTS thread system-mt) -include_directories(${Boost_INCLUDE_DIRS}) - -find_package(Protobuf REQUIRED) -include_directories(${PROTOBUF_INCLUDE_DIRS}) -add_library(protobuf STATIC IMPORTED) -set_target_properties(protobuf PROPERTIES IMPORTED_LOCATION "${PROTOBUF_STATIC_LIBRARY}") - -find_package(LibEv REQUIRED) -include_directories(${LIBEV_INCLUDE_DIR}) -add_library(libev STATIC IMPORTED) - - -set(HBASE_LIBS - ${PROTOBUF} - ${LIBEV} - ${Boost_LIBRARIES} -) -######### -# Testing Config -######### - -# find GTest headers and libs -find_package(GTest REQUIRED) -include_directories(${GTEST_INCLUDE_DIR}) -add_library(gtest STATIC IMPORTED) -set_target_properties(gtest PROPERTIES IMPORTED_LOCATION "${GTEST_LIBS}") - -set(HBASE_TEST_LIBS ${HBASE_LIBS} ${GTEST_LIBS}) -set(HBASE_ASYNC_TEST_LIBS ${HBASE_LIBS} ${GTEST_LIBS} hbase-async) -set(HBASE_SYNC_TEST_LIBS ${HBASE_LIBS} ${GTEST_LIBS} hbase-sync) - -function(ADD_HBASE_ASYNC_TEST TEST_NAME) - add_executable(${TEST_NAME} ${TEST_NAME}.cc) - target_link_libraries(${TEST_NAME} ${HBASE_ASYNC_TEST_LIBS}) - add_test(${TEST_NAME} "${EXECUTABLE_OUTPUT_PATH}/${TEST_NAME}") -endfunction() - - -function(ADD_HBASE_SYNC_TEST TEST_NAME) - add_executable(${TEST_NAME} ${TEST_NAME}.cc) - target_link_libraries(${TEST_NAME} ${HBASE_ASYNC_TEST_LIBS}) - add_test(${TEST_NAME} "${EXECUTABLE_OUTPUT_PATH}/${TEST_NAME}") -endfunction() - - -##### -# Actual project definition -##### -add_subdirectory(src/async) -add_subdirectory(src/sync) - -add_subdirectory(src/core) -add_subdirectory(src/rpc) - - -add_library(hbase-async SHARED $ $) -add_library(hbase-sync SHARED $ $) diff --git a/hbase-native-client/README.md b/hbase-native-client/README.md index a959ecacc562..68ddd60d64ae 100644 --- a/hbase-native-client/README.md +++ b/hbase-native-client/README.md @@ -1,34 +1,58 @@ -# hbase-native-client - -Native client for HBase 0.96 - -This is a C library that implements a -HBase client. It's thread safe and libEv -based. - - -## Design Philosphy - -Synchronous and Async versions will both be built -on the same foundation. The core foundation will -be C++. External users wanting a C library will -have to choose either async or sync. These -libraries will be thin veneers ontop of the C++. - -We should try and follow pthreads example as much -as possible: - -* Consistent naming. -* Opaque pointers as types so that binary compat is easy. -* Simple setup when the defaults are good. -* Attr structs when lots of paramters could be needed. - - -## Naming -All public C files will start with hbase_*.{h, cc}. This -is to keep naming conflicts to a minimum. Anything without -the hbase_ prefix is assumed to be implementation private. - -All C apis and typedefs will be prefixed with hb_. - -All typedefs end with _t. +# libHBase + +Native client for Apache HBase +This is a JNI based, thread safe C library that implements an HBase client. + +## Building the native client +``` + mvn install -Phbase-native-client -DskipTests +``` + +This will build the tarball containing the headers, shared library and the jar +files in the `target` directory with the following structure. + +``` +/ ++---bin/ ++---conf/ ++---include/ +| +--hbase/ ++---lib/ +| +---native/ ++---src + +---examples/ + | +---async/ + +---test/ + +---native/ + +---common/ +``` + +The headers can be found under `include` folder while the shared library to link +against is under `lib/native`. + +## Building and Running Unit Tests +libHBase uses [GTest](https://code.google.com/p/googletest/) as the test framework +for unit/integration tests. During the build process, it automatically downloads +and build the GTest. You will need to have `cmake` installed on the build machine +to build the GTest framwork. + +Runnig the unit tests currently requires you to set `LIBHBASE_ZK_QUORUM` to a valid +HBase Zookeeper quorum. The default is `"localhost:2181"`. This can be either set +as an environment variable or in [this configuration file](src/test/resources/config.properties). +``` +LIBHBASE_ZK_QUORUM=":,..." mvn integration-test +``` + +## Building Applications with libHBase +For examples on how to use the APIs, please take a look at [this sample source] +(src/examples/async/example_async.c). + +As the library uses JNI, you will need to have both `libhbase` and `libjvm` shared +libraries in your application's library search path. The jars required for the +library can be specified through either of the environment variables `CLASSPATH` +or `HBASE_LIB_DIR`. Custom JVM options, for example `-Xmx`, etc can be specified +using the environment variable `LIBHBASE_OPTS`. + +## Performance Testing +A performance test is included with the library which currently support sequential/ +random gets and puts. You can run the tests using this [shell script](bin/perftest.sh). diff --git a/hbase-native-client/bin/build-all.sh b/hbase-native-client/bin/build-all.sh deleted file mode 100755 index a3e45dec25e7..000000000000 --- a/hbase-native-client/bin/build-all.sh +++ /dev/null @@ -1,41 +0,0 @@ -#! /usr/bin/env bash -# -#/** -# * Copyright The Apache Software Foundation -# * -# * Licensed to the Apache Software Foundation (ASF) under one -# * or more contributor license agreements. See the NOTICE file -# * distributed with this work for additional information -# * regarding copyright ownership. The ASF licenses this file -# * to you under the Apache License, Version 2.0 (the -# * "License"); you may not use this file except in compliance -# * with the License. You may obtain a copy of the License at -# * -# * http://www.apache.org/licenses/LICENSE-2.0 -# * -# * Unless required by applicable law or agreed to in writing, software -# * distributed under the License is distributed on an "AS IS" BASIS, -# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# * See the License for the specific language governing permissions and -# * limitations under the License. -# */ - -set -e -set -x - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -source ${DIR}/hbase-client-env.sh - -${DIR}/download-thirdparty.sh -${DIR}/build-thirdparty.sh -cd ${HBASE_DIR} -cmake . -make clean all -make test diff --git a/hbase-native-client/bin/build-thirdparty.sh b/hbase-native-client/bin/build-thirdparty.sh deleted file mode 100755 index 097c1a447564..000000000000 --- a/hbase-native-client/bin/build-thirdparty.sh +++ /dev/null @@ -1,64 +0,0 @@ -#! /usr/bin/env bash -# -#/** -# * Copyright The Apache Software Foundation -# * -# * Licensed to the Apache Software Foundation (ASF) under one -# * or more contributor license agreements. See the NOTICE file -# * distributed with this work for additional information -# * regarding copyright ownership. The ASF licenses this file -# * to you under the Apache License, Version 2.0 (the -# * "License"); you may not use this file except in compliance -# * with the License. You may obtain a copy of the License at -# * -# * http://www.apache.org/licenses/LICENSE-2.0 -# * -# * Unless required by applicable law or agreed to in writing, software -# * distributed under the License is distributed on an "AS IS" BASIS, -# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# * See the License for the specific language governing permissions and -# * limitations under the License. -# */ - -set -x -set -e - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -source ${DIR}/../bin/hbase-client-env.sh - -# On some systems, autotools installs libraries to lib64 rather than lib. Fix -# this by setting up lib64 as a symlink to lib. We have to do this step first -# to handle cases where one third-party library depends on another. -mkdir -p "${HBASE_PREFIX}/lib" -cd ${HBASE_PREFIX} -ln -sf lib "${HBASE_PREFIX}/lib64" - -if [ ! -f gtest ]; then - cd ${HBASE_GTEST_DIR} - cmake . - make -j4 - cd .. - ln -sf ${HBASE_GTEST_DIR} gtest -fi - -if [ ! -f ${HBASE_PREFIX}/lib/libprotobuf.a ]; then - cd ${HBASE_PROTOBUF_DIR} - ./configure --with-pic --disable-shared --prefix=${HBASE_PREFIX} - make -j4 install -fi - -if [ ! -f ${HBASE_PREFIX}/lib/libev.a ]; then - cd ${HBASE_LIBEV_DIR} - ./configure --with-pic --disable-shared --prefix=${HBASE_PREFIX} - make -j4 install -fi - -echo "---------------------" -echo "Thirdparty dependencies built and installed into $HBASE_PREFIX successfully" diff --git a/hbase-native-client/bin/download-thirdparty.sh b/hbase-native-client/bin/download-thirdparty.sh deleted file mode 100755 index db98aae65db8..000000000000 --- a/hbase-native-client/bin/download-thirdparty.sh +++ /dev/null @@ -1,70 +0,0 @@ -#! /usr/bin/env bash -# -#/** -# * Copyright The Apache Software Foundation -# * -# * Licensed to the Apache Software Foundation (ASF) under one -# * or more contributor license agreements. See the NOTICE file -# * distributed with this work for additional information -# * regarding copyright ownership. The ASF licenses this file -# * to you under the Apache License, Version 2.0 (the -# * "License"); you may not use this file except in compliance -# * with the License. You may obtain a copy of the License at -# * -# * http://www.apache.org/licenses/LICENSE-2.0 -# * -# * Unless required by applicable law or agreed to in writing, software -# * distributed under the License is distributed on an "AS IS" BASIS, -# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# * See the License for the specific language governing permissions and -# * limitations under the License. -# */ - -set -x -set -e - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -source ${DIR}/../bin/hbase-client-env.sh - -mkdir -p ${HBASE_TP_DIR} -cd ${HBASE_TP_DIR} - - -if [ ! -d ${HBASE_GTEST_DIR} ]; then - echo "Fetching gtest" - wget -c http://googletest.googlecode.com/files/gtest-${HBASE_GTEST_VERSION}.zip - unzip gtest-${HBASE_GTEST_VERSION}.zip - rm gtest-${HBASE_GTEST_VERSION}.zip -fi - -if [ ! -d ${HBASE_PROTOBUF_DIR} ]; then - echo "Fetching protobuf" - wget -c http://protobuf.googlecode.com/files/protobuf-${HBASE_PROTOBUF_VERSION}.tar.gz - tar xzf protobuf-${HBASE_PROTOBUF_VERSION}.tar.gz - rm protobuf-${HBASE_PROTOBUF_VERSION}.tar.gz -fi - -if [ ! -d $HBASE_LIBEV_DIR ]; then - echo "Fetching libev" - wget -c http://dist.schmorp.de/libev/libev-${HBASE_LIBEV_VERSION}.tar.gz - tar zxf libev-${HBASE_LIBEV_VERSION}.tar.gz - rm -rf libev-${HBASE_LIBEV_VERSION}.tar.gz -fi - -if [ ! -d $HBASE_PREFIX/bin/cpplint.py ]; then - echo "Fetching cpplint" - mkdir -p $HBASE_PREFIX/bin/ - wget -O $HBASE_PREFIX/bin/cpplint.py http://google-styleguide.googlecode.com/svn/trunk/cpplint/cpplint.py - chmod +x $HBASE_PREFIX/bin/cpplint.py -fi - - -echo "---------------" -echo "Thirdparty dependencies downloaded successfully" diff --git a/hbase-native-client/bin/hbase-client-env.sh b/hbase-native-client/bin/hbase-client-env.sh deleted file mode 100644 index 96763da672e9..000000000000 --- a/hbase-native-client/bin/hbase-client-env.sh +++ /dev/null @@ -1,47 +0,0 @@ -#! /usr/bin/env bash -# -#/** -# * Copyright The Apache Software Foundation -# * -# * Licensed to the Apache Software Foundation (ASF) under one -# * or more contributor license agreements. See the NOTICE file -# * distributed with this work for additional information -# * regarding copyright ownership. The ASF licenses this file -# * to you under the Apache License, Version 2.0 (the -# * "License"); you may not use this file except in compliance -# * with the License. You may obtain a copy of the License at -# * -# * http://www.apache.org/licenses/LICENSE-2.0 -# * -# * Unless required by applicable law or agreed to in writing, software -# * distributed under the License is distributed on an "AS IS" BASIS, -# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# * See the License for the specific language governing permissions and -# * limitations under the License. -# */ - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to - # resolve it relative to the path where - # the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" -HBASE_DIR="${DIR}/../" -HBASE_TP_DIR="${HBASE_DIR}/thirdparty/" - -HBASE_PREFIX=$HBASE_TP_DIR/installed - -HBASE_GTEST_VERSION=1.7.0 -HBASE_GTEST_DIR=$HBASE_TP_DIR/gtest-$HBASE_GTEST_VERSION - -HBASE_PROTOBUF_VERSION=2.5.0 -HBASE_PROTOBUF_DIR=$HBASE_TP_DIR/protobuf-$HBASE_PROTOBUF_VERSION - -HBASE_LIBEV_VERSION=4.15 -HBASE_LIBEV_DIR=$HBASE_TP_DIR/libev-$HBASE_LIBEV_VERSION - -# use the compiled tools -export PATH=$HBASE_PREFIX/bin:$PATH diff --git a/hbase-native-client/bin/perftest.sh b/hbase-native-client/bin/perftest.sh new file mode 100755 index 000000000000..cbeb72135776 --- /dev/null +++ b/hbase-native-client/bin/perftest.sh @@ -0,0 +1,86 @@ +# +#/** +# * Copyright The Apache Software Foundation +# * +# * Licensed to the Apache Software Foundation (ASF) under one +# * or more contributor license agreements. See the NOTICE file +# * distributed with this work for additional information +# * regarding copyright ownership. The ASF licenses this file +# * to you under the Apache License, Version 2.0 (the +# * "License"); you may not use this file except in compliance +# * with the License. You may obtain a copy of the License at +# * +# * http://www.apache.org/licenses/LICENSE-2.0 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# */ +function get_canonical_dir() { + target="$1" + + canonical_name=`readlink -f ${target} 2>/dev/null` + if [[ $? -eq 0 ]]; then + canonical_dir=`dirname $canonical_name` + echo ${canonical_dir} + return + fi + + # Mac has no readlink -f + cd `dirname ${target}` + target=`basename ${target}` + # chase down the symlinks + while [ -L ${target} ]; do + target=`readlink ${target}` + cd `dirname ${target}` + target=`basename ${target}` + done + canonical_dir=`pwd -P` + ret=${canonical_dir} + echo $ret +} +bin=$(get_canonical_dir "$0") +LIBHBASE_HOME=`cd "$bin/..">/dev/null; pwd` + +cygwin=false +case "`uname`" in +CYGWIN*) cygwin=true;; +esac + +HBASE_NATIVE_DIR=${LIBHBASE_HOME}/lib/native + +HBASE_LIBRARY_PATH="$HBASE_LIBRARY_PATH:${HBASE_NATIVE_DIR}" +#Add libjvm.so's location +if [ -d "$JAVA_HOME/jre/lib/amd64/server" ]; then + HBASE_LIBRARY_PATH="$HBASE_LIBRARY_PATH:$JAVA_HOME/jre/lib/amd64/server" +fi +if [ -d "$JAVA_HOME/jre/lib/i386/server" ]; then + HBASE_LIBRARY_PATH="$HBASE_LIBRARY_PATH:$JAVA_HOME/jre/lib/i386/server" +fi +LD_LIBRARY_PATH="${HBASE_LIBRARY_PATH#:}" + +HBASE_LIB_DIR=${LIBHBASE_HOME}/lib + +if $cygwin; then + LIBHBASE_HOME=`cygpath -d "$LIBHBASE_HOME"` + LD_LIBRARY_PATH=`cygpath -d "$LD_LIBRARY_PATH"` + HBASE_NATIVE_DIR=`cygpath -d "$HBASE_NATIVE_DIR"` +fi + +#This is passed to JVM by libhbase +LIBHBASE_OPTS="${LIBHBASE_OPTS} -Dlibhbase.log.dir=${LIBHBASE_HOME}/logs -Dlibhbase.log.name=perftest-java.log -Dlibhbase.log.level=info -Dlibhbase.logger=RFA" +LIBHBASE_OPTS="${LIBHBASE_OPTS} -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/ -XX:+UseConcMarkSweepGC -XX:+UseParNewGC" + +export LIBHBASE_OPTS=${LIBHBASE_OPTS} +export HBASE_LIB_DIR=${HBASE_LIB_DIR} +export HBASE_CONF_DIR=${LIBHBASE_HOME}/conf +export LD_LIBRARY_PATH=${LD_LIBRARY_PATH} + +if [ $# -ne 0 ]; then + mkdir -p ${LIBHBASE_HOME}/logs + LOGFILE_OPTION="-logFilePath ${LIBHBASE_HOME}/logs/perftest.log" +fi + +exec ${HBASE_NATIVE_DIR}/perftest ${LOGFILE_OPTION} $* diff --git a/hbase-native-client/build.gradle b/hbase-native-client/build.gradle new file mode 100644 index 000000000000..90e1fc8c4b59 --- /dev/null +++ b/hbase-native-client/build.gradle @@ -0,0 +1,263 @@ +/** + * Copyright The Apache Software Foundation + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +import org.gradle.internal.os.OperatingSystem + +apply plugin: 'c' +apply plugin: 'cpp' + +defaultTasks "hbase", "perftest", "example_async", "unittests" + +ext { + currentJvm = org.gradle.internal.jvm.Jvm.current() + javaHome = currentJvm.getJavaHome().getAbsolutePath() + javaHomeInclude = javaHome + '/include' + + String osName = System.properties['os.name'].toLowerCase() + if (osName.contains('linux')) { + javaHomeIncludeOs = javaHomeInclude + '/linux' + libjvmLibraryString = javaHome + "/jre/lib/amd64/server/libjvm.so" + libGTestName = "/libgtest.so" + } + else if (osName.contains('windows')) { + javaHomeIncludeOs = javaHomeInclude + '/win32' + libjvmLibraryString = javaHome + "/lib/jvm.lib" + libGTestName = "/cyggtest.dll" + } + else if (osName.contains('mac os x')) { + // TODO - deal with different versions of OSX, + // because Apple has done heavy modification to the JVM and JDK every version + javaHomeInclude = "/System/Library/Frameworks/JavaVM.framework/Versions/A/Headers" + javaHomeIncludeOs = "/System/Library/Frameworks/JavaVM.framework/Versions/A/Headers" + libjvmLibraryString = "/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Libraries/libserver.dylib" + libGTestName = "/libgtest.dylib" + } + + // this should be set to the directory of JNI generated headers + if (!project.hasProperty('jniIncludeDir')) { + jniIncludeDir = "src/main/native/generated" + } + if (!project.hasProperty('googleTestDir')) { + googleTestDir = "target/gtest-1.7.0" + } +} + +def stdout = new ByteArrayOutputStream() +try { + exec { + commandLine( + "ls", libjvmLibraryString + ) + errorOutput = stdout + standardOutput = stdout + ignoreExitValue = false + logger.info("Using ${libjvmLibraryString} and include directories ${javaHomeInclude} and ${javaHomeIncludeOs}") + } +} catch(e){ + logger.error(stdout.toString()) + throw new GradleException("The file ${libjvmLibraryString} was not found") +} + +model { + toolChains { + // currently only GCC is supported + gcc(Gcc) { + } + } + + buildTypes { + release + } + + repositories { + libs(PrebuiltLibraries) { + jvm { + binaries.withType(SharedLibraryBinary) { + sharedLibraryFile = file(libjvmLibraryString) + } + } + + gtest { + binaries.withType(SharedLibraryBinary) { + sharedLibraryFile = file(googleTestDir + libGTestName) + } + } + } + } +} + +/** + * Verify that JAVA_HOME is set + */ +dependencies { + if (!javaHome) { + logger.error('JAVA_HOME is not set.') + throw new GradleException("JAVA_HOME is not set.") + } + println 'Found JAVA_HOME: ' + javaHome +} + +/** + * Register the source files for goals + */ +sources { + /* libHBase sources */ + hbase { + cpp { + source { + srcDirs "src/main/native/jni_impl", "src/main/native/common" + include "**/*.cc" + } + exportedHeaders { + srcDirs "src/main/native/include", "src/main/native/common", jniIncludeDir, + javaHomeInclude, javaHomeIncludeOs + } + } + } + + /* perftest sources */ + perftest { + cpp { + source { + srcDirs "src/test/native/perftest", "src/test/native/common" + include "**/*.cc" + } + exportedHeaders { + srcDirs "src/test/native/common" + } + } + } + /* unittests sources */ + unittests { + cpp { + source { + srcDirs "src/test/native/unittests", "src/test/native/common" + include "**/*.cc" + } + exportedHeaders { + srcDirs "src/test/native/common", googleTestDir + "/include" + } + } + } + + /* example_async sources */ + example_async { + cpp { + source { + srcDirs "src/test/native/common" + include "byte_buffer.cc" + } + exportedHeaders { + srcDirs "src/test/native/common" + } + } + c { + source { + srcDirs "src/examples/async" + include "example_async.c" + } + exportedHeaders { + srcDirs "src/test/native/common" + } + } + } +} + +/** + * Compiler flags for all targets + */ +binaries.all { + if (toolChain in Gcc) { + cCompiler.args "-Wall", "-Werror", "-fvisibility=hidden", "-std=gnu99" + cppCompiler.args "-Wall", "-Werror", "-fvisibility=hidden", "-fvisibility-inlines-hidden" + + lib library: 'jvm', linkage: 'shared' + if (OperatingSystem.current().windows) { + // Without this, the linker decorate the JNIEXPORTs and then JNI can not find them + linker.args "-Wl,--kill-at" + } + } + // TODO: set flags for other compilers +} + +/* + * libHBase Shared Library + */ +libraries { + hbase { + binaries.withType(SharedLibraryBinary) { + cppCompiler.define "__STDC_FORMAT_MACROS" // for PRIu64 macro + cppCompiler.define "_LIBHBASE_IMPLEMENTATION_" + cppCompiler.define "THREADED" + + cCompiler.define "_LIBHBASE_IMPLEMENTATION_" + cCompiler.define "THREADED" + } + } +} + +/* + * example_async executable + */ +executables { + perftest { + binaries.all { + cppCompiler.define "__STDC_FORMAT_MACROS" // for PRIu64 macro + + lib library: 'hbase', linkage: 'shared' + } + } + + example_async { + binaries.all { + lib library: 'hbase', linkage: 'shared' + } + } + + unittests { + binaries.all { + cppCompiler.args "-std=gnu++0x" + lib library: 'hbase', linkage: 'shared' + lib library: 'gtest', linkage: 'shared' + } + } +} + +/* + * Build tasks + */ +task wrapper(type: Wrapper) { + description 'A wrapper which downloads and/or uses Gradle' + gradleVersion = '1.12' +} + +task 'hbase' (dependsOn: 'hbaseSharedLibrary') { + description 'Builds HBase shared library.' +} + +task 'perftest' (dependsOn: 'perftestExecutable') { + description 'Builds perftest executable.' +} + +task 'example_async' (dependsOn: 'example_asyncExecutable') { + description 'Builds async example executable.' +} + +task 'unittests' (dependsOn: 'unittestsExecutable') { + description 'Builds unittests executable.' +} diff --git a/hbase-native-client/cmake_modules/FindGTest.cmake b/hbase-native-client/cmake_modules/FindGTest.cmake deleted file mode 100644 index 1da689214629..000000000000 --- a/hbase-native-client/cmake_modules/FindGTest.cmake +++ /dev/null @@ -1,49 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -set( GTEST_INCLUDE_SEARCH - ${CMAKE_SOURCE_DIR}/thirdparty/gtest/include -) - -set( GTEST_LIB_SEARCH - ${CMAKE_SOURCE_DIR}/thirdparty/gtest -) - -find_path(GTEST_INCLUDE - NAMES gtest/gtest.h - PATHS ${GTEST_INCLUDE_SEARCH} - NO_DEFAULT_PATH -) - -find_library(GTEST_LIBRARY - NAMES gtest - PATHS ${GTEST_LIB_SEARCH} - NO_DEFAULT_PATH -) - -find_library(GTEST_LIBRARY_MAIN - NAMES gtest_main - PATHS ${GTEST_LIB_SEARCH} - NO_DEFAULT_PATH -) - -if (GTEST_INCLUDE AND GTEST_LIBRARY AND GTEST_LIBRARY_MAIN) - set(GTEST_LIBS ${GTEST_LIBRARY} ${GTEST_LIBRARY_MAIN}) - set(GTEST_INCLUDE_DIR ${GTEST_INCLUDE}) - set(GTEST_FOUND TRUE) -endif() - -mark_as_advanced( - GTEST_INCLUDE_DIR - GTEST_LIBS -) diff --git a/hbase-native-client/cmake_modules/FindLibEv.cmake b/hbase-native-client/cmake_modules/FindLibEv.cmake deleted file mode 100644 index 9a40c17f0b17..000000000000 --- a/hbase-native-client/cmake_modules/FindLibEv.cmake +++ /dev/null @@ -1,43 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -set( LIBEV_INCLUDE_SEARCH - ${CMAKE_SOURCE_DIR}/thirdparty/installed/include -) - -set( LIBEV_LIB_SEARCH - ${CMAKE_SOURCE_DIR}/thirdparty/installed/include -) - -find_path(LIBEV_INCLUDE - NAMES ev++.h - PATHS ${LIBEV_INCLUDE_SEARCH} - NO_DEFAULT_PATH -) - -find_library(LIBEV_LIBRARY - NAMES ev - PATHS ${LIBEV_LIB_SEARCH} - NO_DEFAULT_PATH -) - -if (LIBEV_INCLUDE_PATH AND LIBEV_LIBRARY) - set(LIBEV_LIBS ${LIBEV_LIBRARY}) - set(LIBEV_INCLUDE_DIR ${LIBEV_INCLUDE}) - set(LIBEV_FOUND TRUE) -endif() - -mark_as_advanced( - LIBEV_INCLUDE_DIR - LIBEV_LIBS -) diff --git a/hbase-native-client/gradle/wrapper/gradle-wrapper.jar b/hbase-native-client/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 000000000000..0087cd3b1865 Binary files /dev/null and b/hbase-native-client/gradle/wrapper/gradle-wrapper.jar differ diff --git a/hbase-native-client/gradle/wrapper/gradle-wrapper.properties b/hbase-native-client/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000000..ec66b868af29 --- /dev/null +++ b/hbase-native-client/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,21 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#Wed Jun 25 02:52:17 PDT 2014 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-1.12-bin.zip diff --git a/hbase-native-client/gradlew b/hbase-native-client/gradlew new file mode 100644 index 000000000000..949cf4f0216a --- /dev/null +++ b/hbase-native-client/gradlew @@ -0,0 +1,184 @@ +#!/usr/bin/env bash +# +#/** +# * Copyright 2007 The Apache Software Foundation +# * +# * Licensed to the Apache Software Foundation (ASF) under one +# * or more contributor license agreements. See the NOTICE file +# * distributed with this work for additional information +# * regarding copyright ownership. The ASF licenses this file +# * to you under the Apache License, Version 2.0 (the +# * "License"); you may not use this file except in compliance +# * with the License. You may obtain a copy of the License at +# * +# * http://www.apache.org/licenses/LICENSE-2.0 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# */ +# +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/hbase-native-client/gradlew.bat b/hbase-native-client/gradlew.bat new file mode 100644 index 000000000000..37248fe5d520 --- /dev/null +++ b/hbase-native-client/gradlew.bat @@ -0,0 +1,108 @@ +@if "%DEBUG%" == "" @echo off +@rem/* +@rem * Licensed to the Apache Software Foundation (ASF) under one +@rem * or more contributor license agreements. See the NOTICE file +@rem * distributed with this work for additional information +@rem * regarding copyright ownership. The ASF licenses this file +@rem * to you under the Apache License, Version 2.0 (the +@rem * "License"); you may not use this file except in compliance +@rem * with the License. You may obtain a copy of the License at +@rem * +@rem * http://www.apache.org/licenses/LICENSE-2.0 +@rem * +@rem * Unless required by applicable law or agreed to in writing, software +@rem * distributed under the License is distributed on an "AS IS" BASIS, +@rem * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem * See the License for the specific language governing permissions and +@rem * limitations under the License. +@rem */ +@rem +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/hbase-native-client/pom.xml b/hbase-native-client/pom.xml new file mode 100644 index 000000000000..afc04f290a6f --- /dev/null +++ b/hbase-native-client/pom.xml @@ -0,0 +1,593 @@ + + + + 4.0.0 + + org.apache.hbase + hbase + 2.0.0-SNAPSHOT + .. + + + hbase-native-client + HBase - Native Library + + + + + mapr public + MapR Public Maven Repository + http://repository.mapr.com/maven/ + + true + + + true + + + + + + UTF-8 + 1.7.0 + 2d6ec8ccdf5c46b05ba54a9fd1d130d7 + + + + + + org.apache.maven.plugins + maven-site-plugin + + true + + + + com.googlecode.maven-download-plugin + maven-download-plugin + 1.1.0 + + + download-gtest + process-test-resources + + wget + + false + + ${maven.test.skip} + http://googletest.googlecode.com/files/gtest-${gtest.version}.zip + true + ${project.build.directory} + ${gtest.md5} + + + + + + maven-surefire-plugin + + + + default-test + none + + + secondPartTestsExecution + none + + + + + org.codehaus.mojo + native-maven-plugin + 1.0-alpha-7 + true + + + generate-jni-headers + compile + + javah + + + + org.apache.hadoop.hbase.jni.CallbackHandlers + + ${project.build.directory}/native/javah + + + + + + + maven-assembly-plugin + + gnu + false + false + + src/assembly/all.xml + + + + + build-tarball + package + + single + + + + + + + maven-antrun-plugin + + + build-libhbase-binaries + compile + + run + + false + + + + + + + + + + + + + + + + build-libhbase-tests + test-compile + + run + + false + + ${maven.test.skip} + + + + + + + + + + + + + + + + + + + + + + run-libhbase-unittests + integration-test + + run + + false + + ${maven.test.skip} + + + + + + + + + + + + + + + + + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + org.codehaus.mojo + native-maven-plugin + [1.0-alpha-7,) + + javah + + + + + + + + + + com.googlecode.maven-download-plugin + + maven-download-plugin + [1.1.0,) + + wget + + + + + + + + + + + + + + + + + org.apache.hbase + hbase-client + + + jsp-api-2.1 + org.mortbay.jetty + + + commons-el + commons-el + + + commons-httpclient + commons-httpclient + + + commons-cli + commons-cli + + + jsp-2.1 + org.mortbay.jetty + + + jetty-util + org.mortbay.jetty + + + jasper-runtime + tomcat + + + core + org.eclipse.jdt + + + jasper-compiler + tomcat + + + jetty + org.mortbay.jetty + + + com.yammer.metrics + metrics-core + + + com.github.stephenc.high-scale-lib + high-scale-lib + + + commons-io + commons-io + + + commons-beanutils + commons-beanutils-core + + + log4j + log4j + + + org.apache.avro + avro + + + org.apache.avro + avro-ipc + + + org.apache.thrift + libthrift + + + org.jruby + jruby-complete + + + org.mortbay.jetty + servlet-api-2.5 + + + org.codehaus.jackson + jackson-jaxrs + + + org.codehaus.jackson + jackson-xc + + + org.jamon + jamon-runtime + + + com.google.protobuf + protobuf-java + + + com.sun.jersey + jersey-core + + + com.sun.jersey + jersey-json + + + com.sun.jersey + jersey-server + + + hadoop-mapreduce-client-core + org.apache.hadoop + + + findbugs-annotations + com.github.stephenc.findbugs + + + + + org.slf4j + slf4j-log4j12 + 1.7.5 + + + org.slf4j + slf4j-api + + + org.hbase + asynchbase + 1.5.0-libhbase-SNAPSHOT + + + log4j-over-slf4j + org.slf4j + + + guava + com.google.guava + + + + + org.apache.zookeeper + zookeeper + + + log4j + log4j + + + slf4j-log4j12 + org.slf4j + + + jline + jline + + + netty + org.jboss.netty + + + + + + + + + + hadoop-1.1 + + + + hadoop.profile1.1 + + + + + org.apache.hadoop + hadoop-core + + + + + + + hadoop-2.0 + + + + !hadoop.profile + + + + + org.apache.hadoop + hadoop-common + + + javax.servlet.jsp + jsp-api + + + com.sun.jersey + jersey-server + + + javax.servlet + servlet-api + + + tomcat + jasper-compiler + + + tomcat + jasper-runtime + + + jersey-json + com.sun.jersey + + + jersey-core + com.sun.jersey + + + avro + org.apache.avro + + + jetty + org.mortbay.jetty + + + jetty-util + org.mortbay.jetty + + + commons-math3 + org.apache.commons + + + commons-compress + org.apache.commons + + + commons-cli + commons-cli + + + jets3t + net.java.dev.jets3t + + + commons-httpclient + commons-httpclient + + + commons-el + commons-el + + + commons-digester + commons-digester + + + commons-io + commons-io + + + + + org.apache.hadoop + hadoop-auth + + + httpclient + org.apache.httpcomponents + + + + + + + + + hadoop-3.0 + + + hadoop.profile + 3.0 + + + + 3.0-SNAPSHOT + + + + org.apache.hadoop + hadoop-common + + + + + + diff --git a/hbase-native-client/src/assembly/all.xml b/hbase-native-client/src/assembly/all.xml new file mode 100644 index 000000000000..546a3c48741d --- /dev/null +++ b/hbase-native-client/src/assembly/all.xml @@ -0,0 +1,91 @@ + + + bin + + + dir + tar.gz + + ${project.build.directory} + false + + + + ${basedir}/*.txt + + + + bin + 0755 + 0755 + + + ${project.build.directory}/gradle/binaries/hbaseSharedLibrary + 0755 + 0755 + lib/native + + + ${project.build.directory}/gradle/binaries/perftestExecutable + 0755 + 0755 + lib/native + + + src/main/resources + 0644 + 0755 + conf + + + src/main/native/include + 0644 + 0755 + include + + + src/examples + 0644 + 0755 + + + src/test/native/common + 0644 + 0755 + + + + + /lib + false + runtime + 0644 + 0644 + + junit:junit + org.hamcrest:hamcrest-core + com.github.stephenc.findbugs:findbugs-annotations + + + + diff --git a/hbase-native-client/src/async/CMakeLists.txt b/hbase-native-client/src/async/CMakeLists.txt deleted file mode 100644 index c11537cd5ec4..000000000000 --- a/hbase-native-client/src/async/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -set( ASYNC_SRC - hbase_admin.cc - hbase_client.cc - hbase_connection.cc - hbase_get.cc - hbase_mutations.cc - hbase_result.cc - hbase_scanner.cc -) - - -add_library(hasync OBJECT ${ASYNC_SRC}) - -ADD_HBASE_ASYNC_TEST(mutations-test) -ADD_HBASE_ASYNC_TEST(get-test) diff --git a/hbase-native-client/src/async/get-test.cc b/hbase-native-client/src/async/get-test.cc deleted file mode 100644 index df94ce22ffe0..000000000000 --- a/hbase-native-client/src/async/get-test.cc +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include "gtest/gtest.h" -#include "async/hbase_get.h" -#include "async/hbase_client.h" - - -pthread_cond_t cv; -pthread_mutex_t mutex; - -TEST(GetTest, TestPut) { - char tn[] = "T1"; - hb_byte_t row[] = "ROW"; - - hb_client_t client = NULL; - hb_get_t get = NULL; - int32_t s1 = -1; - - pthread_cond_init(&cv, NULL); - pthread_mutex_init(&mutex, NULL); - - s1 = hb_client_create(&client, NULL); - EXPECT_EQ(0, s1); - - s1 = hb_get_create(&get); - EXPECT_EQ(0, s1); - - hb_get_set_table(get, tn, 2); - hb_get_set_row(get, row, 3); - - /* - * TODO: - * This is currently a NO-OP as there is no CB. - */ - hb_get_send(client, get, NULL, NULL); - - hb_client_destroy(client, NULL, NULL); - - EXPECT_EQ(0, s1); -} diff --git a/hbase-native-client/src/async/hbase_admin.cc b/hbase-native-client/src/async/hbase_admin.cc deleted file mode 100644 index 17ff2a72b49c..000000000000 --- a/hbase-native-client/src/async/hbase_admin.cc +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "async/hbase_admin.h" - -#include -#include - -#include "core/admin.h" -#include "async/hbase_connection.h" - -int32_t hb_admin_create(hb_admin_t* admin_ptr, - hb_connection_t connection) { - (*admin_ptr) = reinterpret_cast(new Admin()); - return 0; -} - -/* - * Disconnect the admin releasing any internal objects - * or connections created in the background. - */ -int32_t hb_admin_destroy(hb_admin_t admin, - hb_admin_disconnection_cb cb, void * extra) { - if (cb) - cb(0, admin, extra); - free(admin); - return 0; -} - -/* - * See if a table exists. - */ -int32_t hb_admin_table_exists(hb_admin_t admin, - char * name_space, size_t name_space_length, - char * table, size_t table_length, - hb_admin_table_exists_cb cb, void * extra) { - if (cb) - cb(0, admin, name_space, name_space_length, - table, table_length, true, extra); - return 0; -} diff --git a/hbase-native-client/src/async/hbase_admin.h b/hbase-native-client/src/async/hbase_admin.h deleted file mode 100644 index f03a83f79f9b..000000000000 --- a/hbase-native-client/src/async/hbase_admin.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ASYNC_HBASE_ADMIN_H_ -#define ASYNC_HBASE_ADMIN_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include "core/hbase_macros.h" -#include "async/hbase_connection.h" - - -typedef void (* hb_admin_disconnection_cb)( int32_t status, - hb_admin_t admin, void * extra); -typedef void (* hb_admin_table_exists_cb)(int32_t status, hb_admin_t admin, - char * name_space, size_t name_space_length, - char * table, size_t table_length, bool exsists, void * extra); - -/** - * Create a new hb_admin. - * All fields are initialized to the defaults. If you want to set - * connection or other properties, set those before calling any - * RPC functions. - */ -HBASE_API int32_t hb_admin_create(hb_admin_t* admin_ptr, - hb_connection_t connection); - -/* - * Disconnect the admin releasing any internal objects - * or connections created in the background. - */ -HBASE_API int32_t hb_admin_destroy(hb_admin_t admin, - hb_admin_disconnection_cb cb, void * extra); - -/* - * See if a table exists. - */ -HBASE_API int32_t hb_admin_table_exists(hb_admin_t admin, - char * name_space, size_t name_space_length, - char * table, size_t table_length, - hb_admin_table_exists_cb cb, void * extra); - - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif // ASYNC_HBASE_ADMIN_H_ diff --git a/hbase-native-client/src/async/hbase_client.h b/hbase-native-client/src/async/hbase_client.h deleted file mode 100644 index 34c3d98bfb7b..000000000000 --- a/hbase-native-client/src/async/hbase_client.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ASYNC_HBASE_CLIENT_H_ -#define ASYNC_HBASE_CLIENT_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "core/hbase_macros.h" -#include "core/hbase_types.h" - -/* - * Client disconnection callback typedef - * - * This is called after the connections are closed, but just - * before the client is freed. - */ -typedef void (* hb_client_disconnection_cb)( int32_t status, - hb_client_t client, void * extra); - -/** - * Create an hb_client_t. - * - * If connection is null then all defaults will be used. - */ -HBASE_API int32_t hb_client_create(hb_client_t * client_ptr, - hb_connection_t connection); - -/* - * Disconnect the client releasing any internal objects - * or connections created in the background. - */ -HBASE_API int32_t hb_client_destroy(hb_client_t client, - hb_client_disconnection_cb cb, void * extra); - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif // ASYNC_HBASE_CLIENT_H_ - - diff --git a/hbase-native-client/src/async/hbase_connection.h b/hbase-native-client/src/async/hbase_connection.h deleted file mode 100644 index 343f36cf41fa..000000000000 --- a/hbase-native-client/src/async/hbase_connection.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ASYNC_HBASE_CONNECTION_H_ -#define ASYNC_HBASE_CONNECTION_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "core/hbase_macros.h" -#include "core/hbase_types.h" -#include "core/hbase_connection_attr.h" - -#include - -/** - * Create an hb_connection. - * - * if connection_attr is null everything will be left as default - */ -HBASE_API int32_t hb_connection_create(hb_connection_t * connection_ptr, - hb_connection_attr_t connection_attr); - -/** - * Destroy the connection and free all resources allocated at creation - * time. - */ -HBASE_API int32_t hb_connection_destroy(hb_connection_t connection); - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif // ASYNC_HBASE_CONNECTION_H_ - diff --git a/hbase-native-client/src/async/hbase_errno.h b/hbase-native-client/src/async/hbase_errno.h deleted file mode 100644 index 1698bbdbb634..000000000000 --- a/hbase-native-client/src/async/hbase_errno.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ASYNC_HBASE_ERRNO_H_ -#define ASYNC_HBASE_ERRNO_H_ - -#endif // ASYNC_HBASE_ERRNO_H_ diff --git a/hbase-native-client/src/async/hbase_get.cc b/hbase-native-client/src/async/hbase_get.cc deleted file mode 100644 index 32048d81fe64..000000000000 --- a/hbase-native-client/src/async/hbase_get.cc +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "async/hbase_get.h" - -#include -#include - -#include "core/get.h" - -int32_t hb_get_create(hb_get_t * get_ptr) { - (*get_ptr) = reinterpret_cast(new Get()); - if ((*get_ptr) == NULL) { - return -1; - } - return 0; -} - -int32_t hb_get_destroy(hb_get_t get) { - free(get); - return 0; -} - -int32_t hb_get_set_row(hb_get_t get, unsigned char * row, - size_t row_length) { - return 0; -} - -int32_t hb_get_set_table(hb_get_t get, - char * table, size_t table_length) { - return 0; -} - -int32_t hb_get_set_namespace(hb_get_t get, - char * name_space, size_t name_space_length) { - return 0; -} - -int32_t hb_get_send(hb_client_t client, - hb_get_t get, hb_get_cb cb, void * extra) { - if (cb) { - cb(0, client, get, NULL, extra); - } - return 0; -} diff --git a/hbase-native-client/src/async/hbase_get.h b/hbase-native-client/src/async/hbase_get.h deleted file mode 100644 index 7d91c08ae7e0..000000000000 --- a/hbase-native-client/src/async/hbase_get.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ASYNC_HBASE_GET_H_ -#define ASYNC_HBASE_GET_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "core/hbase_macros.h" -#include "core/hbase_types.h" - -/** - * Allocate a new get structure. - * Ownership passes to the caller. - */ -HBASE_API int32_t hb_get_create(hb_get_t * get_ptr); - -/** - * Destroy and free a get structure. - */ -HBASE_API int32_t hb_get_destroy(hb_get_t get); - -/** - * set the row of this get. - */ -HBASE_API int32_t hb_get_set_row(hb_get_t get, hb_byte_t * row, - size_t row_length); - -/** - * Set the table. - */ -HBASE_API int32_t hb_get_set_table(hb_get_t get, - char * table, size_t table_length); - -/** - * Set the namespace this get is targeting. - */ -HBASE_API int32_t hb_get_set_namespace(hb_get_t get, - char * name_space, size_t name_space_length); - -/* - * get call back typedef. - */ -typedef void (* hb_get_cb)(int32_t status, hb_client_t client, - hb_get_t get, hb_result_t results, void * extra); - -HBASE_API int32_t hb_get_send(hb_client_t client, - hb_get_t get, hb_get_cb cb, void * extra); - - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif // ASYNC_HBASE_GET_H_ diff --git a/hbase-native-client/src/async/hbase_mutations.cc b/hbase-native-client/src/async/hbase_mutations.cc deleted file mode 100644 index 2456dc0074cb..000000000000 --- a/hbase-native-client/src/async/hbase_mutations.cc +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "async/hbase_mutations.h" - -#include - -#include "core/hbase_types.h" -#include "core/mutation.h" -#include "core/put.h" -#include "core/delete.h" - -#include "async/hbase_result.h" - -extern "C" { -int32_t hb_put_create(hb_put_t* put_ptr) { - (*put_ptr) = reinterpret_cast(new Put()); - return 0; -} - -int32_t hb_delete_create(hb_delete_t * delete_ptr) { - (*delete_ptr) = reinterpret_cast(new Delete()); - return 0; -} - -int32_t hb_increment_create(hb_increment_t * increment_ptr) { - return 0; -} - -int32_t hb_append_create(hb_append_t * append_ptr) { - return 0; -} - -int32_t hb_mutation_destroy(hb_mutation_t mutation) { - return 0; -} - -HBASE_API int32_t hb_mutation_set_namespace(hb_mutation_t mutation, - char * name_space, size_t name_space_length) { - Mutation * m = reinterpret_cast(mutation); - m->set_namespace(name_space, name_space_length); - return 0; -} - -HBASE_API int32_t hb_mutation_set_table(hb_mutation_t mutation, - char * table, size_t table_length) { - Mutation * m = reinterpret_cast(mutation); - m->set_namespace(table, table_length); - return 0; -} - -int32_t hb_mutation_set_row(hb_mutation_t mutation, - unsigned char * rk, size_t row_length) { - Mutation * m = reinterpret_cast(mutation); - m->set_row(rk, row_length); - return 0; -} - -int32_t hb_mutation_set_durability(hb_mutation_t mutation, - hb_durability_type durability) { - Mutation * m = reinterpret_cast(mutation); - m->set_durability(durability); - return 0; -} - -int32_t hb_put_add_cell(hb_put_t put, hb_cell_t * cell) { - return 0; -} - -int32_t hb_delete_add_col(hb_increment_t incr, - unsigned char * family, size_t family_length, - unsigned char * qual, size_t qual_length) { - return 0; -} - -int32_t hb_increment_add_value(hb_increment_t incr, - unsigned char * family, size_t family_length, - unsigned char * qual, size_t qual_length, - int64_t ammount) { - return 0; -} - -int32_t hb_append_add_cell(hb_append_t put, hb_cell_t * cell) { - return 0; -} - -int32_t hb_mutation_send(hb_client_t client, - hb_mutation_t mutation, hb_mutation_cb cb, - void * extra) { - if (cb) { - cb(0, client, mutation, NULL, extra); - } - return 0; -} -} // extern "C" diff --git a/hbase-native-client/src/async/hbase_mutations.h b/hbase-native-client/src/async/hbase_mutations.h deleted file mode 100644 index 4000390836fa..000000000000 --- a/hbase-native-client/src/async/hbase_mutations.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ASYNC_HBASE_MUTATIONS_H_ -#define ASYNC_HBASE_MUTATIONS_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "core/hbase_types.h" -#include "async/hbase_result.h" - -// Creation methods - -/** - * Create a put. - * Ownership passes to the caller. - */ -HBASE_API int32_t hb_put_create(hb_put_t * put_ptr); - -/** - * Create a delete - * Ownership passes to the caller. - */ -HBASE_API int32_t hb_delete_create(hb_delete_t * delete_ptr); - -/** - * Create an increment - * Ownership passes to the caller. - */ -HBASE_API int32_t hb_increment_create(hb_increment_t * increment_ptr); - -/** - * Create an append - * Ownership passes to the caller. - */ -HBASE_API int32_t hb_append_create(hb_append_t * append_ptr); - -/** - * Destroy the mutation. - * All internal structures are cleaned up. However any backing - * data structures passed in by the user are not cleaned up. - */ -HBASE_API int32_t hb_mutation_destroy(hb_mutation_t mutation); - -// Shared setters. -HBASE_API int32_t hb_mutation_set_namespace(hb_mutation_t mutation, - char * name_space, size_t name_space_length); -HBASE_API int32_t hb_mutation_set_table(hb_mutation_t mutation, - char * table, size_t table_length); -HBASE_API int32_t hb_mutation_set_row(hb_mutation_t mutation, - unsigned char * rk, size_t row_length); -HBASE_API int32_t hb_mutation_set_durability(hb_mutation_t mutation, - hb_durability_type durability); - -// Put Setters etc. -HBASE_API int32_t hb_put_add_cell(hb_put_t put, hb_cell_t * cell); - -// Delete -HBASE_API int32_t hb_delete_add_col(hb_increment_t incr, - unsigned char * family, size_t family_length, - unsigned char * qual, size_t qual_length); - -// Increment -HBASE_API int32_t hb_increment_add_value(hb_increment_t incr, - unsigned char * family, size_t family_length, - unsigned char * qual, size_t qual_length, - int64_t ammount); - -// Append -HBASE_API int32_t hb_append_add_cell(hb_append_t put, hb_cell_t * cell); - -// Now that the mutations are created and populated -// The real meat of the client is below. - -/* - * mutation call back typedef - */ -typedef void (* hb_mutation_cb)(int32_t status, - hb_client_t client, hb_mutation_t mutation, - hb_result_t result, void * extra); - -/* - * Queue a single mutation. This mutation will be - * sent out in the background and can be batched with - * other requests destined for the same server. - * - * The call back will be executed after the response - * is received from the RegionServer. Even if the - * mutation was batched with other requests, - * the call back will be invoked for every mutation - * individually. - */ -HBASE_API int32_t hb_mutation_send(hb_client_t client, - hb_mutation_t mutation, hb_mutation_cb cb, - void * extra); - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif // ASYNC_HBASE_MUTATIONS_H_ diff --git a/hbase-native-client/src/async/hbase_result.cc b/hbase-native-client/src/async/hbase_result.cc deleted file mode 100644 index 9351270d4b32..000000000000 --- a/hbase-native-client/src/async/hbase_result.cc +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "async/hbase_result.h" - -#include "core/hbase_types.h" - -int32_t hb_result_get_cells(hb_result_t result, - hb_cell_t ** cell_ptr, size_t * num_cells) { - return 0; -} - -int32_t hb_result_get_table(hb_result_t result, - char ** table, size_t * table_length) { - return 0; -} - -int32_t hb_result_get_namespace(hb_result_t result, - char ** name_space, size_t * name_space_length) { - return 0; -} diff --git a/hbase-native-client/src/async/hbase_result.h b/hbase-native-client/src/async/hbase_result.h deleted file mode 100644 index eecbbb37519a..000000000000 --- a/hbase-native-client/src/async/hbase_result.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ASYNC_HBASE_RESULT_H_ -#define ASYNC_HBASE_RESULT_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "core/hbase_macros.h" -#include "core/hbase_types.h" - -HBASE_API int32_t hb_result_destroy(hb_result_t result); - -HBASE_API int32_t hb_result_get_cells(hb_result_t result, - hb_cell_t ** cell_ptr, size_t * num_cells); - -HBASE_API int32_t hb_result_get_table(hb_result_t result, - char ** table, size_t * table_length); -HBASE_API int32_t hb_result_get_namespace(hb_result_t result, - char ** name_space, size_t * name_space_length); - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif // ASYNC_HBASE_RESULT_H_ diff --git a/hbase-native-client/src/async/hbase_scanner.cc b/hbase-native-client/src/async/hbase_scanner.cc deleted file mode 100644 index 5a8e5557f77f..000000000000 --- a/hbase-native-client/src/async/hbase_scanner.cc +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include "async/hbase_scanner.h" - -#include - -#include "core/hbase_types.h" -#include "core/scanner.h" - -int32_t hb_scanner_create(hb_scanner_t * scanner_ptr) { - (*scanner_ptr) = reinterpret_cast(new Scanner()); - return (*scanner_ptr != NULL)?0:1; -} - -HBASE_API int32_t hb_scanner_set_table(hb_scanner_t scanner, - char * table, size_t table_length) { - return 0; -} - -HBASE_API int32_t hb_scanner_set_namespace(hb_scanner_t scanner, - char * name_space, size_t name_space_length) { - return 0; -} - -int32_t hb_scanner_set_start_row(hb_scanner_t scanner, - unsigned char * start_row, size_t start_row_length) { - return 0; -} - -int32_t hb_scanner_set_end_row(hb_scanner_t scanner, - unsigned char * end_row, size_t end_row_length) { - return 0; -} - -int32_t hb_scanner_set_cache_size(hb_scanner_t scanner, - size_t cache_size) { - return 0; -} - -int32_t hb_scanner_set_num_versions(hb_scanner_t scanner, - int8_t num_versions) { - return 0; -} diff --git a/hbase-native-client/src/async/hbase_scanner.h b/hbase-native-client/src/async/hbase_scanner.h deleted file mode 100644 index cd3f54451770..000000000000 --- a/hbase-native-client/src/async/hbase_scanner.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef ASYNC_HBASE_SCANNER_H_ -#define ASYNC_HBASE_SCANNER_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "async/hbase_result.h" -#include "core/hbase_types.h" - -HBASE_API int32_t hb_scanner_create(hb_scanner_t * scanner_ptr); - -HBASE_API int32_t hb_scanner_set_table(hb_scanner_t scanner, - char * table, size_t table_length); -HBASE_API int32_t hb_scanner_set_namespace(hb_scanner_t scanner, - char * name_space, size_t name_space_length); - -HBASE_API int32_t hb_scanner_set_start_row(hb_scanner_t scanner, - unsigned char * start_row, size_t start_row_length); -HBASE_API int32_t hb_scanner_set_end_row(hb_scanner_t scanner, - unsigned char * end_row, size_t end_row_length); - -HBASE_API int32_t hb_scanner_set_cache_size(hb_scanner_t scanner, - size_t cache_size); -HBASE_API int32_t hb_scanner_set_batch_size(hb_scanner_t scanner, - size_t batch_size); -HBASE_API int32_t hb_scanner_set_num_versions(hb_scanner_t scanner, - int8_t num_versions); - -/* - * Scanner call back typedef. - * - * This will be called when initinalization of the scanner - * is complete. It will also be called when scanner next - * returns results. - */ -typedef void (* hb_scanner_cb)(int32_t status, - hb_client_t client, - hb_scanner_t scanner, - hb_result_t results, - size_t num_results, - void * extra); -/* - * Get the next results from the scanner - */ -HBASE_API int32_t hb_scanner_next(hb_client_t client, - hb_scanner_t scanner, hb_scanner_cb cb, void * extra); - -/* - * Close the scanner releasing any local and server side - * resources held. The call back is fired just before the - * scanner's memory is freed. - */ -HBASE_API int32_t hb_scanner_destroy(hb_client_t client, - hb_scanner_t scanner, hb_scanner_cb cb, void * extra); - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif // ASYNC_HBASE_SCANNER_H_ diff --git a/hbase-native-client/src/async/mutations-test.cc b/hbase-native-client/src/async/mutations-test.cc deleted file mode 100644 index be5898ec95d4..000000000000 --- a/hbase-native-client/src/async/mutations-test.cc +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include "gtest/gtest.h" -#include "async/hbase_mutations.h" -#include "async/hbase_client.h" - -pthread_cond_t cv; -pthread_mutex_t mutex; - -bool sent = false; - -TEST(ClientTest, EasyTest) { - EXPECT_EQ(1, 1); -} - -void mutate_cb(int32_t status, - hb_client_t client, hb_mutation_t mutation, - hb_result_t result, void * extra) { - - // Test Stuff. - EXPECT_EQ(status, 0); - EXPECT_TRUE(client != NULL); - EXPECT_TRUE(mutation != NULL); - - pthread_mutex_lock(&mutex); - sent = true; - pthread_cond_signal(&cv); - pthread_mutex_unlock(&mutex); -} - -void wait_send() { - pthread_mutex_lock(&mutex); - while (!sent) { - pthread_cond_wait(&cv, &mutex); - } - pthread_mutex_unlock(&mutex); -} - -TEST(MutationTest, TestPut) { - char tn[] = "T1"; - hb_byte_t row[] = "ROW"; - char fam[] = "D"; - hb_byte_t qual[] = "QUAL"; - hb_byte_t data[] = "Z"; - - hb_client_t client = NULL; - hb_put_t put = NULL; - hb_cell_t cell; - - cell.family = fam; - cell.family_length = 1; - - cell.qual = qual; - cell.qual_length = 4; - - cell.value = data; - cell.value_length = 1; - - int32_t status = -1; - - status = hb_client_create(&client, NULL); - EXPECT_EQ(0, status); - - hb_put_create(&put); - hb_mutation_set_table((hb_mutation_t) put, tn, 2); - hb_mutation_set_row((hb_mutation_t) put, row, 3); - hb_put_add_cell(put, &cell); - - pthread_cond_init(&cv, NULL); - pthread_mutex_init(&mutex, NULL); - - status = hb_mutation_send(client, (hb_mutation_t) put, &mutate_cb, NULL); - EXPECT_EQ(0, status); - - // Now wait a while for things to send. - wait_send(); - EXPECT_EQ(true, sent); - - hb_mutation_destroy((hb_mutation_t *) put); - hb_client_destroy(client, NULL, NULL); - - EXPECT_EQ(0, status); -} diff --git a/hbase-native-client/src/core/CMakeLists.txt b/hbase-native-client/src/core/CMakeLists.txt deleted file mode 100644 index c15f64953104..000000000000 --- a/hbase-native-client/src/core/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -set( CORE_SRC - admin.cc - client.cc - connection.cc - get.cc - mutation.cc - put.cc - delete.cc - scanner.cc - hbase_connection_attr.cc -) - - -add_library(hcore OBJECT ${CORE_SRC}) diff --git a/hbase-native-client/src/core/admin.cc b/hbase-native-client/src/core/admin.cc deleted file mode 100644 index 897e6bf657d4..000000000000 --- a/hbase-native-client/src/core/admin.cc +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "core/admin.h" diff --git a/hbase-native-client/src/core/admin.h b/hbase-native-client/src/core/admin.h deleted file mode 100644 index 624c4ac8925e..000000000000 --- a/hbase-native-client/src/core/admin.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef CORE_ADMIN_H_ -#define CORE_ADMIN_H_ - -class Admin { -}; -#endif // CORE_ADMIN_H_ diff --git a/hbase-native-client/src/core/client.cc b/hbase-native-client/src/core/client.cc deleted file mode 100644 index 91c235c7d351..000000000000 --- a/hbase-native-client/src/core/client.cc +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "core/client.h" diff --git a/hbase-native-client/src/core/client.h b/hbase-native-client/src/core/client.h deleted file mode 100644 index 68348a841850..000000000000 --- a/hbase-native-client/src/core/client.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef CORE_CLIENT_H_ -#define CORE_CLIENT_H_ - -class Client { -}; -#endif // CORE_CLIENT_H_ diff --git a/hbase-native-client/src/core/connection.cc b/hbase-native-client/src/core/connection.cc deleted file mode 100644 index 099f31d58b20..000000000000 --- a/hbase-native-client/src/core/connection.cc +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "core/connection.h" - -void Connection::set_zk_quorum(char * zk_q) { - this->zk_quorum = zk_q; -} diff --git a/hbase-native-client/src/core/connection.h b/hbase-native-client/src/core/connection.h deleted file mode 100644 index 463b7b52319c..000000000000 --- a/hbase-native-client/src/core/connection.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef CORE_CONNECTION_H_ -#define CORE_CONNECTION_H_ - -class Connection { - char * zk_quorum; - public: - void set_zk_quorum(char * zk_q); -}; -#endif // CORE_CONNECTION_H_ diff --git a/hbase-native-client/src/core/connection_attr.h b/hbase-native-client/src/core/connection_attr.h deleted file mode 100644 index a7c229e34a11..000000000000 --- a/hbase-native-client/src/core/connection_attr.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef CORE_CONNECTION_ATTR_H_ -#define CORE_CONNECTION_ATTR_H_ - -#include "core/hbase_macros.h" -#include "core/hbase_types.h" - -class ConnectionAttr { -}; - -#endif // CORE_CONNECTION_ATTR_H_ - diff --git a/hbase-native-client/src/core/delete.cc b/hbase-native-client/src/core/delete.cc deleted file mode 100644 index 695f5bf39c80..000000000000 --- a/hbase-native-client/src/core/delete.cc +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "core/delete.h" - -Delete::~Delete() { -} diff --git a/hbase-native-client/src/core/delete.h b/hbase-native-client/src/core/delete.h deleted file mode 100644 index 5740fd965a42..000000000000 --- a/hbase-native-client/src/core/delete.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef CORE_DELETE_H_ -#define CORE_DELETE_H_ - -#include "core/mutation.h" - -class Delete: public Mutation { - public: - ~Delete(); -}; -#endif // CORE_DELETE_H_ diff --git a/hbase-native-client/src/core/get.cc b/hbase-native-client/src/core/get.cc deleted file mode 100644 index 9e11332ebab5..000000000000 --- a/hbase-native-client/src/core/get.cc +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "core/get.h" diff --git a/hbase-native-client/src/core/get.h b/hbase-native-client/src/core/get.h deleted file mode 100644 index 3a9fd286ab51..000000000000 --- a/hbase-native-client/src/core/get.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef CORE_GET_H_ -#define CORE_GET_H_ - -class Get { -}; - -#endif // CORE_GET_H_ diff --git a/hbase-native-client/src/core/hbase_connection_attr.h b/hbase-native-client/src/core/hbase_connection_attr.h deleted file mode 100644 index c73c818a9e03..000000000000 --- a/hbase-native-client/src/core/hbase_connection_attr.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef CORE_HBASE_CONNECTION_ATTR_H_ -#define CORE_HBASE_CONNECTION_ATTR_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "core/hbase_macros.h" -#include "core/hbase_types.h" - -#include - -HBASE_API int32_t hb_connection_attr_create(hb_connection_attr_t * attr_ptr); - -/** - * Set the zk quorum of a connection that will be created. - */ -HBASE_API int32_t hb_connection_attr_set_zk_quorum(hb_connection_t connection, - char * zk_quorum); - -/** - * Set the zk root of a connection that will be created. - */ -HBASE_API int32_t hb_connection_attr_set_zk_root(hb_connection_t connection, - char * zk_root); - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif // CORE_HBASE_CONNECTION_ATTR_H_ - diff --git a/hbase-native-client/src/core/hbase_macros.h b/hbase-native-client/src/core/hbase_macros.h deleted file mode 100644 index 71765c826599..000000000000 --- a/hbase-native-client/src/core/hbase_macros.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef CORE_HBASE_MACROS_H_ -#define CORE_HBASE_MACROS_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * The following code block define API as the tag for exported - * functions. The library should be compiled with symbols visibility - * set to hidden by default and only the exported functions should be - * tagged as HBASE_API. - * - * When building the library on Windows, compile with compiler flag - * "-D_LIBHBASE_IMPLEMENTATION_", whereas when linking application with - * this library, this compiler flag should not be used. - */ -#if defined _WIN32 || defined __CYGWIN__ - #ifdef _LIBHBASE_IMPLEMENTATION_ - #define API __declspec(dllexport) - #else - #ifdef _LIBHBASE_TEST_ - #define HBASE_API - #else - #define HBASE_API __declspec(dllimport) - #endif - #endif -#else - #if __GNUC__ >= 4 - #define HBASE_API __attribute__ ((visibility ("default"))) - #else - #define HBASE_API - #endif -#endif - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif // CORE_HBASE_MACROS_H_ - diff --git a/hbase-native-client/src/core/hbase_types.h b/hbase-native-client/src/core/hbase_types.h deleted file mode 100644 index 8889b92d1d08..000000000000 --- a/hbase-native-client/src/core/hbase_types.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef CORE_HBASE_TYPES_H_ -#define CORE_HBASE_TYPES_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -typedef unsigned char hb_byte_t; - -/* - * Base kv type. - */ -typedef struct { - hb_byte_t* row; - size_t row_length; - - char * family; - size_t family_length; - - hb_byte_t* qual; - size_t qual_length; - - hb_byte_t* value; - size_t value_length; - - uint64_t timestamp; -} hb_cell_t; - -typedef enum { - DELETE_ONE_VERSION, - DELETE_MULTIPLE_VERSIONS, - DELETE_FAMILY, - DELETE_FAMILY_VERSION -} hb_delete_type; - -typedef enum { - USE_DEFAULT, - SKIP_WAL, - ASYNC_WAL, - SYNC_WAL, - HSYNC_WAL -} hb_durability_type; - -typedef void* hb_admin_t; -typedef void* hb_client_t; -typedef void* hb_connection_attr_t; -typedef void* hb_connection_t; -typedef void* hb_get_t; -typedef void* hb_mutation_t; -typedef void* hb_put_t; -typedef void* hb_delete_t; -typedef void* hb_increment_t; -typedef void* hb_append_t; -typedef void* hb_result_t; -typedef void* hb_scanner_t; - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif // CORE_HBASE_TYPES_H_ diff --git a/hbase-native-client/src/core/mutation.h b/hbase-native-client/src/core/mutation.h deleted file mode 100644 index e35d59513daf..000000000000 --- a/hbase-native-client/src/core/mutation.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef CORE_MUTATION_H_ -#define CORE_MUTATION_H_ - -#include - -#include "core/hbase_types.h" - -class Mutation { - char * name_space; - size_t name_space_length; - - char * table; - size_t table_length; - - unsigned char * row; - size_t row_length; - - hb_durability_type durability; - public: - void set_namespace(char * name_space, size_t name_space_length); - void set_table(char * table, size_t table_length); - void set_row(unsigned char * row, size_t row_length); - void set_durability(hb_durability_type durability); - - virtual ~Mutation(); -}; -#endif // CORE_MUTATION_H_ - - diff --git a/hbase-native-client/src/core/put.cc b/hbase-native-client/src/core/put.cc deleted file mode 100644 index 8bedc8bd27ce..000000000000 --- a/hbase-native-client/src/core/put.cc +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "core/put.h" - -Put::~Put() { -} diff --git a/hbase-native-client/src/core/put.h b/hbase-native-client/src/core/put.h deleted file mode 100644 index 7bca3e300d3e..000000000000 --- a/hbase-native-client/src/core/put.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef CORE_PUT_H_ -#define CORE_PUT_H_ - -#include "core/mutation.h" - -class Put: public Mutation { - public: - ~Put(); -}; -#endif // CORE_PUT_H_ diff --git a/hbase-native-client/src/core/scanner.cc b/hbase-native-client/src/core/scanner.cc deleted file mode 100644 index a10e44442afc..000000000000 --- a/hbase-native-client/src/core/scanner.cc +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "core/scanner.h" diff --git a/hbase-native-client/src/core/scanner.h b/hbase-native-client/src/core/scanner.h deleted file mode 100644 index 257583be6794..000000000000 --- a/hbase-native-client/src/core/scanner.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef CORE_SCANNER_H_ -#define CORE_SCANNER_H_ - -class Scanner { -}; -#endif // CORE_SCANNER_H_ diff --git a/hbase-native-client/src/examples/async/example_async.c b/hbase-native-client/src/examples/async/example_async.c new file mode 100644 index 000000000000..6d337bc23898 --- /dev/null +++ b/hbase-native-client/src/examples/async/example_async.c @@ -0,0 +1,656 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#line 19 "example_async.c" // ensures short filename in logs. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Found under /libhbase/src/test/native/common */ +#include "byte_buffer.h" + +/* + * Sample code to illustrate usage of libhbase APIs + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define CHECK_API_ERROR(retCode, ...) \ + HBASE_LOG_MSG((retCode ? HBASE_LOG_LEVEL_ERROR : HBASE_LOG_LEVEL_INFO), \ + __VA_ARGS__, retCode); + +static byte_t *FAMILIES[] = { (byte_t *)"f", (byte_t *)"g" }; +static hb_columndesc HCD[2] = { NULL }; + +typedef struct cell_data_t_ { + bytebuffer value; + hb_cell_t *hb_cell; + struct cell_data_t_ *next_cell; +} cell_data_t; + +cell_data_t* +new_cell_data() { + cell_data_t *cell_data = (cell_data_t*) calloc(1, sizeof(cell_data_t)); + cell_data->next_cell = NULL; + return cell_data; +} + +typedef struct row_data_t_ { + bytebuffer key; + struct cell_data_t_ *first_cell; +} row_data_t; + +static void +release_row_data(row_data_t *row_data) { + if (row_data != NULL) { + cell_data_t *cell = row_data->first_cell; + while (cell) { + bytebuffer_free(cell->value); + free(cell->hb_cell); + cell_data_t *cur_cell = cell; + cell = cell->next_cell; + free(cur_cell); + } + bytebuffer_free(row_data->key); + free(row_data); + } +} + +/** + * Put synchronizer and callback + */ +static volatile int32_t outstanding_puts_count; +static pthread_cond_t puts_cv = PTHREAD_COND_INITIALIZER; +static pthread_mutex_t puts_mutex = PTHREAD_MUTEX_INITIALIZER; + +static void +put_callback(int32_t err, hb_client_t client, + hb_mutation_t mutation, hb_result_t result, void *extra) { + row_data_t* row_data = (row_data_t *)extra; + HBASE_LOG_INFO("Received put callback for row \'%.*s\', result = %d.", + row_data->key->length, row_data->key->buffer, err); + release_row_data(row_data); + hb_mutation_destroy(mutation); + + pthread_mutex_lock(&puts_mutex); + outstanding_puts_count--; + if (outstanding_puts_count == 0) { + pthread_cond_signal(&puts_cv); + } + pthread_mutex_unlock(&puts_mutex); +} + +static void +wait_for_puts() { + HBASE_LOG_INFO("Waiting for outstanding puts to complete."); + pthread_mutex_lock(&puts_mutex); + while (outstanding_puts_count > 0) { + pthread_cond_wait(&puts_cv, &puts_mutex); + } + pthread_mutex_unlock(&puts_mutex); + HBASE_LOG_INFO("Put operations completed."); +} + +/** + * Flush synchronizer and callback + */ +static volatile bool flush_done = false; +static pthread_cond_t flush_cv = PTHREAD_COND_INITIALIZER; +static pthread_mutex_t flush_mutex = PTHREAD_MUTEX_INITIALIZER; + +static void +client_flush_callback(int32_t err, + hb_client_t client, void *extra) { + HBASE_LOG_INFO("Received client flush callback."); + pthread_mutex_lock(&flush_mutex); + flush_done = true; + pthread_cond_signal(&flush_cv); + pthread_mutex_unlock(&flush_mutex); +} + +static void +wait_for_flush() { + HBASE_LOG_INFO("Waiting for flush to complete."); + pthread_mutex_lock(&flush_mutex); + while (!flush_done) { + pthread_cond_wait(&flush_cv, &flush_mutex); + } + pthread_mutex_unlock(&flush_mutex); + HBASE_LOG_INFO("Flush completed."); +} + +static void printRow(const hb_result_t result) { + const byte_t *key = NULL; + size_t key_len = 0; + hb_result_get_key(result, &key, &key_len); + size_t cell_count = 0; + hb_result_get_cell_count(result, &cell_count); + HBASE_LOG_INFO("Row=\'%.*s\', cell count=%d", key_len, key, cell_count); + const hb_cell_t **cells; + hb_result_get_cells(result, &cells, &cell_count); + for (size_t i = 0; i < cell_count; ++i) { + HBASE_LOG_INFO( + "Cell %d: family=\'%.*s\', qualifier=\'%.*s\', " + "value=\'%.*s\', timestamp=%lld.", i, + cells[i]->family_len, cells[i]->family, + cells[i]->qualifier_len, cells[i]->qualifier, + cells[i]->value_len, cells[i]->value, cells[i]->ts); + } +} + +/** + * Get synchronizer and callback + */ +static volatile bool get_done = false; +static pthread_cond_t get_cv = PTHREAD_COND_INITIALIZER; +static pthread_mutex_t get_mutex = PTHREAD_MUTEX_INITIALIZER; + +static void +get_callback(int32_t err, hb_client_t client, + hb_get_t get, hb_result_t result, void *extra) { + bytebuffer rowKey = (bytebuffer)extra; + if (err == 0) { + const char *table_name; + size_t table_name_len; + hb_result_get_table(result, &table_name, &table_name_len); + HBASE_LOG_INFO("Received get callback for table=\'%.*s\'.", + table_name_len, table_name); + + printRow(result); + + const hb_cell_t *mycell; + bytebuffer qualifier = bytebuffer_strcpy("column-a"); + HBASE_LOG_INFO("Looking up cell for family=\'%s\', qualifier=\'%.*s\'.", + FAMILIES[0], qualifier->length, qualifier->buffer); + if (hb_result_get_cell(result, FAMILIES[0], 1, qualifier->buffer, + qualifier->length, &mycell) == 0) { + HBASE_LOG_INFO("Cell found, value=\'%.*s\', timestamp=%lld.", + mycell->value_len, mycell->value, mycell->ts); + } else { + HBASE_LOG_ERROR("Cell not found."); + } + bytebuffer_free(qualifier); + hb_result_destroy(result); + } else { + HBASE_LOG_ERROR("Get failed with error code: %d.", err); + } + + bytebuffer_free(rowKey); + hb_get_destroy(get); + + pthread_mutex_lock(&get_mutex); + get_done = true; + pthread_cond_signal(&get_cv); + pthread_mutex_unlock(&get_mutex); +} + +static void +wait_for_get() { + HBASE_LOG_INFO("Waiting for get operation to complete."); + pthread_mutex_lock(&get_mutex); + while (!get_done) { + pthread_cond_wait(&get_cv, &get_mutex); + } + pthread_mutex_unlock(&get_mutex); + HBASE_LOG_INFO("Get operation completed."); +} + +/** + * Delete synchronizer and callbacks + */ +static volatile bool delete_done = false; +static pthread_cond_t del_cv = PTHREAD_COND_INITIALIZER; +static pthread_mutex_t del_mutex = PTHREAD_MUTEX_INITIALIZER; + +static void +delete_callback(int32_t err, hb_client_t client, + hb_mutation_t delete, hb_result_t result, void *extra) { + bytebuffer rowKey = (bytebuffer)extra; + HBASE_LOG_INFO("Received delete callback for row \'%.*s\', " + "result = %d.", rowKey->length, rowKey->buffer, err); + + hb_mutation_destroy(delete); + pthread_mutex_lock(&del_mutex); + delete_done = true; + pthread_cond_signal(&del_cv); + pthread_mutex_unlock(&del_mutex); +} + +static void +wait_for_delete() { + HBASE_LOG_INFO("Waiting for delete operation to complete."); + pthread_mutex_lock(&del_mutex); + while (!delete_done) { + pthread_cond_wait(&del_cv, &del_mutex); + } + pthread_mutex_unlock(&del_mutex); + HBASE_LOG_INFO("Delete operation completed."); +} + +/** + * Scan synchronizer and callbacks + */ +static volatile bool scan_done = false; +static pthread_cond_t scan_cv = PTHREAD_COND_INITIALIZER; +static pthread_mutex_t scan_mutex = PTHREAD_MUTEX_INITIALIZER; + +void scan_callback(int32_t err, hb_scanner_t scanner, + hb_result_t results[], size_t num_results, void *extra) { + if (num_results) { + const char *table_name; + size_t table_name_len; + hb_result_get_table(results[0], &table_name, &table_name_len); + HBASE_LOG_INFO("Received scan_next callback for table=\'%.*s\', row count=%d.", + table_name_len, table_name, num_results); + + for (int i = 0; i < num_results; ++i) { + printRow(results[i]); + hb_result_destroy(results[i]); + } + hb_scanner_next(scanner, scan_callback, NULL); + } else { + hb_scanner_destroy(scanner, NULL, NULL); + pthread_mutex_lock(&scan_mutex); + scan_done = true; + pthread_cond_signal(&scan_cv); + pthread_mutex_unlock(&scan_mutex); + } +} + +static void +wait_for_scan() { + HBASE_LOG_INFO("Waiting for scan to complete."); + pthread_mutex_lock(&scan_mutex); + while (!scan_done) { + pthread_cond_wait(&scan_cv, &scan_mutex); + } + pthread_mutex_unlock(&scan_mutex); + HBASE_LOG_INFO("Scan completed."); +} + +/** + * Client destroy synchronizer and callbacks + */ +static volatile bool client_destroyed = false; +static pthread_cond_t client_destroyed_cv = PTHREAD_COND_INITIALIZER; +static pthread_mutex_t client_destroyed_mutex = PTHREAD_MUTEX_INITIALIZER; + +static void +client_disconnection_callback(int32_t err, + hb_client_t client, void *extra) { + HBASE_LOG_INFO("Received client disconnection callback."); + pthread_mutex_lock(&client_destroyed_mutex); + client_destroyed = true; + pthread_cond_signal(&client_destroyed_cv); + pthread_mutex_unlock(&client_destroyed_mutex); +} + +static void +wait_client_disconnection() { + HBASE_LOG_INFO("Waiting for client to disconnect."); + pthread_mutex_lock(&client_destroyed_mutex); + while (!client_destroyed) { + pthread_cond_wait(&client_destroyed_cv, &client_destroyed_mutex); + } + pthread_mutex_unlock(&client_destroyed_mutex); + HBASE_LOG_INFO("Client disconnected."); +} + +static int +ensureTable(hb_connection_t connection, const char *table_name) { + int32_t retCode = 0; + hb_admin_t admin = NULL; + + if ((retCode = hb_admin_create(connection, &admin)) != 0) { + HBASE_LOG_ERROR("Could not create HBase admin : errorCode = %d.", retCode); + goto cleanup; + } + + if ((retCode = hb_admin_table_exists(admin, NULL, table_name)) == 0) { + HBASE_LOG_INFO("Table '%s' exists, deleting...", table_name); + if ((retCode = hb_admin_table_delete(admin, NULL, table_name)) != 0) { + HBASE_LOG_ERROR("Could not delete table %s[%d].", table_name, retCode); + goto cleanup; + } + } else if (retCode != ENOENT) { + HBASE_LOG_ERROR("Error while checking if the table exists: errorCode = %d.", retCode); + goto cleanup; + } + + hb_coldesc_create(FAMILIES[0], 1, &HCD[0]); + hb_coldesc_set_maxversions(HCD[0], 2); + hb_coldesc_set_minversions(HCD[0], 1); + hb_coldesc_set_ttl(HCD[0], 2147480000); + hb_coldesc_set_inmemory(HCD[0], 1); + + hb_coldesc_create(FAMILIES[1], 1, &HCD[1]); + + HBASE_LOG_INFO("Creating table '%s'...", table_name); + if ((retCode = hb_admin_table_create(admin, NULL, table_name, HCD, 2)) == 0) { + HBASE_LOG_INFO("Table '%s' created, verifying if enabled.", table_name); + retCode = hb_admin_table_enabled(admin, NULL, table_name); + CHECK_API_ERROR(retCode, + "Table '%s' is %senabled, result %d.", table_name, retCode?"not ":""); + retCode = hb_admin_table_disable(admin, NULL, table_name); + CHECK_API_ERROR(retCode, + "Attempted to disable table '%s', result %d.", table_name); + retCode = hb_admin_table_disable(admin, NULL, table_name); + CHECK_API_ERROR(retCode, + "Attempted to disable table '%s' again, result %d.", table_name); + retCode = hb_admin_table_enable(admin, NULL, table_name); + CHECK_API_ERROR(retCode, + "Attempted to enable table '%s', result %d.", table_name); + retCode = hb_admin_table_enable(admin, NULL, table_name); + CHECK_API_ERROR(retCode, + "Attempted to enable table '%s' again, result %d.", table_name); + } + hb_coldesc_destroy(HCD[0]); + hb_coldesc_destroy(HCD[1]); + +cleanup: + if (admin) { + hb_admin_destroy(admin, NULL, NULL); + } + return retCode; +} + +/** + * Program entry point + */ +int +main(int argc, char **argv) { + int32_t retCode = 0; + FILE* logFile = NULL; + hb_connection_t connection = NULL; + hb_client_t client = NULL; + const char *rowkey_prefix = "row"; + const char *value_prefix = "test value"; + bytebuffer column_a = bytebuffer_strcpy("column-a"); + bytebuffer column_b = bytebuffer_strcpy("column-b"); + + const char *table_name = (argc > 1) ? argv[1] : "TempTable"; + const char *zk_ensemble = (argc > 2) ? argv[2] : "localhost:2181"; + const char *zk_root_znode = (argc > 3) ? argv[3] : NULL; + const size_t table_name_len = strlen(table_name); + + const int num_puts = 10; + hb_put_t put = NULL; + + srand(time(NULL)); + hb_log_set_level(HBASE_LOG_LEVEL_DEBUG); // defaults to INFO + const char *logFilePath = getenv("HBASE_LOG_FILE"); + if (logFilePath != NULL) { + FILE* logFile = fopen(logFilePath, "a"); + if (!logFile) { + retCode = errno; + fprintf(stderr, "Unable to open log file \"%s\"", logFilePath); + perror(NULL); + goto cleanup; + } + hb_log_set_stream(logFile); // defaults to stderr + } + + if ((retCode = hb_connection_create(zk_ensemble, + zk_root_znode, + &connection)) != 0) { + HBASE_LOG_ERROR("Could not create HBase connection : errorCode = %d.", retCode); + goto cleanup; + } + + if ((retCode = ensureTable(connection, table_name)) != 0) { + HBASE_LOG_ERROR("Failed to ensure table %s : errorCode = %d", table_name, retCode); + goto cleanup; + } + + HBASE_LOG_INFO("Connecting to HBase cluster using Zookeeper ensemble '%s'.", + zk_ensemble); + if ((retCode = hb_client_create(connection, &client)) != 0) { + HBASE_LOG_ERROR("Could not connect to HBase cluster : errorCode = %d.", retCode); + goto cleanup; + } + + // let's send a batch of 10 puts with single cell asynchronously + outstanding_puts_count += num_puts; + for (int i = 0; i < num_puts; ++i) { + row_data_t *row_data = (row_data_t *) calloc(1, sizeof(row_data_t)); + row_data->key = bytebuffer_printf("%s%02d", rowkey_prefix, i); + hb_put_create(row_data->key->buffer, row_data->key->length, &put); + hb_mutation_set_table(put, table_name, table_name_len); + hb_mutation_set_durability(put, DURABILITY_SKIP_WAL); + hb_mutation_set_bufferable(put, false); + + cell_data_t *cell_data = new_cell_data(); + row_data->first_cell = cell_data; + cell_data->value = bytebuffer_printf("%s%02d", value_prefix, i); + + hb_cell_t *cell = (hb_cell_t*) calloc(1, sizeof(hb_cell_t)); + cell_data->hb_cell = cell; + + cell->row = row_data->key->buffer; + cell->row_len = row_data->key->length; + cell->family = FAMILIES[rand() % 2]; + cell->family_len = 1; + cell->qualifier = column_a->buffer; + cell->qualifier_len = column_a->length; + cell->value = cell_data->value->buffer; + cell->value_len = cell_data->value->length; + cell->ts = HBASE_LATEST_TIMESTAMP; + + hb_put_add_cell(put, cell); + HBASE_LOG_INFO("Sending row with row key : '%.*s'.", + cell->row_len, cell->row); + hb_mutation_send(client, put, put_callback, row_data); + } + hb_client_flush(client, client_flush_callback, NULL); + wait_for_flush(); + + wait_for_puts(); // outside the loop, wait for 10 puts to complete + + // now, let's put two cells in a single row + outstanding_puts_count++; + { + row_data_t *row_data = (row_data_t *) calloc(1, sizeof(row_data_t)); + row_data->key = bytebuffer_printf("row_with_two_cells"); + hb_put_create(row_data->key->buffer, row_data->key->length, &put); + hb_mutation_set_table(put, table_name, table_name_len); + hb_mutation_set_durability(put, DURABILITY_SYNC_WAL); + + // first cell + cell_data_t *cell1_data = new_cell_data(); + row_data->first_cell = cell1_data; + cell1_data->value = bytebuffer_printf("cell1_value_v1"); + + hb_cell_t *cell1 = (hb_cell_t*) calloc(1, sizeof(hb_cell_t)); + cell1_data->hb_cell = cell1; + + cell1->row = row_data->key->buffer; + cell1->row_len = row_data->key->length; + cell1->family = FAMILIES[0]; + cell1->family_len = 1; + cell1->qualifier = column_a->buffer; + cell1->qualifier_len = column_a->length; + cell1->value = cell1_data->value->buffer; + cell1->value_len = cell1_data->value->length; + cell1->ts = 1391111111111L; + hb_put_add_cell(put, cell1); + + // second cell + cell_data_t *cell2_data = new_cell_data(); + cell1_data->next_cell = cell2_data; + cell2_data->value = bytebuffer_printf("cell2_value_v1"); + + hb_cell_t *cell2 = (hb_cell_t*) calloc(1, sizeof(hb_cell_t)); + cell2_data->hb_cell = cell2; + + cell2->row = row_data->key->buffer; + cell2->row_len = row_data->key->length; + cell2->family = FAMILIES[1]; + cell2->family_len = 1; + cell2->qualifier = column_b->buffer; + cell2->qualifier_len = column_b->length; + cell2->value = cell2_data->value->buffer; + cell2->value_len = cell2_data->value->length; + cell2->ts = 1391111111111L; + hb_put_add_cell(put, cell2); + + HBASE_LOG_INFO("Sending row with row key : '%.*s'.", + cell1->row_len, cell1->row); + hb_mutation_send(client, put, put_callback, row_data); + wait_for_puts(); + } + + // now, let's put second version in one column + outstanding_puts_count++; + { + row_data_t *row_data = (row_data_t *) calloc(1, sizeof(row_data_t)); + row_data->key = bytebuffer_printf("row_with_two_cells"); + hb_put_create(row_data->key->buffer, row_data->key->length, &put); + hb_mutation_set_table(put, table_name, table_name_len); + hb_mutation_set_durability(put, DURABILITY_SYNC_WAL); + + // first cell + cell_data_t *cell1_data = new_cell_data(); + row_data->first_cell = cell1_data; + cell1_data->value = bytebuffer_printf("cell1_value_v2"); + + hb_cell_t *cell1 = (hb_cell_t*) calloc(1, sizeof(hb_cell_t)); + cell1_data->hb_cell = cell1; + + cell1->row = row_data->key->buffer; + cell1->row_len = row_data->key->length; + cell1->family = FAMILIES[0]; + cell1->family_len = 1; + cell1->qualifier = column_a->buffer; + cell1->qualifier_len = column_a->length; + cell1->value = cell1_data->value->buffer; + cell1->value_len = cell1_data->value->length; + cell1->ts = 1392222222222L; + hb_put_add_cell(put, cell1); + + HBASE_LOG_INFO("Sending row with row key : '%.*s'.", + cell1->row_len, cell1->row); + hb_mutation_send(client, put, put_callback, row_data); + wait_for_puts(); + } + + // now, scan the entire table + { + hb_scanner_t scanner = NULL; + hb_scanner_create(client, &scanner); + hb_scanner_set_table(scanner, table_name, table_name_len); + hb_scanner_set_num_max_rows(scanner, 3); // maximum 3 rows at a time + hb_scanner_set_num_versions(scanner, 10); // up to 10 versions of the cell + hb_scanner_next(scanner, scan_callback, NULL); // dispatch the call + wait_for_scan(); + } + + // fetch a row with row-key="row_with_two_cells" + { + bytebuffer rowKey = bytebuffer_strcpy("row_with_two_cells"); + hb_get_t get = NULL; + hb_get_create(rowKey->buffer, rowKey->length, &get); + hb_get_add_column(get, FAMILIES[0], 1, NULL, 0); + hb_get_add_column(get, FAMILIES[1], 1, NULL, 0); + hb_get_set_table(get, table_name, table_name_len); + hb_get_set_num_versions(get, 10); // up to ten versions of each column + + get_done = false; + hb_get_send(client, get, get_callback, rowKey); + wait_for_get(); + } + + // delete a specific version of a column + { + bytebuffer rowKey = bytebuffer_strcpy("row_with_two_cells"); + hb_delete_t del = NULL; + hb_delete_create(rowKey->buffer, rowKey->length, &del); + hb_delete_add_column(del, FAMILIES[0], 1, + column_a->buffer, column_a->length, 1391111111112L); + hb_mutation_set_table(del, table_name, table_name_len); + + delete_done = false; + hb_mutation_send(client, del, delete_callback, rowKey); + wait_for_delete(); + } + + // fetch a row with row-key="row_with_two_cells" + { + bytebuffer rowKey = bytebuffer_strcpy("row_with_two_cells"); + hb_get_t get = NULL; + hb_get_create(rowKey->buffer, rowKey->length, &get); + hb_get_add_column(get, FAMILIES[0], 1, NULL, 0); + hb_get_add_column(get, FAMILIES[1], 1, NULL, 0); + hb_get_set_table(get, table_name, table_name_len); + hb_get_set_num_versions(get, 10); // up to ten versions of each column + + get_done = false; + hb_get_send(client, get, get_callback, rowKey); + wait_for_get(); + } + +cleanup: + if (client) { + HBASE_LOG_INFO("Disconnecting client."); + hb_client_destroy(client, client_disconnection_callback, NULL); + wait_client_disconnection(); + } + + if (connection) { + hb_connection_destroy(connection); + } + + if (column_a) { + bytebuffer_free(column_a); // do not need 'column' anymore + } + if (column_b) { + bytebuffer_free(column_b); + } + + if (logFile) { + fclose(logFile); + } + + pthread_cond_destroy(&puts_cv); + pthread_mutex_destroy(&puts_mutex); + + pthread_cond_destroy(&get_cv); + pthread_mutex_destroy(&get_mutex); + + pthread_cond_destroy(&del_cv); + pthread_mutex_destroy(&del_mutex); + + pthread_cond_destroy(&client_destroyed_cv); + pthread_mutex_destroy(&client_destroyed_mutex); + + return retCode; +} + +#ifdef __cplusplus +} +#endif diff --git a/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/CallbackHandlers.java b/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/CallbackHandlers.java new file mode 100644 index 000000000000..48e84cb910c6 --- /dev/null +++ b/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/CallbackHandlers.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.hadoop.hbase.jni; + +public class CallbackHandlers { + + private static volatile boolean nativeLibLoaded = false; + static { + try { + synchronized (CallbackHandlers.class) { + System.loadLibrary("hbase"); + nativeLibLoaded = true; + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static boolean isNativeLibLoaded() { + return nativeLibLoaded; + } + + public static native void mutationCallBack(Throwable t, + long callback, long client, long mutation, Object result, long extra); + + public static native void getCallBack(Throwable t, + long callback, long client, long get, Object result, long extra); + + public static native void clientFlushCallBack(Throwable t, + long callback, long client, long extra); + + public static native void clientCloseCallBack(Throwable t, + long callback, long client, long extra); + + public static native void scannerCloseCallBack(Throwable t, + long callback, long scanner, long extra); + + public static native void scanNextCallBack(Throwable t, + long callback, long scanner, Object[] results, int numResults, long extra); +} diff --git a/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/ClientProxy.java b/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/ClientProxy.java new file mode 100644 index 000000000000..d68604cc38a7 --- /dev/null +++ b/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/ClientProxy.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.hadoop.hbase.jni; + +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; + +import org.apache.hadoop.conf.Configuration; +import org.hbase.async.HBaseClient; +import org.hbase.async.KeyValue; +import org.hbase.async.Scanner; + +public class ClientProxy implements Closeable { + private final HBaseClient client_; + + ClientProxy(final Configuration conf) { + final String zkQuorum = conf.get("hbase.zookeeper.ensemble"); + final String baseZNode = conf.get("zookeeper.znode.parent"); + this.client_ = new HBaseClient(zkQuorum, baseZNode); + } + + Scanner newScanner(byte[] table) { + return client_.newScanner(table); + } + + public void sendMutation(final MutationProxy mutationProxy, + final long callback, final long client, + final long mutation, final long extra) { + mutationProxy.send(client_, + new MutationCallbackHandler( + mutationProxy, callback, client, mutation, extra)); + } + + public void sendGet(final GetProxy getProxy, + final long callback, final long client, + final long get, final long extra) { + getProxy.send(client_, + new GetCallbackHandler>( + getProxy, callback, client, get, extra)); + } + + public void flush(final long callback, + final long client, final long extra) + throws IOException { + this.client_.flush().addBoth( + new FlushCallbackHandler( + callback, client, extra)); + } + + @Override + public void close() throws IOException { + close(0, 0, 0); + } + + public void close(final long callback, + final long client, final long extra) + throws IOException { + this.client_.shutdown().addBoth( + new ClientShutdownCallback( + callback, client, extra)); + } +} diff --git a/hbase-native-client/src/core/mutation.cc b/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/ClientShutdownCallback.java similarity index 56% rename from hbase-native-client/src/core/mutation.cc rename to hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/ClientShutdownCallback.java index 48550766958c..3c19ffdae9af 100644 --- a/hbase-native-client/src/core/mutation.cc +++ b/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/ClientShutdownCallback.java @@ -16,27 +16,31 @@ * limitations under the License. * */ +package org.apache.hadoop.hbase.jni; -#include "core/mutation.h" +import com.stumbleupon.async.Callback; -void Mutation::set_namespace(char * name_space, size_t name_space_length) { - this->name_space = name_space; - this->name_space_length = name_space_length; -} +public class ClientShutdownCallback implements Callback { -void Mutation::set_table(char * table, size_t table_length) { - this->table = table; - this->table_length = table_length; -} + private long callback; + private long client; + private long extra; -void Mutation::set_row(unsigned char * row, size_t row_length) { - this->row = row; - this->row_length = row_length; -} + public ClientShutdownCallback(long callback, long client, long extra) { + this.callback = callback; + this.client = client; + this.extra = extra; + } -void Mutation::set_durability(hb_durability_type durability) { - this->durability = durability; -} + @Override + public R call(T arg) throws Exception { + Throwable t = null; + if (arg instanceof Throwable) { + t = (Throwable) arg; + } + CallbackHandlers.clientCloseCallBack(t, + callback, client, extra); + return null; + } -Mutation::~Mutation() { } diff --git a/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/DeleteProxy.java b/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/DeleteProxy.java new file mode 100644 index 000000000000..23ae48b675b4 --- /dev/null +++ b/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/DeleteProxy.java @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.hadoop.hbase.jni; + +import java.util.List; +import java.util.Map; + +import org.apache.hadoop.hbase.client.Durability; +import org.apache.hadoop.hbase.client.Mutation; +import org.hbase.async.DeleteRequest; +import org.hbase.async.HBaseClient; +import org.hbase.async.KeyValue; + +public class DeleteProxy extends MutationProxy { + + public DeleteProxy(final byte[] row) { + this.row_ = row; + } + + @Override + public void send(final HBaseClient client, + final MutationCallbackHandler cbh) { + final Map> familyMap = getFamilyMap(); + final int numFamilies = familyMap.size(); + DeleteRequest del = null; + if (numFamilies > 0) { + final byte[][] families = new byte[numFamilies][]; + final byte[][][] qualifiers = new byte[numFamilies][][]; + final long[][] timestamps = new long[numFamilies][]; + int idx = 0; + for (byte[] family : familyMap.keySet()) { + families[idx] = family; + final List kvList = familyMap.get(family); + final int numKVs = kvList.size(); + if (numKVs > 0) { + boolean hasQualifier = false; + qualifiers[idx] = new byte[numKVs][]; + timestamps[idx] = new long[numKVs]; + for (int i = 0; i < numKVs; i++) { + KeyValue kv = kvList.get(i); + if (kv.qualifier().length > 0) { + hasQualifier = true; + qualifiers[idx][i] = kv.qualifier(); + timestamps[idx][i] = kv.timestamp(); + } + } + if (!hasQualifier) { + qualifiers[idx] = null; + timestamps[idx] = null; + } + } + idx++; + } + del = new DeleteRequest(getTable(), getRow(), families, qualifiers, timestamps, getTS()); + } else { + del = new DeleteRequest(getTable(), getRow()); + } + // set attributes + del.setDurable(getDurability() != Durability.SKIP_WAL); + del.setBufferable(isBufferable()); + // hand over and attach callback + client.delete(del).addBoth(cbh); + } + + @Override + public Mutation toHBaseMutation() { + //TODO + return null; + } +} diff --git a/hbase-native-client/src/async/hbase_client.cc b/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/FlushCallbackHandler.java similarity index 57% rename from hbase-native-client/src/async/hbase_client.cc rename to hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/FlushCallbackHandler.java index 98e3dbf3450d..996902270cef 100644 --- a/hbase-native-client/src/async/hbase_client.cc +++ b/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/FlushCallbackHandler.java @@ -16,32 +16,31 @@ * limitations under the License. * */ +package org.apache.hadoop.hbase.jni; -#include "async/hbase_client.h" +import com.stumbleupon.async.Callback; -#include -#include -#include +public class FlushCallbackHandler implements Callback { -#include "core/client.h" -#include "async/hbase_connection.h" + private long callback; + private long client; + private long extra; -int32_t hb_client_create(hb_client_t* client_ptr, - hb_connection_t connection) { - (*client_ptr) = reinterpret_cast(new Client()); - if (client_ptr == NULL) - return -1; // TODO(eclark): setup the errno file. - return 0; -} + public FlushCallbackHandler(long callback, long client, long extra) { + this.callback = callback; + this.client = client; + this.extra = extra; + } -int32_t hb_client_destroy(hb_client_t client, - hb_client_disconnection_cb cb, void * extra) { - if (client == NULL) - return -2; - if (cb) { - cb(0, client, extra); + @Override + public R call(T arg) throws Exception { + Throwable t = null; + if (arg instanceof Throwable) { + t = (Throwable) arg; + } + CallbackHandlers.clientFlushCallBack(t, + callback, client, extra); + return null; } - free(client); - return 0; -} +} diff --git a/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/GetCallbackHandler.java b/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/GetCallbackHandler.java new file mode 100644 index 000000000000..e663f8dc5855 --- /dev/null +++ b/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/GetCallbackHandler.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.hadoop.hbase.jni; + +import java.util.ArrayList; + +import org.hbase.async.KeyValue; + +import com.stumbleupon.async.Callback; + +public class GetCallbackHandler implements Callback { + private final long callback; + private final long extra; + private final long client; + private final long get; + private GetProxy getProxy; + + public GetCallbackHandler(GetProxy getProxy, long callback, long client, long get, long extra) { + this.getProxy = getProxy; + this.callback = callback; + this.client = client; + this.get = get; + this.extra = extra; + } + + @Override + @SuppressWarnings("unchecked") + public R call(T arg) throws Exception { + ResultProxy result = null; + Throwable t = null; + if (arg instanceof Throwable) { + t = (Throwable) arg; + } else if (arg != null && arg instanceof ArrayList) { + result = new ResultProxy(getProxy.getTable(), getProxy.getNamespace(), + (ArrayList) arg); + } + CallbackHandlers.getCallBack(t, + callback, client, get, result, extra); + return null; + } +} diff --git a/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/GetProxy.java b/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/GetProxy.java new file mode 100644 index 000000000000..358851b7d5e8 --- /dev/null +++ b/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/GetProxy.java @@ -0,0 +1,117 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.hadoop.hbase.jni; + +import java.nio.charset.CharacterCodingException; +import java.util.ArrayList; +import java.util.Map; +import java.util.NavigableSet; +import java.util.TreeMap; +import java.util.TreeSet; + +import org.apache.hadoop.hbase.filter.Filter; +import org.apache.hadoop.hbase.filter.ParseFilter; +import org.apache.hadoop.hbase.util.Bytes; +import org.hbase.async.GetRequest; +import org.hbase.async.HBaseClient; +import org.hbase.async.KeyValue; + +public class GetProxy extends RowProxy { + static final ParseFilter parseFilter = new ParseFilter(); + + final private Map> familyMap = + new TreeMap>(Bytes.BYTES_COMPARATOR); + private Filter filter; + private int maxVersions = 1; + + public GetProxy(final byte[] row) { + this.row_ = row; + } + + public GetProxy addColumn(final byte [] family, + final byte [] qualifier) { + NavigableSet set = familyMap.get(family); + if(set == null) { + set = new TreeSet(Bytes.BYTES_COMPARATOR); + familyMap.put(family, set); + } + if (qualifier != null) { + set.add(qualifier); + } + return this; + } + + public GetProxy setFilter(final String filter) { + try { + this.filter = parseFilter.parseFilterString(filter); + } catch (CharacterCodingException e) { + // TODO Handle error + e.printStackTrace(); + } + return this; + } + + public GetProxy setMaxVersions(final int maxVersions) { + this.maxVersions = maxVersions; + return this; + } + + Filter getFilter() { + return filter; + } + + Map> getFamilyMap() { + return familyMap; + } + + int getMaxVersions() { + return maxVersions; + } + + public void send(final HBaseClient client, + final GetCallbackHandler> cbh) { + final GetRequest getReq = new GetRequest(getTable(), getRow()); + Map> familyMap = getFamilyMap(); + if (familyMap.size() != 0) { + final int numFamilies = familyMap.size(); + final byte[][] families = new byte[numFamilies][]; + final byte[][][] qualifiers = new byte[numFamilies][][]; + int idx = 0; + for (byte[] family : familyMap.keySet()) { + families[idx] = family; + NavigableSet qualifierSet = familyMap.get(family); + if (qualifierSet.size() == 0) { + qualifiers[idx] = null; + } else { + qualifiers[idx] = new byte[qualifierSet.size()][]; + int i = 0; + for (byte[] qualifier : qualifierSet) { + qualifiers[idx][i] = qualifier; + ++i; + } + } + ++idx; + } + getReq.families(families); + getReq.qualifiers(qualifiers); + } + getReq.maxVersions(getMaxVersions()); + client.get(getReq).addBoth(cbh); + } +} diff --git a/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/MutationCallbackHandler.java b/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/MutationCallbackHandler.java new file mode 100644 index 000000000000..051a71955c72 --- /dev/null +++ b/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/MutationCallbackHandler.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.hadoop.hbase.jni; + +import java.util.ArrayList; + +import org.hbase.async.KeyValue; + +import com.stumbleupon.async.Callback; + +public class MutationCallbackHandler implements Callback { + private final long callback; + private final long extra; + private final long client; + private final long mutation; + private MutationProxy mutationProxy; + + public MutationCallbackHandler(MutationProxy mutationProxy, + long callback, long client, long mutation, long extra) { + this.mutationProxy = mutationProxy; + this.callback = callback; + this.client = client; + this.mutation = mutation; + this.extra = extra; + } + + @Override + @SuppressWarnings("unchecked") + public R call(T arg) throws Exception { + ResultProxy result = null; + Throwable t = null; + if (arg instanceof Throwable) { + t = (Throwable) arg; + } else if (arg != null && arg instanceof ArrayList) { + result = new ResultProxy(mutationProxy.getTable(), + mutationProxy.getNamespace(), (ArrayList) arg); + } + + CallbackHandlers.mutationCallBack(t, + callback, client, mutation, result, extra); + return null; + } +} diff --git a/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/MutationProxy.java b/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/MutationProxy.java new file mode 100644 index 000000000000..bc603350cbe1 --- /dev/null +++ b/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/MutationProxy.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.hadoop.hbase.jni; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.hadoop.hbase.client.Durability; +import org.apache.hadoop.hbase.client.Mutation; +import org.apache.hadoop.hbase.util.Bytes; +import org.hbase.async.HBaseClient; +import org.hbase.async.KeyValue; + +public abstract class MutationProxy extends RowProxy { + protected Durability durability_ = Durability.USE_DEFAULT; + + protected boolean bufferable_ = false; + + protected Map> familyMap = + new TreeMap>(Bytes.BYTES_COMPARATOR); + + public MutationProxy addColumn(final byte[] family, + final byte[] qualifier, final byte[] value) { + return addColumn(family, qualifier, KeyValue.TIMESTAMP_NOW, value); + } + + public MutationProxy addColumn(final byte[] family, + final byte[] qualifier, final long ts, final byte [] value) { + List list = familyMap.get(family); + if(list == null) { + list = new ArrayList(0); + familyMap.put(family, list); + } + list.add(new KeyValue(row_, family, + (qualifier == null ? HBaseClient.EMPTY_ARRAY : qualifier), + ts, (value == null ? HBaseClient.EMPTY_ARRAY : value))); + return this; + } + + public Durability getDurability() { + return durability_; + } + + public void setDurability(final int durability) { + this.durability_ = Durability.values()[durability]; + } + + public boolean isBufferable() { + return bufferable_; + } + + public void setBufferable(boolean bufferable) { + this.bufferable_ = bufferable; + } + + public Map> getFamilyMap() { + return familyMap; + } + + public abstract Mutation toHBaseMutation(); + + public abstract void send(final HBaseClient client, + final MutationCallbackHandler cbh); +} diff --git a/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/PutProxy.java b/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/PutProxy.java new file mode 100644 index 000000000000..518591cb5074 --- /dev/null +++ b/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/PutProxy.java @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.hadoop.hbase.jni; + +import java.util.List; +import java.util.Map; + +import org.apache.hadoop.hbase.client.Durability; +import org.apache.hadoop.hbase.client.Mutation; +import org.apache.hadoop.hbase.client.Put; +import org.hbase.async.HBaseClient; +import org.hbase.async.KeyValue; +import org.hbase.async.PutRequest; + +public class PutProxy extends MutationProxy { + public PutProxy(byte[] row) { + this.row_ = row; + } + + @Override + public Mutation toHBaseMutation() { + final Put put = new Put(row_); + put.setDurability(durability_); + for (byte[] family : familyMap.keySet()) { + final List kvList = familyMap.get(family); + final int numKVs = kvList.size(); + for (int i = 0; i < numKVs; i++) { + KeyValue kv = kvList.get(i); + put.add(kv.family(), kv.qualifier(), kv.timestamp(), kv.value()); + } + } + return put; + } + + @Override + public void send(final HBaseClient client, + final MutationCallbackHandler cbh) { + final Map> familyMap = getFamilyMap(); + final int numFamilies = familyMap.size(); + final byte[][] families = new byte[numFamilies][]; + final byte[][][] qualifiers = new byte[numFamilies][][]; + final byte[][][] values = new byte[numFamilies][][]; + final long[][] timestamps = new long[numFamilies][]; + int idx = 0; + for (byte[] family : familyMap.keySet()) { + families[idx] = family; + final List kvList = familyMap.get(family); + final int numKVs = kvList.size(); + qualifiers[idx] = new byte[numKVs][]; + values[idx] = new byte[numKVs][]; + timestamps[idx] = new long[numKVs]; + for (int i = 0; i < numKVs; i++) { + KeyValue kv = kvList.get(i); + qualifiers[idx][i] = kv.qualifier(); + values[idx][i] = kv.value(); + timestamps[idx][i] = kv.timestamp(); + } + idx++; + } + final PutRequest put = new PutRequest(getTable(), + getRow(), families, qualifiers, values, timestamps); + // set attributes + put.setDurable(getDurability() != Durability.SKIP_WAL); + put.setBufferable(isBufferable()); + // hand over and attach callback + client.put(put).addBoth(cbh); + } +} diff --git a/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/ResultProxy.java b/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/ResultProxy.java new file mode 100644 index 000000000000..cf7c29a511b0 --- /dev/null +++ b/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/ResultProxy.java @@ -0,0 +1,136 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.hadoop.hbase.jni; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; + +import org.hbase.async.Bytes; +import org.hbase.async.HBaseClient; +import org.hbase.async.KeyValue; + +public class ResultProxy { + + protected ArrayList kvList; + private byte[] namespace; + private byte[] table; + + public static final Comparator KV_COMPARATOR = + new Comparator() { + @Override + public int compare(KeyValue o1, KeyValue o2) { + int d; + if ((d = Bytes.memcmp(o1.key(), o2.key())) != 0) { + return d; + } else if ((d = Bytes.memcmp(o1.family(), o2.family())) != 0) { + return d; + } else if ((d = Bytes.memcmp(o1.qualifier(), o2.qualifier())) != 0) { + return d; + } else if ((d = Long.signum(o2.timestamp() - o1.timestamp())) != 0) { + return d; + } else { + d = Bytes.memcmp(o1.value(), o2.value()); + } + return d; + } + }; + + public ResultProxy(byte[] table, byte[] namespace, ArrayList kvList) { + this.table = table; + this.namespace = namespace; + this.kvList = kvList; + } + + byte[] getRowKey() { + return kvList == null || kvList.size() == 0 + ? null : kvList.get(0).key(); + } + + byte[] getFamily(int cellIndex) { + if (kvList == null || kvList.size() <= cellIndex) { + throw new IndexOutOfBoundsException(); + } + return kvList.get(cellIndex).family(); + } + + byte[] getQualifier(int cellIndex) { + if (kvList == null || kvList.size() <= cellIndex) { + throw new IndexOutOfBoundsException(); + } + return kvList.get(cellIndex).qualifier(); + } + + byte[] getValue(int cellIndex) { + if (kvList == null || kvList.size() <= cellIndex) { + throw new IndexOutOfBoundsException(); + } + return kvList.get(cellIndex).value(); + } + + long getTS(int cellIndex) { + if (kvList == null || kvList.size() <= cellIndex) { + throw new IndexOutOfBoundsException(); + } + return kvList.get(cellIndex).timestamp(); + } + + int getCellCount() { + return kvList != null ? kvList.size() : 0; + } + + byte[] getNamespace() { + return namespace; + } + + int getNamespaceLength() { + return namespace == null ? 0 : namespace.length; + } + + byte[] getTable() { + return table; + } + + int getTableLength() { + return table == null ? 0 : table.length; + } + + ArrayList getKvList() { + return kvList; + } + + int indexOf(final byte [] family, final byte [] qualifier) { + KeyValue searchTerm = new KeyValue( + getRowKey(), family, qualifier, HBaseClient.EMPTY_ARRAY); + int pos = Collections.binarySearch(kvList, searchTerm, KV_COMPARATOR); + // never will exact match + if (pos < 0) { + pos = (pos+1) * -1; + // pos is now insertion point + } + if (pos == kvList.size()) { + return -1; // doesn't exist + } + + KeyValue kv = kvList.get(pos); + return (Bytes.equals(family, kv.family()) + && Bytes.equals(qualifier, kv.qualifier())) + ? pos : -1; + } +} diff --git a/hbase-native-client/src/async/hbase_connection.cc b/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/RowProxy.java similarity index 54% rename from hbase-native-client/src/async/hbase_connection.cc rename to hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/RowProxy.java index 57fa4f53c0c2..9d2f5e149151 100644 --- a/hbase-native-client/src/async/hbase_connection.cc +++ b/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/RowProxy.java @@ -16,22 +16,45 @@ * limitations under the License. * */ +package org.apache.hadoop.hbase.jni; -#include "async/hbase_connection.h" +import org.hbase.async.KeyValue; -#include "core/connection.h" -#include "core/hbase_types.h" +public abstract class RowProxy { + protected byte [] row_ = null; + protected byte [] table_ = null; + protected byte [] namespace_ = null; + protected long ts_ = KeyValue.TIMESTAMP_NOW; -extern "C" { -int32_t hb_connection_create(hb_connection_t * connection_ptr, - hb_connection_attr_t connection_attr) { - (*connection_ptr) = reinterpret_cast(new Connection()); - if ((*connection_ptr) == NULL) - return -1; - return 0; -} -int32_t hb_connection_destroy(hb_connection_t connection) { - free(connection); - return 0; + public byte[] getRow() { + return row_; + } + + public void setRow(byte[] row) { + this.row_ = row; + } + + public byte[] getTable() { + return table_; + } + + public void setTable(byte[] table) { + this.table_ = table; + } + + public byte[] getNamespace() { + return namespace_; + } + + public void setNamespace(byte[] namespace) { + this.namespace_ = namespace; + } + + public long getTS() { + return ts_; + } + + public void setTS(long ts) { + this.ts_ = ts; + } } -} // extern "C" diff --git a/hbase-native-client/src/core/hbase_connection_attr.cc b/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/ScannerCloseCallback.java similarity index 56% rename from hbase-native-client/src/core/hbase_connection_attr.cc rename to hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/ScannerCloseCallback.java index 61940e829088..d2b8628f0bf5 100644 --- a/hbase-native-client/src/core/hbase_connection_attr.cc +++ b/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/ScannerCloseCallback.java @@ -16,26 +16,30 @@ * limitations under the License. * */ +package org.apache.hadoop.hbase.jni; -#include "core/hbase_connection_attr.h" +import com.stumbleupon.async.Callback; -#include "core/hbase_macros.h" -#include "core/hbase_types.h" -#include "core/connection_attr.h" +public class ScannerCloseCallback implements Callback { -extern "C" { -int32_t hb_connection_attr_create(hb_connection_attr_t * attr_ptr) { - (*attr_ptr) = new ConnectionAttr(); - return (attr_ptr == NULL)?-1:0; -} + private long callback_; + private long scanner_; + private long extra_; -int32_t hb_connection_attr_set_zk_quorum(hb_connection_t connection, - char * zk_quorum) { - return 0; -} + public ScannerCloseCallback(long callback, long scanner, long extra) { + this.callback_ = callback; + this.scanner_ = scanner; + this.extra_ = extra; + } -int32_t hb_connection_attr_set_zk_root(hb_connection_t connection, - char * zk_root) { - return 0; -} + @Override + public R call(T arg) throws Exception { + Throwable t = null; + if (arg instanceof Throwable) { + t = (Throwable) arg; + } + CallbackHandlers.scannerCloseCallBack(t, + callback_, scanner_, extra_); + return null; + } } diff --git a/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/ScannerNextCallback.java b/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/ScannerNextCallback.java new file mode 100644 index 000000000000..4a88d1439e1c --- /dev/null +++ b/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/ScannerNextCallback.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.hadoop.hbase.jni; + +import java.util.ArrayList; + +import org.hbase.async.KeyValue; + +import com.stumbleupon.async.Callback; + +public class ScannerNextCallback implements Callback { + + private long callback_; + private long scanner_; + private long extra_; + private ScannerProxy proxy_; + + public ScannerNextCallback(ScannerProxy proxy, long callback, long scanner, long extra) { + this.callback_ = callback; + this.scanner_ = scanner; + this.extra_ = extra; + proxy_ = proxy; + } + + @Override + public R call(T arg) throws Exception { + int numRows = 0; + Throwable t = null; + ResultProxy[] results = null; + if (arg instanceof Throwable) { + t = (Throwable) arg; + } else if (arg != null && arg instanceof ArrayList) { + @SuppressWarnings("unchecked") + ArrayList> rows = (ArrayList>) arg; + numRows = rows.size(); + results = new ResultProxy[numRows]; + for (int i = 0; i < numRows; ++i) { + results[i] = new ResultProxy( + proxy_.getTable(), proxy_.getNamespace(), rows.get(i)); + } + } + CallbackHandlers.scanNextCallBack(t, + callback_, scanner_, results, numRows, extra_); + return null; + } + +} diff --git a/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/ScannerProxy.java b/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/ScannerProxy.java new file mode 100644 index 000000000000..26a8f5834be1 --- /dev/null +++ b/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/ScannerProxy.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.hadoop.hbase.jni; + +import java.io.IOException; +import java.util.ArrayList; + +import org.hbase.async.KeyValue; +import org.hbase.async.Scanner; + +public class ScannerProxy extends RowProxy { + + private ClientProxy clientProxy_ = null; + private Scanner scanner_ = null; + private byte[] endRow_ = null; + private int maxNumRows_ = -1; + private int numVersions_ = -1; + + ScannerProxy(ClientProxy clientProxy) { + this.clientProxy_ = clientProxy; + } + + private void initScanner() { + scanner_ = clientProxy_.newScanner(getTable()); + if (row_ != null) { + scanner_.setStartKey(row_); + } + if (endRow_ != null) { + scanner_.setStopKey(endRow_); + } + if (maxNumRows_ != -1) { + scanner_.setMaxNumRows(maxNumRows_); + } + if (numVersions_ != -1) { + scanner_.setMaxVersions(numVersions_); + } + } + + public void next(final long callback, final long scanner, + final long extra) throws IOException { + if (scanner_ == null) { + initScanner(); + } + scanner_.nextRows().addBoth( + new ScannerNextCallback>>( + this, callback, scanner, extra)); + } + + public void close(final long callback, final long scanner, + final long extra) throws IOException { + scanner_.close().addBoth( + new ScannerCloseCallback( + callback, scanner, extra)); + } + + public void setMaxNumRows(int maxNumRows) { + maxNumRows_ = maxNumRows; + } + + public void setNumVersions(int numVersions) { + numVersions_ = numVersions; + } + + public void setEndRow(byte[] endRow) { + endRow_ = endRow; + } +} diff --git a/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/TableProxy.java b/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/TableProxy.java new file mode 100644 index 000000000000..a3b7b9f783ee --- /dev/null +++ b/hbase-native-client/src/main/java/org/apache/hadoop/hbase/jni/TableProxy.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.hadoop.hbase.jni; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.client.HTable; +import org.apache.hadoop.hbase.client.Put; +import org.apache.hadoop.hbase.client.Row; + +public final class TableProxy { + protected HTable table_; + + public TableProxy(Configuration conf, String name) throws IOException { + table_ = new HTable(conf, name); + } + + public void setAutoFlush(boolean autoFlush) { + table_.setAutoFlushTo(autoFlush); + } + + public void close() throws IOException { + table_.close(); + } + + public void flushCommits() throws IOException { + table_.flushCommits(); + } + + public void put(final List putProxies) throws IOException { + List puts = new ArrayList(putProxies.size()); + for (PutProxy putProxy : putProxies) { + puts.add((Put) putProxy.toHBaseMutation()); + } + table_.put(puts); + } + + @Deprecated + public Object[] batch(final List mutations) + throws InterruptedException, IOException { + List actions = new ArrayList(mutations.size()); + for (MutationProxy mutation : mutations) { + actions.add(mutation.toHBaseMutation()); + } + return table_.batch(actions); + } + +} diff --git a/hbase-native-client/src/main/native/common/hbase_consts.cc b/hbase-native-client/src/main/native/common/hbase_consts.cc new file mode 100644 index 000000000000..2f654e164d45 --- /dev/null +++ b/hbase-native-client/src/main/native/common/hbase_consts.cc @@ -0,0 +1,34 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#include "hbase_consts.h" + +namespace hbase { + +const std::string HConstants::EMPTY_STRING; + +const char *HConstants::ZK_CLIENT_PORT = "hbase.zookeeper.property.clientPort"; + +const char *HConstants::ZK_ROOT_NODE = "zookeeper.znode.parent"; + +const char *HConstants::ZK_ENSEMBLE = "hbase.zookeeper.ensemble"; + +const char *HConstants::ZK_QUORUM = "hbase.zookeeper.quorum"; + +const char *HConstants::ZK_DEFAULT_PORT = "2181"; + +} /* namespace hbase */ diff --git a/hbase-native-client/src/main/native/common/hbase_consts.h b/hbase-native-client/src/main/native/common/hbase_consts.h new file mode 100644 index 000000000000..00a794532aab --- /dev/null +++ b/hbase-native-client/src/main/native/common/hbase_consts.h @@ -0,0 +1,38 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef HBASE_COMMON_CONSTS_H__ +#define HBASE_COMMON_CONSTS_H__ + +#include + +namespace hbase { + +class HConstants { + public: + static const std::string EMPTY_STRING; + + static const char *ZK_CLIENT_PORT; + static const char *ZK_ROOT_NODE; + static const char *ZK_ENSEMBLE; + static const char *ZK_QUORUM; + static const char *ZK_DEFAULT_PORT; +}; + +} /* namespace hbase */ + +#endif /* HBASE_COMMON_CONSTS_H__ */ diff --git a/hbase-native-client/src/main/native/common/hbase_log.cc b/hbase-native-client/src/main/native/common/hbase_log.cc new file mode 100644 index 000000000000..53b8addbcb6c --- /dev/null +++ b/hbase-native-client/src/main/native/common/hbase_log.cc @@ -0,0 +1,207 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#line 19 "hbase_log.cc" // ensures short filename in logs. + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#line __LINE__ "hbase_log.cc" + +#define TIME_NOW_BUF_SIZE 1024 + +#define FORMAT_LOG_BUF_SIZE 4096 + +#define LOGSTREAM getLogStream() + +#ifdef THREADED + +static pthread_key_t time_now_buffer; + +static pthread_key_t format_log_msg_buffer; + +void +freeBuffer(void *p) { + if(p) free(p); +} + +__attribute__((constructor)) void prepareTSDKeys() { + pthread_key_create(&time_now_buffer, freeBuffer); + pthread_key_create(&format_log_msg_buffer, freeBuffer); +} + +char* +getTSData(pthread_key_t key, int size) { + char *p = (char*)pthread_getspecific(key); + if(p == 0) { + int res; + p = (char*)calloc(1, size); + res = pthread_setspecific(key, p); + if(res != 0) { + fprintf(stderr,"Failed to set TSD key: %d", res); + } + } + return p; +} + +char * +get_time_buffer() { + return getTSData(time_now_buffer, TIME_NOW_BUF_SIZE); +} + +char * +get_format_log_buffer() { + return getTSData(format_log_msg_buffer, FORMAT_LOG_BUF_SIZE); +} + +#else // #ifdef THREADED + +char * +get_time_buffer() { + static char buf[TIME_NOW_BUF_SIZE]; + return buf; +} + +char * +get_format_log_buffer() { + static char buf[FORMAT_LOG_BUF_SIZE]; + return buf; +} + +#endif // #ifdef THREADED + +static HBaseLogLevel hbLogLevel = HBASE_LOG_LEVEL_INFO; + +static FILE *logStream = 0; +FILE *getLogStream() { + if(logStream == 0) + logStream = stderr; + return logStream; +} + +static const char * +time_now(char *now_str) { + struct timeval tv; + struct tm lt; + time_t now = 0; + size_t len = 0; + + gettimeofday(&tv, 0); + now = tv.tv_sec; + localtime_r(&now, <); + + // clone the format used by log4j ISO8601DateFormat + // specifically: "yyyy-MM-dd HH:mm:ss,SSS" + len = strftime(now_str, TIME_NOW_BUF_SIZE, + "%Y-%m-%d %H:%M:%S", <); + len += snprintf(now_str + len, + TIME_NOW_BUF_SIZE - len, + ",%03d", (int)(tv.tv_usec/1000)); + return now_str; +} + +#ifdef __cplusplus +extern "C" { +#endif + +static const char *DBG_LEVEL_STR[] = { + "?????", "FATAL", "ERROR", + "WARN ", "INFO ", "DEBUG", "TRACE" +}; + +HBASE_API void +hb_log_message( + HBaseLogLevel curLevel, + int line, + const char *fileName, + const char *funcName, + const char *message) { + if (curLevel < HBASE_LOG_LEVEL_FATAL + || curLevel > HBASE_LOG_LEVEL_TRACE) { + curLevel = HBASE_LOG_LEVEL_INVALID; + } + static pid_t pid = 0; + if (pid==0) { + pid = getpid(); + } +#ifndef THREADED + fprintf(LOGSTREAM, "%s %s %d@%s(%s#%d): %s\n", + time_now(get_time_buffer()), DBG_LEVEL_STR[curLevel], + pid, fileName, funcName, line, message); +#else + fprintf(LOGSTREAM, "%s %s %d(0x%lx)@%s(%s#%d): %s\n", + time_now(get_time_buffer()), DBG_LEVEL_STR[curLevel], pid, + (unsigned long int)pthread_self(), fileName, funcName, line, message); +#endif + fflush(LOGSTREAM); +} + +HBASE_API const char* +hb_format_log_message(const char *format, ...) { + va_list va; + char *buf = get_format_log_buffer(); + if(!buf) { + return "format_log_message: Unable to allocate memory buffer"; + } + + va_start(va, format); + int msgLen = vsnprintf(buf, FORMAT_LOG_BUF_SIZE, format, va); + if (msgLen >= FORMAT_LOG_BUF_SIZE) { + // indicate that the log was truncated. + snprintf(buf+(FORMAT_LOG_BUF_SIZE-11), 11, "...(%05d)", + (msgLen-FORMAT_LOG_BUF_SIZE+10)); + } + va_end(va); + return buf; +} + +HBASE_API void +hb_log_set_stream(FILE *stream) { + logStream = stream; +} + +HBASE_API HBaseLogLevel +hb_log_get_level() { + return hbLogLevel; +} + +HBASE_API void +hb_log_set_level(HBaseLogLevel level) { + if(level == 0) { + // disable logging (unit tests do this) + hbLogLevel = (HBaseLogLevel)0; + return; + } + if(level >= HBASE_LOG_LEVEL_FATAL + && level <= HBASE_LOG_LEVEL_TRACE) { + hbLogLevel = level; + } else { + HBASE_LOG_ERROR("Invalid log level: %d", (int32_t)level); + } +} + +#ifdef __cplusplus +} +#endif diff --git a/hbase-native-client/src/main/native/common/hbase_macros.h b/hbase-native-client/src/main/native/common/hbase_macros.h new file mode 100644 index 000000000000..9470c29baa2f --- /dev/null +++ b/hbase-native-client/src/main/native/common/hbase_macros.h @@ -0,0 +1,67 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef HBASE_COMMON_MACROS_H__ +#define HBASE_COMMON_MACROS_H__ + +#include + +#ifdef LIKELY +#undef LIKELY +#endif + +#ifdef UNLIKELY +#undef UNLIKELY +#endif + +#if __GNUC__ >= 3 + #define EXPECT(expr, value) __builtin_expect((expr), (value)) +#else + #define EXPECT(expr, value) (expr) +#endif + +#ifndef TRUE + #define TRUE 1 +#endif +#ifndef FALSE + #define FALSE 0 +#endif + +#define LIKELY(expr) EXPECT((expr), TRUE) +#define UNLIKELY(expr) EXPECT((expr), FALSE) + +#define RETURN_IF_INVALID_PARAM(stmt, ...) \ + if (UNLIKELY(stmt)){ \ + HBASE_LOG_ERROR(__VA_ARGS__); \ + return EINVAL; \ + } + +#define CALLBACK_IF_INVALID_PARAM(stmt, call_back, \ + client, operation, result, extra, ...) \ + if (UNLIKELY(stmt)){ \ + HBASE_LOG_ERROR(__VA_ARGS__); \ + call_back(EINVAL, client, operation, result, extra); \ + return 0; \ + } + +#define RETURN_IF_ERROR(stmt) \ + do { \ + Status __status__ = (stmt); \ + if (UNLIKELY(!__status__.ok())) return __status__; \ + } while (false) + +#endif /* HBASE_COMMON_MACROS_H__ */ diff --git a/hbase-native-client/src/main/native/common/hbase_msgs.cc b/hbase-native-client/src/main/native/common/hbase_msgs.cc new file mode 100644 index 000000000000..dc45916714fc --- /dev/null +++ b/hbase-native-client/src/main/native/common/hbase_msgs.cc @@ -0,0 +1,147 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#include + +#include "hbase_msgs.h" + +namespace hbase { + +const char *Msgs::ZK_PORT_INVALID = + "Invalid port number '%s' specified in zookeeper ensemble '%s'."; + +const char *Msgs::ERR_CONN_NULL = "'hb_connection_t' is NULL."; + +const char *Msgs::ERR_CONNPTR_NULL = "'hb_connection_t*' is NULL."; + +const char *Msgs::ERR_ADMIN_NULL = "'hb_admin_t' is NULL."; + +const char *Msgs::ERR_ADMIN_PTR_NULL = "'hb_admin_t*' is NULL."; + +const char *Msgs::ERR_CLIENT_NULL = "'hb_client_t' is NULL."; + +const char *Msgs::ERR_CLIENTPTR_NULL = "'hb_client_t*' is NULL."; + +const char *Msgs::ERR_TBL_NAME_NULL = "'tableName' is NULL."; + +const char *Msgs::ERR_HTBL_NULL = "'hb_table_t' is NULL."; + +const char *Msgs::ERR_HTBLPTR_NULL = "'hb_table_t*' is NULL."; + +const char *Msgs::ERR_TBLPTR_NULL = "'table_ptr' is NULL."; + +const char *Msgs::ERR_TBL_LENPTR_NULL = "'table_length_ptr' is NULL."; + +const char *Msgs::ERR_TBL_NULL = "'table' is NULL."; + +const char *Msgs::ERR_TBL_LEN = "'table_len' %d is <= 0."; + +const char *Msgs::ERR_START_ROW_NULL = "'start_row' is NULL."; + +const char *Msgs::ERR_START_ROWL_LEN = "'start_row_len' %d is <= 0."; + +const char *Msgs::ERR_END_ROW_NULL = "'end_row' is NULL."; + +const char *Msgs::ERR_END_ROWL_LEN = "'end_row_len' %d is <= 0."; + +const char *Msgs::ERR_FAMILIES_NULL = "'families[]' is NULL."; + +const char *Msgs::ERR_FAMILY_NULL = "'family' is NULL."; + +const char *Msgs::ERR_FAMILY_LEN = "'family_len' %d is <= 0."; + +const char *Msgs::ERR_COLDESC_NULL = "'hb_columndesc' is NULL."; + +const char *Msgs::ERR_NUM_FAMILIES = "'numFamilies' %d is <= 0."; + +const char *Msgs::ERR_MAX_VERSIONS = "'max_versions' is <= 0."; + +const char *Msgs::ERR_MIN_VERSIONS = "'min_versions' is < 0."; + +const char *Msgs::ERR_TTL = "'ttl' is < 0."; + +const char *Msgs::ERR_CELL_NULL = "'hb_cell_t' is NULL."; + +const char *Msgs::ERR_CELLPTR_NULL = "'hb_cell_t*' is NULL."; + +const char *Msgs::ERR_CELL_COUNTPTR_NULL = "'cell_count_ptr' is NULL."; + +const char *Msgs::ERR_KEY_NULL = "'rowkey' is NULL."; + +const char *Msgs::ERR_KEY_LEN = "'rowkey_len' %d is <= 0."; + +const char *Msgs::ERR_KEYPTR_NULL = "'key_ptr' is NULL."; + +const char *Msgs::ERR_KEY_LENPTR = "'key_length_ptr' is NULL."; + +const char *Msgs::ERR_QUAL_NULL = "'qualifier' is NULL."; + +const char *Msgs::ERR_QUAL_LEN = "'qualifier_len' %d is <= 0."; + +const char *Msgs::ERR_VALUE_NULL = "'value' is NULL."; + +const char *Msgs::ERR_VALUE_LEN = "'value_len' %d is <= 0."; + +const char *Msgs::ERR_DEL_NULL = "'hb_delete_t' is NULL."; + +const char *Msgs::ERR_DELPTR_NULL = "'hb_delete_t*' is NULL."; + +const char *Msgs::ERR_GET_NULL = "'hb_get_t' is NULL."; + +const char *Msgs::ERR_GETPTR_NULL = "'hb_get_t*' is NULL."; + +const char *Msgs::ERR_RESULT_NULL = "'hb_result_t' is NULL."; + +const char *Msgs::ERR_RESULTPTR_NULL = "'hb_result_t*' is NULL."; + +const char *Msgs::ERR_PUT_NULL = "'hb_put_t' is NULL."; + +const char *Msgs::ERR_PUTPTR_NULL = "'hb_put_t*' is NULL."; + +const char *Msgs::ERR_MUTATION_NULL = "'hb_mutation_t' is NULL."; + +const char *Msgs::ERR_MUTATIONPTR_NULL = "'hb_mutation_t*' is NULL."; + +const char *Msgs::ERR_MUTATIONS_NULL = "'hb_mutation_t[]' is NULL."; + +const char *Msgs::ERR_NUM_MUTATIONS = "'num_mutations' %d is <= 0."; + +const char *Msgs::ERR_PUTS_NULL = "'hb_put_t[]' is NULL."; + +const char *Msgs::ERR_NUM_PUTS = "'num_puts' %d is <= 0."; + +const char *Msgs::ERR_TIMESTAMP1 = "'timestamp' "PRIu64" is <= 0."; + +const char *Msgs::ERR_TIMESTAMP2 = "'timestamp' "PRIu64" is <= 0 and != -1."; + +const char *Msgs::ERR_NUM_VERSIONS = "'num_versions' is <= 0."; + +const char *Msgs::ERR_TABLE_ALREADY_DISABLED = + "DisableTable() called for '%s' which is already disabled."; + +const char *Msgs::ERR_TABLE_ALREADY_ENABLED = + "EnableTable() called for '%s' which is already enabled."; + +const char *Msgs::ERR_SCANNER_NULL = "'hb_scanner_t' is NULL."; + +const char *Msgs::ERR_SCANNERPTR_NULL = "'hb_scanner_t*' is NULL."; + +const char *Msgs::ERR_CACHE_SIZE = "'cache_size' %d is <= 0."; + +const char *Msgs::ERR_SCANNER_OPEN = "Scanner is already open."; + +} // namespace hbase diff --git a/hbase-native-client/src/main/native/common/hbase_msgs.h b/hbase-native-client/src/main/native/common/hbase_msgs.h new file mode 100644 index 000000000000..e26978743424 --- /dev/null +++ b/hbase-native-client/src/main/native/common/hbase_msgs.h @@ -0,0 +1,115 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef HBASE_COMMON_MSGS_H_ +#define HBASE_COMMON_MSGS_H_ + +namespace hbase { + +class Msgs { +public: + static const char *ZK_PORT_INVALID; + + static const char *ERR_CONN_NULL; + static const char *ERR_CONNPTR_NULL; + + static const char *ERR_ADMIN_NULL; + static const char *ERR_ADMIN_PTR_NULL; + + static const char *ERR_CLIENT_NULL; + static const char *ERR_CLIENTPTR_NULL; + + static const char *ERR_TBL_NULL; + static const char *ERR_TBL_LEN; + static const char *ERR_TBL_NAME_NULL; + + static const char *ERR_START_ROW_NULL; + static const char *ERR_START_ROWL_LEN; + + static const char *ERR_END_ROW_NULL; + static const char *ERR_END_ROWL_LEN; + + static const char *ERR_TBLPTR_NULL; + static const char *ERR_TBL_LENPTR_NULL; + + static const char *ERR_KEYPTR_NULL; + static const char *ERR_KEY_LENPTR; + + static const char *ERR_HTBL_NULL; + static const char *ERR_HTBLPTR_NULL; + + static const char *ERR_FAMILY_NULL; + static const char *ERR_FAMILY_LEN; + static const char *ERR_FAMILIES_NULL; + static const char *ERR_NUM_FAMILIES; + static const char *ERR_COLDESC_NULL; + + static const char *ERR_MAX_VERSIONS; + static const char *ERR_MIN_VERSIONS; + static const char *ERR_TTL; + + static const char *ERR_CELL_NULL; + static const char *ERR_CELLPTR_NULL; + static const char *ERR_CELL_COUNTPTR_NULL; + + static const char *ERR_KEY_NULL; + static const char *ERR_KEY_LEN; + + static const char *ERR_DEL_NULL; + static const char *ERR_DELPTR_NULL; + + static const char *ERR_GET_NULL; + static const char *ERR_GETPTR_NULL; + + static const char *ERR_RESULT_NULL; + static const char *ERR_RESULTPTR_NULL; + + static const char *ERR_PUT_NULL; + static const char *ERR_PUTPTR_NULL; + + static const char *ERR_PUTS_NULL; + static const char *ERR_NUM_PUTS; + + static const char *ERR_MUTATION_NULL; + static const char *ERR_MUTATIONPTR_NULL; + + static const char *ERR_MUTATIONS_NULL; + static const char *ERR_NUM_MUTATIONS; + + static const char *ERR_VALUE_NULL; + static const char *ERR_VALUE_LEN; + + static const char *ERR_QUAL_NULL; + static const char *ERR_QUAL_LEN; + + static const char *ERR_TIMESTAMP1; + static const char *ERR_TIMESTAMP2; + + static const char *ERR_NUM_VERSIONS; + + static const char *ERR_TABLE_ALREADY_DISABLED; + static const char *ERR_TABLE_ALREADY_ENABLED; + + static const char *ERR_SCANNER_NULL; + static const char *ERR_SCANNERPTR_NULL; + static const char *ERR_CACHE_SIZE; + static const char *ERR_SCANNER_OPEN; +}; + +} // namespace hbase + +#endif /* HBASE_COMMON_MSGS_H_ */ diff --git a/hbase-native-client/src/main/native/common/hbase_status.cc b/hbase-native-client/src/main/native/common/hbase_status.cc new file mode 100644 index 000000000000..4a6e5664b7ce --- /dev/null +++ b/hbase-native-client/src/main/native/common/hbase_status.cc @@ -0,0 +1,41 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#include +#include +#include + +#include + +#include "hbase_status.h" + +namespace hbase { + +const Status Status::Success(0); +const Status Status::EInvalid(EINVAL); +const Status Status::ENoEntry(ENOENT); +const Status Status::EAgain(EAGAIN); +const Status Status::ENoBufs(ENOBUFS); +const Status Status::EBusy(EBUSY); +const Status Status::ENoMem(ENOMEM); +const Status Status::ENoSys(ENOSYS); +const Status Status::ERange(ERANGE); + +const Status Status::HBaseInternalError(HBASE_INTERNAL_ERR); +const Status Status::HBaseTableDisabled(HBASE_TABLE_DISABLED); + +} /* namespace hbase */ diff --git a/hbase-native-client/src/main/native/common/hbase_status.h b/hbase-native-client/src/main/native/common/hbase_status.h new file mode 100644 index 000000000000..f5b307d49797 --- /dev/null +++ b/hbase-native-client/src/main/native/common/hbase_status.h @@ -0,0 +1,59 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef HBASE_COMMON_STATUS_H__ +#define HBASE_COMMON_STATUS_H__ + +#include +#include + +#include "hbase_macros.h" + +namespace hbase { + +class Status { +public: + Status(int32_t code, const char *msg="") + : code_(code), msg_(msg) { } + + void SetCode(int32_t code) {code_ = code;} + + int32_t GetCode() { return code_; } + + bool ok() const { return code_ == 0; } + + static const Status Success; + static const Status EInvalid; + static const Status ENoEntry; + static const Status ENoMem; + static const Status ENoSys; + static const Status ERange; + static const Status EAgain; + static const Status ENoBufs; + static const Status EBusy; + + static const Status HBaseInternalError; + static const Status HBaseTableDisabled; + +private: + int32_t code_; + std::string msg_; +}; + +} /* namespace hbase */ + +#endif /* HBASE_COMMON_STATUS_H__ */ diff --git a/hbase-native-client/src/main/native/generated/org_apache_hadoop_hbase_jni_CallbackHandlers.h b/hbase-native-client/src/main/native/generated/org_apache_hadoop_hbase_jni_CallbackHandlers.h new file mode 100644 index 000000000000..8052ef8c69a2 --- /dev/null +++ b/hbase-native-client/src/main/native/generated/org_apache_hadoop_hbase_jni_CallbackHandlers.h @@ -0,0 +1,78 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_apache_hadoop_hbase_jni_CallbackHandlers */ + +#ifndef _Included_org_apache_hadoop_hbase_jni_CallbackHandlers +#define _Included_org_apache_hadoop_hbase_jni_CallbackHandlers +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_apache_hadoop_hbase_jni_CallbackHandlers + * Method: mutationCallBack + * Signature: (Ljava/lang/Throwable;JJJLjava/lang/Object;J)V + */ +JNIEXPORT void JNICALL Java_org_apache_hadoop_hbase_jni_CallbackHandlers_mutationCallBack + (JNIEnv *, jclass, jthrowable, jlong, jlong, jlong, jobject, jlong); + +/* + * Class: org_apache_hadoop_hbase_jni_CallbackHandlers + * Method: getCallBack + * Signature: (Ljava/lang/Throwable;JJJLjava/lang/Object;J)V + */ +JNIEXPORT void JNICALL Java_org_apache_hadoop_hbase_jni_CallbackHandlers_getCallBack + (JNIEnv *, jclass, jthrowable, jlong, jlong, jlong, jobject, jlong); + +/* + * Class: org_apache_hadoop_hbase_jni_CallbackHandlers + * Method: clientFlushCallBack + * Signature: (Ljava/lang/Throwable;JJJ)V + */ +JNIEXPORT void JNICALL Java_org_apache_hadoop_hbase_jni_CallbackHandlers_clientFlushCallBack + (JNIEnv *, jclass, jthrowable, jlong, jlong, jlong); + +/* + * Class: org_apache_hadoop_hbase_jni_CallbackHandlers + * Method: clientCloseCallBack + * Signature: (Ljava/lang/Throwable;JJJ)V + */ +JNIEXPORT void JNICALL Java_org_apache_hadoop_hbase_jni_CallbackHandlers_clientCloseCallBack + (JNIEnv *, jclass, jthrowable, jlong, jlong, jlong); + +/* + * Class: org_apache_hadoop_hbase_jni_CallbackHandlers + * Method: scannerCloseCallBack + * Signature: (Ljava/lang/Throwable;JJJ)V + */ +JNIEXPORT void JNICALL Java_org_apache_hadoop_hbase_jni_CallbackHandlers_scannerCloseCallBack + (JNIEnv *, jclass, jthrowable, jlong, jlong, jlong); + +/* + * Class: org_apache_hadoop_hbase_jni_CallbackHandlers + * Method: scanNextCallBack + * Signature: (Ljava/lang/Throwable;JJ[Ljava/lang/Object;IJ)V + */ +JNIEXPORT void JNICALL Java_org_apache_hadoop_hbase_jni_CallbackHandlers_scanNextCallBack + (JNIEnv *, jclass, jthrowable, jlong, jlong, jobjectArray, jint, jlong); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/hbase-native-client/src/main/native/include/hbase/admin.h b/hbase-native-client/src/main/native/include/hbase/admin.h new file mode 100644 index 000000000000..0158567f1b87 --- /dev/null +++ b/hbase-native-client/src/main/native/include/hbase/admin.h @@ -0,0 +1,121 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef LIBHBASE_ADMIN_H_ +#define LIBHBASE_ADMIN_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "types.h" + +/** + * Create a new hb_admin. + * All fields are initialized to the defaults. If you want to set + * connection or other properties, set those before calling any + * RPC functions. + */ +HBASE_API int32_t +hb_admin_create( + hb_connection_t connection, + hb_admin_t *admin_ptr); + +/** + * Disconnect the admin releasing any internal objects + * or connections created in the background. + */ +HBASE_API int32_t +hb_admin_destroy( + hb_admin_t admin, + hb_admin_disconnection_cb cb, + void *extra); + +/** + * Checks if a table exists. + * @returns 0 on if the table exist, an error code otherwise. + */ +HBASE_API int32_t +hb_admin_table_exists( + const hb_admin_t admin, /* [in] HBaseClient handle */ + const char *name_space, /* [in] Null terminated namespace, set to NULL + * for default namespace and for 0.94 version */ + const char *table_name); /* [in] Null terminated table name */ + +/** + * Checks if a table is enabled. + * @returns 0 on if the table enabled, HBASE_TABLE_DISABLED if the table + * is disabled or an error code if an error occurs. + */ +HBASE_API int32_t +hb_admin_table_enabled( + const hb_admin_t admin, /* [in] HBaseClient handle */ + const char *name_space, /* [in] Null terminated namespace, set to NULL + * for default namespace and for 0.94 version */ + const char *table_name); /* [in] Null terminated table name */ + +/** + * Creates an HBase table. + * @returns 0 on success, an error code otherwise. + */ +HBASE_API int32_t +hb_admin_table_create( + const hb_admin_t admin, /* [in] HBaseClient handle */ + const char *name_space, /* [in] Null terminated namespace, set to NULL + * for default namespace and for 0.94 version */ + const char *table_name, /* [in] Null terminated table name */ + const hb_columndesc families[], /* [in] Array of Null terminated family names */ + const size_t num_families); /* [in] Number of families */ + +/** + * Disable an HBase table. + * @returns 0 on success, an error code otherwise. + */ +HBASE_API int32_t +hb_admin_table_disable( + const hb_admin_t admin, /* [in] HBaseClient handle */ + const char *name_space, /* [in] Null terminated namespace, set to NULL + * for default namespace and for 0.94 version */ + const char *table_name); /* [in] Null terminated table name */ + +/** + * Enable an HBase table. + * @returns 0 on success, an error code otherwise. + */ +HBASE_API int32_t +hb_admin_table_enable( + const hb_admin_t admin, /* [in] HBaseClient handle */ + const char *name_space, /* [in] Null terminated namespace, set to NULL + * for default namespace and for 0.94 version */ + const char *table_name); /* [in] Null terminated table name */ + +/** + * Deletes an HBase table, disables the table if not already disabled. + * Returns 0 on success, and error code otherwise. + */ +HBASE_API int32_t +hb_admin_table_delete( + const hb_admin_t admin , /* [in] HBaseClient handle */ + const char *name_space, /* [in] Null terminated namespace, set to NULL + * for default namespace and for 0.94 version */ + const char *table_name); /* [in] Null terminated table name */ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* LIBHBASE_ADMIN_H_ */ diff --git a/hbase-native-client/src/main/native/include/hbase/client.h b/hbase-native-client/src/main/native/include/hbase/client.h new file mode 100644 index 000000000000..86bbd34872f1 --- /dev/null +++ b/hbase-native-client/src/main/native/include/hbase/client.h @@ -0,0 +1,66 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef LIBHBASE_CLIENT_H_ +#define LIBHBASE_CLIENT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "types.h" + +/** + * Initializes a handle to hb_client_t which can be passed to other HBase APIs. + * You need to use this method only once per HBase cluster. The returned handle + * is thread safe. + * + * @returns 0 on success, non-zero error code in case of failure. + */ +HBASE_API int32_t +hb_client_create( + hb_connection_t connection, /* [in] hb_connection_t for this client */ + hb_client_t *client_ptr); /* [out] pointer to hb_client_t handle */ + +/** + * Flushes any buffered client-side write operations to HBase. + * The callback will be invoked when everything that was buffered at the time of + * the call has been flushed. + * Note that this doesn't guarantee that ALL outstanding RPCs have completed. + */ +HBASE_API int32_t +hb_client_flush( + hb_client_t client, + hb_client_flush_cb cb, + void *extra); + +/** + * Cleans up hb_client_t handle and release any held resources. + * The callback is called after the connections are closed, but just before the + * client is freed. + */ +HBASE_API int32_t +hb_client_destroy( + hb_client_t client, + hb_client_disconnection_cb cb, + void *extra); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // LIBHBASE_CLIENT_H_ diff --git a/hbase-native-client/src/main/native/include/hbase/coldesc.h b/hbase-native-client/src/main/native/include/hbase/coldesc.h new file mode 100644 index 000000000000..fb7a261b27a3 --- /dev/null +++ b/hbase-native-client/src/main/native/include/hbase/coldesc.h @@ -0,0 +1,83 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef LIBHBASE_COLDESC_H_ +#define LIBHBASE_COLDESC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "types.h" + +/** + * Creates a column family descriptor. + * @returns a handle to an hb_columndesc object or NULL if unsuccessful. + */ +HBASE_API int32_t +hb_coldesc_create( + const byte_t *family, /* [in] Null terminated column family name */ + const size_t family_len, + hb_columndesc *col_desc); + +/** + * Release resources held by column family descriptor. + */ +HBASE_API int32_t +hb_coldesc_destroy( + hb_columndesc col_desc); /* [in] hb_columndesc handle */ + +/** + * Sets the maximum number of cell versions to be retained for the column + * family. Defaults to 3. + */ +HBASE_API int32_t +hb_coldesc_set_maxversions( + hb_columndesc col_desc, /* [in] hb_columndesc handle */ + int32_t max_versions); /* [in] maximum number of versions */ + +/** + * Sets the minimum number of cell versions to be retained for the column + * family. Defaults to 0. + */ +HBASE_API int32_t +hb_coldesc_set_minversions( + hb_columndesc col_desc, /* [in] hb_columndesc handle */ + int32_t min_versions); /* [in] minimum number of versions */ + +/** + * Sets the time-to-live of cell contents, in seconds. Defaults is forever. + */ +HBASE_API int32_t +hb_coldesc_set_ttl( + hb_columndesc col_desc, /* [in] hb_columndesc handle */ + int32_t ttl); /* [in] time-to-live of cell contents, in seconds */ + +/** + * Sets if all values are to keep in the HRegionServer cache. Defaults to + * 0 (false). + */ +HBASE_API int32_t +hb_coldesc_set_inmemory( + hb_columndesc col_desc, /* [in] hb_columndesc handle */ + int32_t inmemory); /* [in] 0 for false, true otherwise */ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // LIBHBASE_COLDESC_H_ diff --git a/hbase-native-client/src/main/native/include/hbase/connection.h b/hbase-native-client/src/main/native/include/hbase/connection.h new file mode 100644 index 000000000000..0cd9d4c42721 --- /dev/null +++ b/hbase-native-client/src/main/native/include/hbase/connection.h @@ -0,0 +1,47 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef LIBHBASE_CONNECTION_H_ +#define LIBHBASE_CONNECTION_H_ + +#include + +#include "types.h" + +/** + * Creates an hb_connection_t instance and initializes its address into + * the passed pointer. + */ +HBASE_API int32_t +hb_connection_create( + const char *zk_quorum, /* [in] NULL terminated, comma separated + * string of Zookeeper servers. e.g. + * ",...". If set to + * NULL, library default will be used */ + const char *zk_root, /* [in] The HBase Zookeeper root z-node. + * If set to NULL, library default will + * be used. */ + hb_connection_t *connection_ptr); /* [out] pointer to hb_connection_t */ + +/** + * Destroy the connection and free all resources allocated at creation time. + */ +HBASE_API int32_t +hb_connection_destroy( + hb_connection_t connection); /* [in] hb_connection_t handle */ + +#endif /* LIBHBASE_CONNECTION_H_ */ diff --git a/hbase-native-client/src/main/native/include/hbase/get.h b/hbase-native-client/src/main/native/include/hbase/get.h new file mode 100644 index 000000000000..0ac37467843b --- /dev/null +++ b/hbase-native-client/src/main/native/include/hbase/get.h @@ -0,0 +1,146 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef LIBHBASE_GET_H_ +#define LIBHBASE_GET_H_ + +#include "types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Creates an hb_get_t object and populate the handle get_ptr. + */ +HBASE_API int32_t +hb_get_create( + const byte_t *rk, /* [in] the row key for this hb_get_t object */ + const size_t rk_len, + hb_get_t *get_ptr); /* [out] handle to an hb_get_t object */ + +/** + * Queues the get request. Callback specified by cb will be called + * on completion. Any buffer(s) attached to the get object can be + * reclaimed only after the callback is received. + */ +HBASE_API int32_t +hb_get_send( + hb_client_t client, + hb_get_t get, + hb_get_cb cb, + void *extra); + +/** + * Sets the table name, required. + */ +HBASE_API int32_t +hb_get_set_table( + hb_get_t get, + const char *table_name, + const size_t table_name_len); + +/** + * @NotYetImplemented + * + * Sets the table namespace (0.96 and later) + */ +HBASE_API int32_t +hb_get_set_namespace( + hb_get_t get, + const char *name_space, + const size_t name_space_len); + +/** + * Release any resource held by hb_get_t object. + */ +HBASE_API int32_t +hb_get_destroy(hb_get_t get); + +/** + * Sets the row key, required. + */ +HBASE_API int32_t +hb_get_set_row( + hb_get_t get, + const byte_t *rk, + const size_t rk_len); + +/** + * Adds a column family and optionally a column qualifier to + * the hb_get_t object, optional. + */ +HBASE_API int32_t +hb_get_add_column( + hb_get_t get, + const byte_t *family, + const size_t family_len, + const byte_t *qualifier, + const size_t qualifier_len); + +/** + * @NotYetImplemented + * + * Optional. Adds a filter to the hb_get_t object. + * + * The filter must be specified using HBase Filter Language. + * Refer to class org.apache.hadoop.hbase.filter.ParseFilter and + * https://issues.apache.org/jira/browse/HBASE-4176 or + * http://hbase.apache.org/book.html#thrift.filter-language for + * language syntax and additional details. + */ +HBASE_API int32_t +hb_get_set_filter( + hb_get_t get, + const char *filter); + +/** + * Optional. Sets maximum number of latest values of each column to be + * fetched. + */ +HBASE_API int32_t +hb_get_set_num_versions( + hb_get_t get, + const int32_t num_versions); + +/** + * @NotYetImplemented + * + * Optional. Only columns with the specified timestamp will be included. + */ +HBASE_API int32_t +hb_get_set_timestamp( + hb_get_t get, + const int64_t ts); + +/** + * @NotYetImplemented + * + * Optional. Only columns with timestamp within the specified range will + * be included. + */ +HBASE_API int32_t +hb_get_set_timerange( + hb_get_t get, + const int64_t min_ts, + const int64_t max_ts); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LIBHBASE_GET_H_ */ diff --git a/hbase-native-client/src/main/native/include/hbase/hbase.h b/hbase-native-client/src/main/native/include/hbase/hbase.h new file mode 100644 index 000000000000..00a9e068c4ec --- /dev/null +++ b/hbase-native-client/src/main/native/include/hbase/hbase.h @@ -0,0 +1,70 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef LIBHBASE_HBASE_H_ +#define LIBHBASE_HBASE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "admin.h" +#include "client.h" +#include "coldesc.h" +#include "connection.h" +#include "get.h" +#include "log.h" +#include "mutations.h" +#include "result.h" +#include "scanner.h" +#include "types.h" + +/* + * This header file describes the APIs and data structures of a C client for + * Apache HBase. + * + * Following conventions are used. + * + * 1. All data types are prefixed with the 'hb_'. + * + * 2. All exported functions are annotated with HBASE_API, prefixed with 'hb_' + * and named using the following convention: + * 'hb___[|]'. + * + * 3. All asynchronous APIs take a callback which is triggered when the request + * completes. This callback can be triggered in the callers thread or another + * thread. To avoid any potential deadlock/starvation, applications should not + * block in the callback routine. + * + * 4. All callbacks take a void pointer for the user to supply their own data + * which is passed when callback is triggered. + * + * 4. Its applications responsibility to free up all the backing data buffers. + * Asynchronous APIs do not make a copy of data buffers hence the ownership + * of these buffers is temporarily transfered to the library until the + * callback is triggered. Application should not modify these buffers while + * they are in flight. + * + * 5. No explicit batching is supported for asynchronous APIs. + * ... + */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LIBHBASE_HBASE_H_ */ diff --git a/hbase-native-client/src/main/native/include/hbase/log.h b/hbase-native-client/src/main/native/include/hbase/log.h new file mode 100644 index 000000000000..30ad7024aad6 --- /dev/null +++ b/hbase-native-client/src/main/native/include/hbase/log.h @@ -0,0 +1,101 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef LIBHBASE_LOG_H_ +#define LIBHBASE_LOG_H_ + +#include + +#include "types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Set the log output level + */ +HBASE_API void +hb_log_set_level(HBaseLogLevel level); + +/** + * By default, the log messages are sent to stderr. Use this function to + * redirect it to another file stream. Setting it to NULL disables logging. + */ +HBASE_API void +hb_log_set_stream(FILE *stream); + +/** + * An application using the HBase APIs could use these macros to direct + * the log messages to the same stream used by HBase libraries. + */ +#define HBASE_LOG_FATAL(...) if(hb_log_get_level() >= HBASE_LOG_LEVEL_FATAL) \ + hb_log_message(HBASE_LOG_LEVEL_FATAL, __LINE__, __FILE__, __func__, \ + hb_format_log_message(__VA_ARGS__)) + +#define HBASE_LOG_ERROR(...) if(hb_log_get_level() >= HBASE_LOG_LEVEL_ERROR) \ + hb_log_message(HBASE_LOG_LEVEL_ERROR, __LINE__, __FILE__, __func__, \ + hb_format_log_message(__VA_ARGS__)) + +#define HBASE_LOG_WARN(...) if(hb_log_get_level() >= HBASE_LOG_LEVEL_WARN) \ + hb_log_message(HBASE_LOG_LEVEL_WARN, __LINE__, __FILE__, __func__, \ + hb_format_log_message(__VA_ARGS__)) + +#define HBASE_LOG_INFO(...) if(hb_log_get_level() >= HBASE_LOG_LEVEL_INFO) \ + hb_log_message(HBASE_LOG_LEVEL_INFO, __LINE__, __FILE__, __func__, \ + hb_format_log_message(__VA_ARGS__)) + +#define HBASE_LOG_DEBUG(...) if(hb_log_get_level() == HBASE_LOG_LEVEL_DEBUG) \ + hb_log_message(HBASE_LOG_LEVEL_DEBUG, __LINE__, __FILE__, __func__, \ + hb_format_log_message(__VA_ARGS__)) + +#define HBASE_LOG_TRACE(...) if(hb_log_get_level() == HBASE_LOG_LEVEL_TRACE) \ + hb_log_message(HBASE_LOG_LEVEL_TRACE, __LINE__, __FILE__, __func__, \ + hb_format_log_message(__VA_ARGS__)) + +#define HBASE_LOG_MSG(level, ...) if(hb_log_get_level() >= level) \ + hb_log_message(level, __LINE__, __FILE__, __func__, \ + hb_format_log_message(__VA_ARGS__)) + +/** + * For internal use. Use one of the macros defined later in this file. + */ +HBASE_API void +hb_log_message( + HBaseLogLevel curLevel, + int line, + const char *fileName, + const char *funcName, + const char *message); + +/** + * For internal use. Use one of the macros defined later in this file. + */ +HBASE_API const char * +hb_format_log_message(const char *format, ...); + +/** + * For internal use. Get the log output level. + */ +HBASE_API HBaseLogLevel +hb_log_get_level(); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LIBHBASE_LOG_H_ */ diff --git a/hbase-native-client/src/main/native/include/hbase/macros.h b/hbase-native-client/src/main/native/include/hbase/macros.h new file mode 100644 index 000000000000..5bb713d61a25 --- /dev/null +++ b/hbase-native-client/src/main/native/include/hbase/macros.h @@ -0,0 +1,57 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef LIBHBASE_MACROS_H_ +#define LIBHBASE_MACROS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * The following code block define HBASE_API as the tag for exported + * functions. The library should be compiled with symbols visibility + * set to hidden by default and only the exported functions should be + * tagged as HBASE_API. + * + * When building the library on Windows, compile with compiler flag + * "-D_LIBHBASE_IMPLEMENTATION_", whereas when linking application with + * this library, this compiler flag should not be used. + */ +#if defined _WIN32 || defined __CYGWIN__ + #ifdef _LIBHBASE_IMPLEMENTATION_ + #define HBASE_API __declspec(dllexport) + #else + #ifdef USE_STATIC_LIBHBASE + #define HBASE_API + #else + #define HBASE_API __declspec(dllimport) + #endif + #endif +#else + #if __GNUC__ >= 4 + #define HBASE_API __attribute__ ((visibility ("default"))) + #else + #define HBASE_API + #endif +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LIBHBASE_MACROS_H_ */ diff --git a/hbase-native-client/src/main/native/include/hbase/mutations.h b/hbase-native-client/src/main/native/include/hbase/mutations.h new file mode 100644 index 000000000000..4bb294f658c1 --- /dev/null +++ b/hbase-native-client/src/main/native/include/hbase/mutations.h @@ -0,0 +1,228 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef LIBHBASE_MUTATIONS_H_ +#define LIBHBASE_MUTATIONS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "types.h" + +/** + * Creates a structure for put operation and return its handle. + */ +HBASE_API int32_t +hb_put_create( + const byte_t *rowkey, + const size_t rowkey_len, + hb_put_t *put_ptr); + +/** + * Creates a structure for delete operation and return its handle. + */ +HBASE_API int32_t +hb_delete_create( + const byte_t *rowkey, + const size_t rowkey_len, + hb_delete_t *delete_ptr); + +/** + * @NotYetImplemented + * + * Creates a structure for increment operation and return its handle. + */ +HBASE_API int32_t +hb_increment_create( + const byte_t *rowkey, + const size_t rowkey_len, + hb_increment_t *increment_ptr); + +/** + * @NotYetImplemented + * + * Creates an structure for append operation and return its handle. + */ +HBASE_API int32_t +hb_append_create( + const byte_t *rowkey, + const size_t rowkey_len, + hb_append_t *append_ptr); + +/** + * Queue a mutation to go out. These mutations will not be performed + * atomically and can be batched in a non-deterministic way on either + * the server or the client side. + * + * Any buffer attached to the the mutation objects must not be altered + * until the callback has been received. + */ +HBASE_API int32_t +hb_mutation_send( + hb_client_t client, + hb_mutation_t mutation, + hb_mutation_cb cb, + void *extra); + +/** + * Frees up any resource held by the mutation structure. + */ +HBASE_API int32_t +hb_mutation_destroy(hb_mutation_t mutation); + +// Shared setters. +/** + * @NotYetImplemented + * + * Sets the namespace for the mutation (0.96 and later). + */ +HBASE_API int32_t +hb_mutation_set_namespace( + hb_mutation_t mutation, + const char *name_space, + const size_t name_space_len); + +/** + * Sets the table name for the mutation. + */ +HBASE_API int32_t +hb_mutation_set_table( + hb_mutation_t mutation, + const char *table, + const size_t table_len); + +/** + * Sets whether or not this RPC can be buffered on the client side. + * + * Currently only puts and deletes can be buffered. Calling this for + * any other mutation type will return EINVAL. + * + * The default is true. + */ +HBASE_API int32_t +hb_mutation_set_bufferable( + hb_mutation_t mutation, + const bool bufferable); + +/** + * Sets the row key for the mutation. + */ +HBASE_API int32_t +hb_mutation_set_row( + hb_mutation_t mutation, + const byte_t *rowkey, + const size_t rowkey_len); + +/** + * Sets the durability guarantees for the Mutation. + */ +HBASE_API int32_t +hb_mutation_set_durability( + hb_mutation_t mutation, + const hb_durability_t durability); + +/** + * Adds a cell to the put structure. The row key of the cell + * must be same as the row key of the put structure. + */ +HBASE_API int32_t +hb_put_add_cell( + hb_put_t put, + const hb_cell_t *cell); + +/** + * Adds a column (key-value) with latest timestamp to the put. + */ +HBASE_API int32_t +hb_put_add_column( + hb_put_t put, + const byte_t *family, + const size_t family_len, + const byte_t *qualifier, + const size_t qualifier_len, + const byte_t *value, + const size_t value_len); + +/** + * Adds a column (key-value) with the specified timestamp to the put. + */ +HBASE_API int32_t +hb_put_add_ts_column( + hb_put_t put, + const byte_t *family, + const size_t family_len, + const byte_t *qualifier, + const size_t qualifier_len, + const byte_t *value, + const size_t value_len, + const int64_t timestamp); + +/** + * Optional. Set the column criteria for hb_delete_t object. + * Set the qualifier to NULL to delete all columns of a family. + * Only the cells with timestamp less than or equal to the specified + * timestamp are deleted. Set the timestamp to -1 to delete all + * versions of the column. + */ +HBASE_API int32_t +hb_delete_add_column( + hb_delete_t del, + const byte_t *family, + const size_t family_len, + const byte_t *qualifier, + const size_t qualifier_len, + const int64_t timestamp); + +/** + * Optional. Sets the timestamp of the delete row or delete family + * operation. + * This does not override the timestamp of individual columns + * added via hb_delete_add_column(). + */ +HBASE_API int32_t +hb_delete_set_timestamp( + hb_delete_t del, + const int64_t timestamp); + +/** + * @NotYetImplemented + * + * Add a column and the amount by which its value to be incremented + * to the increment operation. + */ +HBASE_API int32_t +hb_increment_add_column( + hb_increment_t incr, + const hb_cell_t *cell, + const int64_t amount); + +/** + * @NotYetImplemented + * + * Add a column for the append operation. + */ +HBASE_API int32_t +hb_append_add_column( + hb_append_t append, + const hb_cell_t *cell); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // LIBHBASE_MUTATIONS_H_ diff --git a/hbase-native-client/src/main/native/include/hbase/result.h b/hbase-native-client/src/main/native/include/hbase/result.h new file mode 100644 index 000000000000..568c94e393cb --- /dev/null +++ b/hbase-native-client/src/main/native/include/hbase/result.h @@ -0,0 +1,124 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef LIBHBASE_RESULT_H_ +#define LIBHBASE_RESULT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "types.h" + +/** + * Returns the row key of this hb_result_t object. + * This buffer is valid until hb_result_destroy() is called. + * Callers should not modify this buffer. + */ +HBASE_API int32_t +hb_result_get_key( + const hb_result_t result, /* [in] */ + const byte_t **key_ptr, /* [out] */ + size_t *key_length_ptr); /* [out] */ + +/** + * Returns the table name of this hb_result_t object. + * This buffer is valid until hb_result_destroy() is called. + * Callers should not modify this buffer. + */ +HBASE_API int32_t +hb_result_get_table( + const hb_result_t result, /* [in] */ + const char **table_ptr, /* [out] */ + size_t *table_length_ptr); /* [out] */ + +/** + * HBase 0.96 or later. + * Returns the namespace of this hb_result_t object. + * This buffer is valid until hb_result_destroy() is called. + * Callers should not modify this buffer. + */ +HBASE_API int32_t +hb_result_get_namespace( + const hb_result_t result, /* [in] */ + const char **namespace_ptr, /* [out] */ + size_t *namespace_length_ptr); /* [out] */ + +/** + * Returns the total number of cells in this hb_result_t object. + */ +HBASE_API int32_t +hb_result_get_cell_count( + const hb_result_t result, /* [in] */ + size_t *cell_count_ptr); /* [out] */ + +/** + * Returns the pointer to a constant hb_cell_t structure with the most recent + * value of the given column. The buffers are valid until hb_result_destroy() + * is called. Callers should not modify these buffers. + * + * @returns 0 if operation succeeds. + * @returns ENOENT if a matching cell is not found. + */ +HBASE_API int32_t +hb_result_get_cell( + const hb_result_t result, /* [in] */ + const byte_t *family, /* [in] */ + const size_t family_len, /* [in] */ + const byte_t *qualifier, /* [in] */ + const size_t qualifier_len, /* [in] */ + const hb_cell_t **cell_ptr); /* [out] */ + +/** + * Returns the pointer to a constant hb_cell_t structure containing the cell + * value at the given 0 based index of the result. The buffers are valid until + * hb_result_destroy() is called. Callers should not modify these buffers. + * + * @returns 0 if operation succeeds. + * @returns ERANGE if the index is outside the bounds. + */ +HBASE_API int32_t +hb_result_get_cell_at( + const hb_result_t result, /* [in] */ + const size_t index, /* [in] */ + const hb_cell_t **cell_ptr); /* [out] */ + +/** + * Returns the array of pointers to constant hb_cell_t structures with the cells + * of the result. The buffers are valid until hb_result_destroy() is called. The + * variable pointed by num_cells_ptr is set to the number of cells in the result. + * + * Calling this function multiple times for the same hb_result_t may return + * the same buffers. Callers should not modify these buffers. + */ +HBASE_API int32_t +hb_result_get_cells( + const hb_result_t result, /* [in] */ + const hb_cell_t ***cells_ptr, /* [out] */ + size_t *num_cells_ptr); /* [out] */ + +/** + * Frees any resources held by the hb_result_t object. + */ +HBASE_API int32_t +hb_result_destroy(hb_result_t result); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LIBHBASE_RESULT_H_*/ diff --git a/hbase-native-client/src/main/native/include/hbase/scanner.h b/hbase-native-client/src/main/native/include/hbase/scanner.h new file mode 100644 index 000000000000..60b5b7b5dbb3 --- /dev/null +++ b/hbase-native-client/src/main/native/include/hbase/scanner.h @@ -0,0 +1,130 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef LIBHBASE_SCANNER_H_ +#define LIBHBASE_SCANNER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "types.h" + +/** + * Creates a client side row scanner. The returned scanner is not thread safe. + * No RPC will be invoked until the call to fetch the next set of rows is made. + * You can set the various attributes of this scanner until that point. + * @returns 0 on success, non-zero error code in case of failure. + */ +HBASE_API int32_t +hb_scanner_create( + hb_client_t client, /* [in] */ + hb_scanner_t *scanner_ptr); /* [out] */ + +/** + * Request the next set of results from the server. You can set the maximum + * number of rows returned by this call using hb_scanner_set_num_max_rows(). + */ +HBASE_API int32_t +hb_scanner_next( + hb_scanner_t scanner, + hb_scanner_cb cb, + void *extra); + +/** + * Close the scanner releasing any local and server side resources held. + * The call back is fired just before the scanner's memory is freed. + */ +HBASE_API int32_t +hb_scanner_destroy( + hb_scanner_t scanner, + hb_scanner_destroy_cb cb, + void *extra); + +/** + * Set the table name for the scanner + */ +HBASE_API int32_t +hb_scanner_set_table( + hb_scanner_t scanner, + const char *table, + const size_t table_length); + +/** + * Set the name space for the scanner (0.96 and above) + */ +HBASE_API int32_t +hb_scanner_set_namespace( + hb_scanner_t scanner, + const char *name_space, + const size_t name_space_length); + +/** + * Specifies the start row key for this scanner (inclusive). + */ +HBASE_API int32_t +hb_scanner_set_start_row( + hb_scanner_t scanner, + const byte_t *start_row, + const size_t start_row_length); + +/** + * Specifies the end row key for this scanner (exclusive). + */ +HBASE_API int32_t +hb_scanner_set_end_row( + hb_scanner_t scanner, + const byte_t *end_row, + const size_t end_row_length); + +/** + * Sets the maximum versions of a column to fetch. + */ +HBASE_API int32_t +hb_scanner_set_num_versions( + hb_scanner_t scanner, + const int8_t num_versions); + +/** + * Sets the maximum number of rows to scan per call to hb_scanner_next(). + */ +HBASE_API int32_t +hb_scanner_set_num_max_rows( + hb_scanner_t scanner, + const size_t cache_size); + +/** + * @NotYetImplemented + * + * Optional. Adds a filter to the hb_scanner_t object. + * + * The filter must be specified using HBase Filter Language. + * Refer to class org.apache.hadoop.hbase.filter.ParseFilter and + * https://issues.apache.org/jira/browse/HBASE-4176 or + * http://hbase.apache.org/book.html#thrift.filter-language for + * language syntax and additional details. + */ +HBASE_API int32_t +hb_scanner_set_filter( + hb_scanner_t scanner, + const char *filter); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LIBHBASE_SCANNER_H_*/ diff --git a/hbase-native-client/src/main/native/include/hbase/types.h b/hbase-native-client/src/main/native/include/hbase/types.h new file mode 100644 index 000000000000..b7f15c238276 --- /dev/null +++ b/hbase-native-client/src/main/native/include/hbase/types.h @@ -0,0 +1,260 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef LIBHBASE_TYPES_H_ +#define LIBHBASE_TYPES_H_ + +#include +#include +#include + +#include "macros.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * HBase ubiquitous byte type + */ +#ifdef byte_t +#undef byte_t +#endif +typedef uint8_t byte_t; + +/** + * Base HBase Cell type. + */ +typedef struct hb_cell_type { + /* row key */ + byte_t *row; + size_t row_len; + + /* column family */ + byte_t *family; + size_t family_len; + + /* column qualifier */ + byte_t *qualifier; + size_t qualifier_len; + + /* column value */ + byte_t *value; + size_t value_len; + + /* timestamp */ + int64_t ts; + + /* for internal use, applications should not set or alter this variable */ + void *private_; +} hb_cell_t; + +#define HBASE_LATEST_TIMESTAMP 0x7fffffffffffffffL + +typedef void *hb_connection_t; +typedef void *hb_client_t; +typedef void *hb_admin_t; + +typedef void *hb_table_t; +typedef void *hb_get_t; +typedef void *hb_result_t; +typedef void *hb_mutation_t; +typedef void *hb_put_t; +typedef void *hb_delete_t; +typedef void *hb_increment_t; +typedef void *hb_append_t; +typedef void *hb_scanner_t; +typedef void *hb_columndesc; + +typedef enum { + DURABILITY_USE_DEFAULT = 0, /* Use column family's default setting */ + DURABILITY_SKIP_WAL = 1, /* Do not write the Mutation to the WAL */ + DURABILITY_ASYNC_WAL = 2, /* Write the Mutation to the WAL asynchronously */ + DURABILITY_SYNC_WAL = 3, /* Write the Mutation to the WAL synchronously */ + DURABILITY_FSYNC_WAL = 4 /* Write the Mutation to the WAL synchronously and force + * the entries to disk. (Note: this is currently not + * supported and will behave identical to SYNC_WAL) + * See https://issues.apache.org/jira/browse/HADOOP-6313 */ +} hb_durability_t; + +/** + * Log levels + */ +typedef enum { + HBASE_LOG_LEVEL_INVALID = 0, + HBASE_LOG_LEVEL_FATAL = 1, + HBASE_LOG_LEVEL_ERROR = 2, + HBASE_LOG_LEVEL_WARN = 3, + HBASE_LOG_LEVEL_INFO = 4, + HBASE_LOG_LEVEL_DEBUG = 5, + HBASE_LOG_LEVEL_TRACE = 6 +} HBaseLogLevel; + +/******************************************************************************* + * HBase Error Codes * + ******************************************************************************* + * The HBase APIs returns or invoke the callback functions with error code * + * set to 0. A non-zero value indicates an error condition. * + * * + * EAGAIN A recoverable error occurred and the operation can be immediately * + * retired. * + * * + * ENOBUFS The resources required to complete the operations are temporarily * + * exhausted and the application should retry the operation after a * + * brief pause, possibly throttling the rate of requests. * + * * + * ENOENT The requested table or a column family was not found. * + * * + * EEXIST Table or column family already exist. * + * * + * ENOMEM The process ran out of memory while trying to process the request. * + * * + * HBASE_TABLE_DISABLED * + * The table is disabled. * + * * + * HBASE_TABLE_NOT_DISABLED * + * The table is not disabled. * + * * + * HBASE_UNKNOWN_SCANNER * + * The specified scanner does not exist on region server. * + * * + * HBASE_INTERNAL_ERR * + * An internal error for which there is no error code defined. More * + * information will be available in the log. * + * * + *******************************************************************************/ +/** + * HBase custom error codes + */ +#define HBASE_INTERNAL_ERR -10000 +#define HBASE_TABLE_DISABLED (HBASE_INTERNAL_ERR-1) +#define HBASE_TABLE_NOT_DISABLED (HBASE_INTERNAL_ERR-2) +#define HBASE_UNKNOWN_SCANNER (HBASE_INTERNAL_ERR-3) + +/******************************************************************************* + * HBase API Callbacks * + ******************************************************************************* + * The following section defines various callback functions for the async * + * APIs. These callbacks may be triggered on the same thread as the caller or * + * on another thread. The application is expected to not block in the callback * + * routines. * + *******************************************************************************/ + +/** + * HBase Admin disconnection callback typedef + * + * This is called after the connections are closed, but just before + * the client is freed. + * + * Refer to the section on error code for the list of possible values + * for 'err'. A value of 0 indicates success. + */ +typedef void (*hb_admin_disconnection_cb)( + int32_t err, + hb_admin_t admin, + void *extra); + +/** + * Client disconnection callback typedef + * This is called after the connections are closed, but just before + * the client is freed. + * + * Refer to the section on error code for the list of possible values + * for 'err'. A value of 0 indicates success. + */ +typedef void (*hb_client_disconnection_cb) ( + int32_t err, + hb_client_t client, + void *extra); + +/** + * Client flush callback typedef + * This will be invoked when everything that was buffered at the time of + * the call has been flushed. + * + * Refer to the section on error code for the list of possible values + * for 'err'. A value of 0 indicates success. + */ +typedef void (*hb_client_flush_cb) ( + int32_t err, + hb_client_t client, + void *extra); + +/** + * Mutation call back typedef + * + * This callback is triggered with result of each mutation. + * + * Refer to the section on error code for the list of possible values + * for 'err'. A value of 0 indicates success. + */ +typedef void (*hb_mutation_cb)( + int32_t err, + hb_client_t client, + hb_mutation_t mutation, + hb_result_t result, + void *extra); + +/** + * Get callback typedef. + * This callback is triggered with result of each get call. + * + * The result, if not NULL, must be freed by calling hb_result_destroy(). + * + * Refer to the section on error code for the list of possible values + * for 'err'. A value of 0 indicates success. + */ +typedef void (*hb_get_cb)( + int32_t err, + hb_client_t client, + hb_get_t get, + hb_result_t result, + void *extra); + +/** + * Scanner call back typedef. + * This will be called when scanner next returns results. + * + * The individual results in the results array must be freed by calling + * hb_result_destroy(). The array itself is freed once the callback returns. + * + * Refer to the section on error code for the list of possible values + * for 'err'. A value of 0 indicates success. + */ +typedef void (*hb_scanner_cb)( + int32_t err, + hb_scanner_t scanner, + hb_result_t results[], + size_t num_results, + void *extra); + +/** + * Scanner close callback. + * + * Refer to the section on error code for the list of possible values + * for 'err'. A value of 0 indicates success. + */ +typedef void (*hb_scanner_destroy_cb)( + int32_t err, + hb_scanner_t scanner, + void *extra); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LIBHBASE_TYPES_H_ */ diff --git a/hbase-native-client/src/main/native/jni_impl/hbase_admin.cc b/hbase-native-client/src/main/native/jni_impl/hbase_admin.cc new file mode 100644 index 000000000000..5aa351d4d021 --- /dev/null +++ b/hbase-native-client/src/main/native/jni_impl/hbase_admin.cc @@ -0,0 +1,378 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#line 19 "hbase_admin.cc" // ensures short filename in logs. + +#include +#include +#include + +#include "hbase_admin.h" + +#include "hbase_client.h" +#include "hbase_config.h" +#include "hbase_consts.h" +#include "hbase_macros.h" +#include "hbase_msgs.h" +#include "jnihelper.h" + +namespace hbase { + +extern "C" { + +/** + * Create a new hb_admin. + * All fields are initialized to the defaults. If you want to set + * connection or other properties, set those before calling any + * RPC functions. + */ +HBASE_API int32_t +hb_admin_create( + hb_connection_t conn, + hb_admin_t *admin_ptr) { + RETURN_IF_INVALID_PARAM((conn == NULL), + Msgs::ERR_CONN_NULL); + RETURN_IF_INVALID_PARAM((admin_ptr == NULL), + Msgs::ERR_ADMIN_PTR_NULL); + + HBaseAdmin *admin = new HBaseAdmin(); + Status status = admin->Init( + reinterpret_cast(conn)); + if (status.ok()) { + *admin_ptr = reinterpret_cast (admin); + } else { + *admin_ptr = NULL; + delete admin; + } + return status.GetCode(); +} + +/** + * Disconnect the admin releasing any internal objects + * or connections created in the background. + */ +HBASE_API int32_t +hb_admin_destroy( + hb_admin_t a, + hb_admin_disconnection_cb cb, + void *extra) { + RETURN_IF_INVALID_PARAM((a == NULL), + Msgs::ERR_ADMIN_NULL); + + HBaseAdmin *admin = reinterpret_cast(a); + int32_t err = admin->Close().GetCode(); + if (cb != NULL) { + cb(err, a, extra); + } + delete admin; + return 0; +} + +/** + * Checks if a table exists. + * @returns 0 on if the table exist, an error code otherwise. + */ +HBASE_API int32_t +hb_admin_table_exists( + const hb_admin_t a, + const char *name_space, + const char *tableName) { + RETURN_IF_INVALID_PARAM((a == NULL), + Msgs::ERR_ADMIN_NULL); + RETURN_IF_INVALID_PARAM((tableName == NULL), + Msgs::ERR_TBL_NAME_NULL); + + return reinterpret_cast(a)-> + TableExists(name_space, tableName).GetCode(); +} + +/** + * Checks if a table is enabled. + * @returns 0 on if the table enabled, HBASE_TABLE_DISABLED if the table + * is disabled or an error code if an error occurs. + */ +HBASE_API int32_t +hb_admin_table_enabled( + const hb_admin_t a, + const char *name_space, + const char *tableName) { + RETURN_IF_INVALID_PARAM((a == NULL), + Msgs::ERR_ADMIN_NULL); + RETURN_IF_INVALID_PARAM((tableName == NULL), + Msgs::ERR_TBL_NAME_NULL); + + return reinterpret_cast(a)-> + TableEnabled(name_space, tableName).GetCode(); +} + +/** + * Enable an HBase table. + * @returns 0 on success, an error code otherwise. + */ +HBASE_API int32_t +hb_admin_table_enable( + const hb_admin_t a, + const char *name_space, + const char *tableName) { + RETURN_IF_INVALID_PARAM((a == NULL), + Msgs::ERR_ADMIN_NULL); + RETURN_IF_INVALID_PARAM((tableName == NULL), + Msgs::ERR_TBL_NAME_NULL); + + return reinterpret_cast(a)-> + EnableTable(name_space, tableName).GetCode(); +} + +/** + * Disable an HBase table. + * @returns 0 on success, an error code otherwise. + */ +HBASE_API int32_t +hb_admin_table_disable( + const hb_admin_t a, + const char *name_space, + const char *tableName) { + RETURN_IF_INVALID_PARAM((a == NULL), + Msgs::ERR_ADMIN_NULL); + RETURN_IF_INVALID_PARAM((tableName == NULL), + Msgs::ERR_TBL_NAME_NULL); + + return reinterpret_cast(a)-> + DisableTable(name_space, tableName).GetCode(); +} + +/** + * Creates an HBase table. + * @returns 0 on success, an error code otherwise. + */ +HBASE_API int32_t +hb_admin_table_create( + const hb_admin_t a, + const char *name_space, + const char *tableName, + const hb_columndesc families[], + const size_t numFamilies) { + RETURN_IF_INVALID_PARAM((a == NULL), + Msgs::ERR_ADMIN_NULL); + RETURN_IF_INVALID_PARAM((tableName == NULL), + Msgs::ERR_TBL_NAME_NULL); + RETURN_IF_INVALID_PARAM((families == NULL), + Msgs::ERR_FAMILIES_NULL); + RETURN_IF_INVALID_PARAM((numFamilies <= 0), + Msgs::ERR_NUM_FAMILIES, numFamilies); + + return reinterpret_cast(a)-> + CreateTable(name_space, tableName, + (const HColumnDescriptor**)families, + numFamilies).GetCode(); +} + +/** + * Deletes an HBase table, disables the table if not already disabled. + * Returns 0 on success, and error code otherwise. + */ +HBASE_API int32_t +hb_admin_table_delete( + const hb_admin_t a, + const char *name_space, + const char *tableName) { + RETURN_IF_INVALID_PARAM((a == NULL), + Msgs::ERR_ADMIN_NULL); + RETURN_IF_INVALID_PARAM((tableName == NULL), + Msgs::ERR_TBL_NAME_NULL); + + return reinterpret_cast(a)-> + DeleteTable(name_space, tableName).GetCode(); +} + +} /* extern "C" */ + +static JniResult +CreateHTableDescriptor( + JNIEnv *env, + const char *tableName) { + jstring tableNameString = env->NewStringUTF(tableName); + return JniHelper::NewObject(env, HBASE_TBLDSC, + JMETHOD1(JPARAM(JAVA_STRING), "V"), + tableNameString); +} + +HBaseAdmin::HBaseAdmin() { + pthread_mutex_init(&admin_mutex, NULL); +} + +HBaseAdmin::~HBaseAdmin() { + pthread_mutex_destroy(&admin_mutex); +} + +Status +HBaseAdmin::Init( + HBaseConfiguration *conf, + JNIEnv *current_env) { + JNI_GET_ENV(current_env); + JniResult result = JniHelper::NewObject( + env, HBASE_HADMIN, JMETHOD1(JPARAM(HADOOP_CONF), "V"), + conf->GetConf()); + if (result.ok()) { + jobject_ = env->NewGlobalRef(result.GetObject()); + } + return result; +} + +Status +HBaseAdmin::Close(JNIEnv *current_env) { + pthread_mutex_lock(&admin_mutex); + if (jobject_ != NULL) { + JNI_GET_ENV(current_env); + JniResult result = JniHelper::InvokeMethod( + env, jobject_, HBASE_HADMIN, "close", "()V"); + env->DeleteGlobalRef(jobject_); + jobject_ = NULL; + return result; + } + pthread_mutex_unlock(&admin_mutex); + return Status::Success; +} + +Status +HBaseAdmin::TableExists( + const char *name_space, + const char *tableName, + JNIEnv *current_env) { + // HBase 0.96 not implemented yet + if (name_space != NULL) return Status::ENoSys; + + JNI_GET_ENV(current_env); + jstring tableNameString = env->NewStringUTF(tableName); + JniResult result = JniHelper::InvokeMethod( + env, jobject_, HBASE_HADMIN, "tableExists", + JMETHOD1(JPARAM(JAVA_STRING), "Z"), tableNameString); + if (result.ok()) { + return (result.GetValue().z != 0) + ? Status::Success : Status::ENoEntry; + } + return result; +} + +Status +HBaseAdmin::TableEnabled( + const char *name_space, + const char *tableName, + JNIEnv *current_env) { + // HBase 0.96 not implemented yet + if (name_space != NULL) return Status::ENoSys; + + JNI_GET_ENV(current_env); + jstring tableNameString = env->NewStringUTF(tableName); + JniResult result = JniHelper::InvokeMethod( + env, jobject_, HBASE_HADMIN, "isTableEnabled", + JMETHOD1(JPARAM(JAVA_STRING), "Z"), tableNameString); + if (result.ok()) { + return (result.GetValue().z != 0) + ? Status::Success : Status::HBaseTableDisabled; + } + return result; +} + +Status +HBaseAdmin::CreateTable( + const char *name_space, + const char *tableName, + const HColumnDescriptor *families[], + const size_t numFamilies, + JNIEnv *current_env) { + // HBase 0.96 not implemented yet + if (name_space != NULL) return Status::ENoSys; + + JNI_GET_ENV(current_env); + JniResult htd = CreateHTableDescriptor(env, tableName); + if (!htd.ok()) return htd; + for (size_t i = 0; i < numFamilies; ++i) { + if (families[i] == NULL) { + return Status::EInvalid; + } + RETURN_IF_ERROR(JniHelper::InvokeMethod( + env, htd.GetObject(), HBASE_TBLDSC, "addFamily", + JMETHOD1(JPARAM(HBASE_CLMDSC), "V"), + families[i]->JObject())); + } + return JniHelper::InvokeMethod( + env, jobject_, HBASE_HADMIN, "createTable", + JMETHOD1(JPARAM(HBASE_TBLDSC), "V"), htd.GetObject()); +} + +Status +HBaseAdmin::EnableTable( + const char *name_space, + const char *tableName, + JNIEnv *current_env) { + // HBase 0.96 not implemented yet + if (name_space != NULL) return Status::ENoSys; + + JNI_GET_ENV(current_env); + jstring tableNameString = env->NewStringUTF(tableName); + Status status = JniHelper::InvokeMethod( + env, jobject_, HBASE_HADMIN, "enableTable", + JMETHOD1(JPARAM(JAVA_STRING), "V"), tableNameString); + if (status.GetCode() == HBASE_TABLE_NOT_DISABLED) { + HBASE_LOG_WARN(Msgs::ERR_TABLE_ALREADY_ENABLED, tableName); + return Status::Success; + } + return status; +} + +Status +HBaseAdmin::DisableTable( + const char *name_space, + const char *tableName, + JNIEnv *current_env) { + // HBase 0.96 not implemented yet + if (name_space != NULL) return Status::ENoSys; + + JNI_GET_ENV(current_env); + jstring tableNameString = env->NewStringUTF(tableName); + Status status = JniHelper::InvokeMethod( + env, jobject_, HBASE_HADMIN, "disableTable", + JMETHOD1(JPARAM(JAVA_STRING), "V"), tableNameString); + if (status.GetCode() == HBASE_TABLE_DISABLED) { + HBASE_LOG_WARN(Msgs::ERR_TABLE_ALREADY_DISABLED, tableName); + return Status::Success; + } + return status; +} + +Status +HBaseAdmin::DeleteTable( + const char *name_space, + const char *tableName, + JNIEnv *current_env) { + // HBase 0.96 not implemented yet + if (name_space != NULL) return Status::ENoSys; + + JNI_GET_ENV(current_env); + Status status = DisableTable(name_space, tableName, env); + if (!status.ok() + && status.GetCode() != HBASE_TABLE_DISABLED) { + return status; + } + jstring tableNameString = env->NewStringUTF(tableName); + return JniHelper::InvokeMethod( + env, jobject_, HBASE_HADMIN, "deleteTable", + JMETHOD1(JPARAM(JAVA_STRING), "V"), tableNameString); +} + +} /* namespace hbase */ diff --git a/hbase-native-client/src/main/native/jni_impl/hbase_admin.h b/hbase-native-client/src/main/native/jni_impl/hbase_admin.h new file mode 100644 index 000000000000..9f9b9461013e --- /dev/null +++ b/hbase-native-client/src/main/native/jni_impl/hbase_admin.h @@ -0,0 +1,58 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef HBASE_JNI_IMPL_ADMIN_H_ +#define HBASE_JNI_IMPL_ADMIN_H_ + +#include + +#include "hbase_coldesc.h" +#include "hbase_config.h" +#include "hbase_status.h" + +namespace hbase { + +class HBaseAdmin : public JniObject { +public: + HBaseAdmin(); + + ~HBaseAdmin(); + + Status Init(HBaseConfiguration *conf, JNIEnv *current_env=NULL); + + Status Close(JNIEnv *current_env=NULL); + + Status TableExists(const char *name_space, const char *tableName, JNIEnv *current_env=NULL); + + Status TableEnabled(const char *name_space, const char *tableName, JNIEnv *current_env=NULL); + + Status CreateTable(const char *name_space, const char *tableName, + const HColumnDescriptor *families[], const size_t numFamilies, JNIEnv *current_env=NULL); + + Status EnableTable(const char *name_space, const char *tableName, JNIEnv *current_env=NULL); + + Status DisableTable(const char *name_space, const char *tableName, JNIEnv *current_env=NULL); + + Status DeleteTable(const char *name_space, const char *tableName, JNIEnv *current_env=NULL); + +private: + pthread_mutex_t admin_mutex; +}; + +} /* namespace hbase */ + +#endif /* HBASE_JNI_IMPL_ADMIN_H_ */ diff --git a/hbase-native-client/src/main/native/jni_impl/hbase_client.cc b/hbase-native-client/src/main/native/jni_impl/hbase_client.cc new file mode 100644 index 000000000000..8479df5fb92a --- /dev/null +++ b/hbase-native-client/src/main/native/jni_impl/hbase_client.cc @@ -0,0 +1,312 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#line 19 "hbase_client.cc" // ensures short filename in logs. + +#include +#include +#include + +#include "hbase_client.h" + +#include "hbase_consts.h" +#include "hbase_msgs.h" +#include "hbase_mutations.h" +#include "hbase_result.h" +#include "jnihelper.h" + +#include "org_apache_hadoop_hbase_jni_CallbackHandlers.h" + +namespace hbase { + +extern "C" { + +/* + * Class: org_apache_hadoop_hbase_jni_CallbackHandlers + * Method: mutationCallBack + * Signature: (Ljava/lang/Throwable;JJJLjava/lang/Object;J)V + */ +HBASE_API void JNICALL +Java_org_apache_hadoop_hbase_jni_CallbackHandlers_mutationCallBack( + JNIEnv *env, jclass clazz, jthrowable jthr, + jlong cb, jlong client, jlong mutation, + jobject result, jlong extra) { + hb_mutation_cb mutation_cb = (hb_mutation_cb) cb; + if (mutation_cb) { + mutation_cb(JniHelper::ErrorFromException(env, jthr), + (hb_client_t)client, + (hb_mutation_t)mutation, + Result::From(jthr, result, env), + (void*)extra); + } +} + +/* + * Class: org_apache_hadoop_hbase_jni_CallbackHandlers + * Method: getCallBack + * Signature: (Ljava/lang/Throwable;JJJLjava/lang/Object;J)V + */ +HBASE_API void JNICALL +Java_org_apache_hadoop_hbase_jni_CallbackHandlers_getCallBack( + JNIEnv *env, jclass clazz, jthrowable jthr, + jlong cb, jlong client, jlong get, + jobject result, jlong extra) { + hb_get_cb get_cb = (hb_get_cb) cb; + if (get_cb) { + get_cb(JniHelper::ErrorFromException(env, jthr), + (hb_client_t)client, + (hb_get_t)get, + Result::From(jthr, result, env), + (void*)extra); + } +} + +/* + * Class: org_apache_hadoop_hbase_jni_CallbackHandlers + * Method: clientFlushCallBack + * Signature: (Ljava/lang/Throwable;JJJ)V + */ +HBASE_API void JNICALL +Java_org_apache_hadoop_hbase_jni_CallbackHandlers_clientFlushCallBack( + JNIEnv *env, jclass clazz, jthrowable jthr, + jlong cb, jlong client, jlong extra) { + hb_client_flush_cb flush_cb = (hb_client_flush_cb) cb; + if (flush_cb) { + flush_cb(JniHelper::ErrorFromException(env, jthr), + (hb_client_t)client, + (void*)extra); + } +} + +/* + * Class: org_apache_hadoop_hbase_jni_CallbackHandlers + * Method: clientCloseCallBack + * Signature: (Ljava/lang/Throwable;JJJ)V + */ +HBASE_API void JNICALL +Java_org_apache_hadoop_hbase_jni_CallbackHandlers_clientCloseCallBack( + JNIEnv *env, jclass clazz, jthrowable jthr, + jlong cb, jlong client, jlong extra) { + hb_client_disconnection_cb close_cb = (hb_client_disconnection_cb) cb; + if (close_cb) { + close_cb(JniHelper::ErrorFromException(env, jthr), + (hb_client_t)client, + (void*)extra); + } + delete reinterpret_cast(client); +} + +/** + * Initializes a handle to hb_client_t which can be passed to other HBase APIs. + * You need to use this method only once per HBase cluster. The returned handle + * is thread safe. + * + * @returns 0 on success, non-zero error code in case of failure. + */ +HBASE_API int32_t +hb_client_create( + hb_connection_t connection, + hb_client_t *c_ptr) { + RETURN_IF_INVALID_PARAM((connection == NULL), + Msgs::ERR_CONN_NULL); + RETURN_IF_INVALID_PARAM((c_ptr == NULL), + Msgs::ERR_CONNPTR_NULL); + + HBaseClient *client = new HBaseClient(); + if (!client) return ENOMEM; + + Status status = client->Init( + reinterpret_cast(connection)); + if (status.ok()) { + *c_ptr = reinterpret_cast (client); + } else { + *c_ptr = NULL; + delete client; + } + return status.GetCode(); +} + +/** + * Queue a mutation to go out. These mutations will not be performed atomically + * and can be batched in a non-deterministic way on either the server or the + * client side. + * + * Any buffer attached to the the mutation objects must not be altered until the + * callback has been triggered. + */ +HBASE_API int32_t +hb_mutation_send( + hb_client_t client, + hb_mutation_t mutation, + hb_mutation_cb cb, + void *extra) { + CALLBACK_IF_INVALID_PARAM((client == NULL), + cb, client, mutation, NULL, extra, Msgs::ERR_CLIENT_NULL); + CALLBACK_IF_INVALID_PARAM((mutation == NULL), + cb, client, mutation, NULL, extra, Msgs::ERR_MUTATION_NULL); + + return reinterpret_cast(client)-> + SendMutation(reinterpret_cast(mutation), + cb, extra).GetCode(); +} + +/** + * Queues the get request. Callback specified by cb will be called on completion. + * Any buffer(s) attached to the get object can be reclaimed only after the + * callback is received. + */ +HBASE_API int32_t +hb_get_send( + hb_client_t client, + hb_get_t get, + hb_get_cb cb, + void *extra) { + CALLBACK_IF_INVALID_PARAM((client == NULL), + cb, client, get, NULL, extra, Msgs::ERR_CLIENT_NULL); + CALLBACK_IF_INVALID_PARAM((get == NULL), + cb, client, get, NULL, extra, Msgs::ERR_GET_NULL); + + return reinterpret_cast(client)-> + SendGet(reinterpret_cast(get), + cb, extra).GetCode(); +} + +/** + * Flushes any buffered client-side write operations to HBase. + * The callback will be invoked when everything that was buffered at the time of + * the call has been flushed. + * Note that this doesn't guarantee that ALL outstanding RPCs have completed. + * This doesn't introduce any sort of global sync point. All it does really is + * it sends any buffered RPCs to HBase. + */ +HBASE_API int32_t +hb_client_flush( + hb_client_t client, + hb_client_flush_cb cb, + void *extra) { + if (UNLIKELY((client == NULL))){ + HBASE_LOG_ERROR(Msgs::ERR_CLIENT_NULL); + cb(EINVAL, client, extra); + return 0; + } + return reinterpret_cast(client)-> + Flush(cb, extra).GetCode(); +} + +/** + * Cleans up hb_client_t handle and release any held resources. + * The callback is called after the connections are closed, but just before the + * client is freed. + */ +HBASE_API int32_t +hb_client_destroy( + hb_client_t client, + hb_client_disconnection_cb cb, + void *extra) { + if (UNLIKELY((client == NULL))){ + HBASE_LOG_ERROR(Msgs::ERR_CLIENT_NULL); + cb(EINVAL, client, extra); + return 0; + } + return reinterpret_cast(client)-> + Close(cb, extra).GetCode(); +} + +} /* extern "C" */ + +HBaseClient::HBaseClient() { + pthread_mutex_init(&client_mutex, NULL); +} + +HBaseClient::~HBaseClient() { + pthread_mutex_destroy(&client_mutex); +} + +Status +HBaseClient::Init( + HBaseConfiguration *conf, + JNIEnv *current_env) { + JNI_GET_ENV(current_env); + JniResult result = JniHelper::NewObject( + env, CLASS_CLIENT_PROXY, + JMETHOD1(JPARAM(HADOOP_CONF), "V"), + conf->GetConf()); + if (result.ok()) { + jobject_ = env->NewGlobalRef(result.GetObject()); + } + return result; +} + +Status +HBaseClient::SendMutation( + Mutation* mutation, + hb_mutation_cb cb, + void* extra, + JNIEnv *current_env) { + JNI_GET_ENV(current_env); + JniResult result = JniHelper::InvokeMethod( + env, jobject_, CLASS_CLIENT_PROXY, "sendMutation", + "(L"CLASS_MUTATION_PROXY";JJJJ)V", mutation->JObject(), + (jlong) cb, (jlong) this, (jlong) mutation, (jlong) extra); + return Status::Success; +} + +Status +HBaseClient::SendGet( + Get* get, + hb_get_cb cb, + void* extra, + JNIEnv* current_env) { + JNI_GET_ENV(current_env); + JniResult result = JniHelper::InvokeMethod( + env, jobject_, CLASS_CLIENT_PROXY, "sendGet", + "(L"CLASS_GET_PROXY";JJJJ)V", get->JObject(), + (jlong) cb, (jlong) this, (jlong) get, (jlong) extra); + return Status::Success; +} + +Status +HBaseClient::Flush( + hb_client_disconnection_cb cb, + void* extra, + JNIEnv* current_env) { + JNI_GET_ENV(current_env); + JniResult result = JniHelper::InvokeMethod( + env, jobject_, CLASS_CLIENT_PROXY, "flush", "(JJJ)V", + (jlong) cb, (jlong) this, (jlong) extra); + return Status::Success; +} + +Status +HBaseClient::Close( + hb_client_disconnection_cb cb, + void *extra, + JNIEnv *current_env) { + pthread_mutex_lock(&client_mutex); + if (jobject_ != NULL) { + JNI_GET_ENV(current_env); + JniResult result = JniHelper::InvokeMethod( + env, jobject_, CLASS_CLIENT_PROXY, "close", + "(JJJ)V", (jlong) cb, (jlong) this, (jlong) extra); + env->DeleteGlobalRef(jobject_); + jobject_ = NULL; + } + pthread_mutex_unlock(&client_mutex); + return Status::Success; +} + +} /* namespace hbase */ diff --git a/hbase-native-client/src/main/native/jni_impl/hbase_client.h b/hbase-native-client/src/main/native/jni_impl/hbase_client.h new file mode 100644 index 000000000000..e3aa2e4060d9 --- /dev/null +++ b/hbase-native-client/src/main/native/jni_impl/hbase_client.h @@ -0,0 +1,55 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef HBASE_JNI_IMPL_CLIENT_H__ +#define HBASE_JNI_IMPL_CLIENT_H__ + +#ifndef _WIN32 +#include +#endif + +#include "hbase_config.h" +#include "hbase_get.h" +#include "hbase_mutations.h" +#include "hbase_status.h" +#include "jnihelper.h" + +namespace hbase { + +class HBaseClient : public JniObject { +public: + HBaseClient(); + + ~HBaseClient(); + + Status Init(HBaseConfiguration *conf, JNIEnv *current_env=NULL); + + Status Flush(hb_client_disconnection_cb cb, void *extra, JNIEnv *current_env=NULL); + + Status Close(hb_client_disconnection_cb cb, void *extra, JNIEnv *current_env=NULL); + + Status SendMutation(Mutation *mutation, hb_mutation_cb cb, void *extra, JNIEnv *current_env=NULL); + + Status SendGet(Get *get, hb_mutation_cb cb, void *extra, JNIEnv *current_env=NULL); + +private: + pthread_mutex_t client_mutex; +}; + +} /* namespace hbase */ + +#endif /* HBASE_JNI_IMPL_CLIENT_H__ */ diff --git a/hbase-native-client/src/main/native/jni_impl/hbase_coldesc.cc b/hbase-native-client/src/main/native/jni_impl/hbase_coldesc.cc new file mode 100644 index 000000000000..1377addd25f0 --- /dev/null +++ b/hbase-native-client/src/main/native/jni_impl/hbase_coldesc.cc @@ -0,0 +1,187 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#line 19 "hbase_coldesc.cc" // ensures short filename in logs. + +#include +#include +#include + +#include "hbase_coldesc.h" + +#include "hbase_macros.h" +#include "hbase_msgs.h" +#include "jnihelper.h" + +namespace hbase { + +extern "C" { + +HBASE_API int32_t +hb_coldesc_create( + const byte_t *family, + const size_t family_len, + hb_columndesc *col_desc) { + RETURN_IF_INVALID_PARAM((family == NULL), + Msgs::ERR_FAMILY_NULL); + RETURN_IF_INVALID_PARAM((family_len <= 0), + Msgs::ERR_FAMILY_LEN, family_len); + + HColumnDescriptor *hcd = new HColumnDescriptor(); + Status status = hcd->Init(family, family_len); + if (UNLIKELY(!status.ok())) { + *col_desc = NULL; + delete hcd; + } else { + *col_desc = reinterpret_cast (hcd); + } + return status.GetCode(); +} + +HBASE_API int32_t +hb_coldesc_destroy(hb_columndesc c) { + RETURN_IF_INVALID_PARAM((c == NULL), + Msgs::ERR_COLDESC_NULL); + + delete reinterpret_cast(c); + return 0; +} + +HBASE_API int32_t +hb_coldesc_set_maxversions( + hb_columndesc c, + int32_t max_versions) { + RETURN_IF_INVALID_PARAM((c == NULL), + Msgs::ERR_COLDESC_NULL); + RETURN_IF_INVALID_PARAM((max_versions <= 0), + Msgs::ERR_MAX_VERSIONS); + + return reinterpret_cast(c)-> + SetMaxVersions(max_versions).GetCode(); +} + +HBASE_API int32_t +hb_coldesc_set_minversions( + hb_columndesc c, + int32_t min_versions) { + RETURN_IF_INVALID_PARAM((c == NULL), + Msgs::ERR_COLDESC_NULL); + RETURN_IF_INVALID_PARAM((min_versions < 0), + Msgs::ERR_MIN_VERSIONS); + + return reinterpret_cast(c)-> + SetMinVersions(min_versions).GetCode(); +} + +HBASE_API int32_t +hb_coldesc_set_ttl( + hb_columndesc c, + int32_t ttl) { + RETURN_IF_INVALID_PARAM((c == NULL), + Msgs::ERR_COLDESC_NULL); + RETURN_IF_INVALID_PARAM((ttl < 0), Msgs::ERR_TTL); + + return reinterpret_cast(c)-> + SetTimeToLive(ttl).GetCode(); +} + +HBASE_API int32_t +hb_coldesc_set_inmemory( + hb_columndesc c, + int32_t in_memory) { + RETURN_IF_INVALID_PARAM((c == NULL), + Msgs::ERR_COLDESC_NULL); + + return reinterpret_cast(c)-> + SetInMemory(in_memory).GetCode(); +} + +} /* extern "C" */ + +Status +HColumnDescriptor::Init( + const byte_t *family, + const size_t family_len, + JNIEnv *current_env) { + JNI_GET_ENV(current_env); + JniResult result = JniHelper::CreateJavaByteArray( + env, family, 0, family_len); + RETURN_IF_ERROR(result); + + result = JniHelper::NewObject( + env, HBASE_CLMDSC, "([B)V", result.GetObject()); + if (result.ok()) { + jobject_ = env->NewGlobalRef(result.GetObject()); + } + return result; +} + +HColumnDescriptor::~HColumnDescriptor() { + Destroy(); +} + +Status +HColumnDescriptor::Destroy(JNIEnv *current_env) { + if (jobject_ != NULL) { + JNI_GET_ENV(current_env); + env->DeleteGlobalRef(jobject_); + jobject_= NULL; + } + return Status::Success; +} + +Status +HColumnDescriptor::SetMaxVersions( + int32_t maxVersions, + JNIEnv *current_env) { + JNI_GET_ENV(current_env); + return JniHelper::InvokeMethod( + env, jobject_, HBASE_CLMDSC, "setMaxVersions", + "(I)"JPARAM(HBASE_CLMDSC), maxVersions); +} + +Status +HColumnDescriptor::SetMinVersions( + int32_t minVersions, + JNIEnv *current_env) { + JNI_GET_ENV(current_env); + return JniHelper::InvokeMethod( + env, jobject_, HBASE_CLMDSC, "setMinVersions", + "(I)"JPARAM(HBASE_CLMDSC), minVersions); +} + +Status +HColumnDescriptor::SetTimeToLive( + int32_t ttl, + JNIEnv *current_env) { + JNI_GET_ENV(current_env); + return JniHelper::InvokeMethod( + env, jobject_, HBASE_CLMDSC, "setTimeToLive", + "(I)"JPARAM(HBASE_CLMDSC), ttl); +} + +Status +HColumnDescriptor::SetInMemory( + bool inMemory, + JNIEnv *current_env) { + JNI_GET_ENV(current_env); + return JniHelper::InvokeMethod( + env, jobject_, HBASE_CLMDSC, "setInMemory", + "(Z)"JPARAM(HBASE_CLMDSC), (inMemory ? 1 : 0)); +} + +} /* namespace hbase */ diff --git a/hbase-native-client/src/main/native/jni_impl/hbase_coldesc.h b/hbase-native-client/src/main/native/jni_impl/hbase_coldesc.h new file mode 100644 index 000000000000..a35d59f04f81 --- /dev/null +++ b/hbase-native-client/src/main/native/jni_impl/hbase_coldesc.h @@ -0,0 +1,51 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef HBASE_JNI_IMPL_COLDESC_H_ +#define HBASE_JNI_IMPL_COLDESC_H_ + +#include + +#include "jnihelper.h" + +namespace hbase { + +class HColumnDescriptor : public JniObject { +public: + HColumnDescriptor() {} + + ~HColumnDescriptor(); + + Status Init(const byte_t *family, const size_t family_len, JNIEnv *current_env=NULL); + + Status SetMaxVersions(int32_t maxVersions, JNIEnv *current_env=NULL); + + Status SetMinVersions(int32_t minVersions, JNIEnv *current_env=NULL); + + Status SetTimeToLive(int32_t ttl, JNIEnv *current_env=NULL); + + Status SetInMemory(bool inMemory, JNIEnv *current_env=NULL); + + friend class HBaseAdmin; + +private: + Status Destroy(JNIEnv *current_env=NULL); +}; + +} /* namespace hbase */ + +#endif /* HBASE_JNI_IMPL_COLDESC_H_ */ diff --git a/hbase-native-client/src/main/native/jni_impl/hbase_config.cc b/hbase-native-client/src/main/native/jni_impl/hbase_config.cc new file mode 100644 index 000000000000..e6e76baf37d3 --- /dev/null +++ b/hbase-native-client/src/main/native/jni_impl/hbase_config.cc @@ -0,0 +1,138 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#line 19 "hbase_config.cc" // ensures short filename in logs. + +#include +#include + +#include "hbase_config.h" + +#include "hbase_consts.h" +#include "hbase_msgs.h" +#include "jnihelper.h" + +namespace hbase { + +extern "C" { +/** + * Creates an hb_connection_t instance and initializes its address into + * the passed pointer. + */ +HBASE_API int32_t +hb_connection_create( + const char *zookeeprEnsemble, + const char *zookeeprBaseNode, + hb_connection_t *c_ptr) { + RETURN_IF_INVALID_PARAM((c_ptr == NULL), + Msgs::ERR_CONNPTR_NULL); + + HBaseConfiguration *conf = new HBaseConfiguration(); + if (conf == NULL) return ENOMEM; + + Status status = conf->Init( + zookeeprEnsemble, zookeeprBaseNode); + if (status.ok()) { + *c_ptr = reinterpret_cast (conf); + } else { + *c_ptr = NULL; + delete conf; + } + return status.GetCode(); +} + +HBASE_API int32_t +hb_connection_destroy(hb_connection_t conn) { + RETURN_IF_INVALID_PARAM((conn == NULL), + Msgs::ERR_CONN_NULL); + delete reinterpret_cast(conn); + return 0; +} + +} // extern "C" + +Status +HBaseConfiguration::Init( + const char *zookeeprEnsemble, + const char *zookeeprBaseNode, + JNIEnv *current_env) { + JNI_GET_ENV(current_env); + + JniResult result = JniHelper::InvokeMethodS( + env, HBASE_CONF, "create", JMETHOD1("", JPARAM(HADOOP_CONF))); + RETURN_IF_ERROR(result); + + jobject_ = env->NewGlobalRef(result.GetObject()); + if (zookeeprEnsemble != NULL) { + RETURN_IF_ERROR( + SetProperty(HConstants::ZK_ENSEMBLE, zookeeprEnsemble, env)); + RETURN_IF_ERROR( + SetProperty(HConstants::ZK_QUORUM, zookeeprEnsemble, env)); + std::string ensemble = zookeeprEnsemble; + std::string clientPort = HConstants::ZK_DEFAULT_PORT; + size_t portStart = ensemble.find(':', 0); + if (portStart != std::string::npos) { + size_t portEnd = ensemble.find(',', ++portStart); + clientPort = ensemble.substr(portStart, (portEnd-portStart)); + for (size_t i = 0; i < clientPort.length(); ++i) { + char digit = clientPort.at(i); + if (digit < '0' || digit > '9') { + HBASE_LOG_ERROR(Msgs::ZK_PORT_INVALID, + clientPort.c_str(), zookeeprEnsemble); + return Status::EInvalid; + } + } + } + RETURN_IF_ERROR( + SetProperty(HConstants::ZK_CLIENT_PORT,clientPort.c_str(), env)); + } + if (zookeeprBaseNode != NULL) { + RETURN_IF_ERROR( + SetProperty(HConstants::ZK_ROOT_NODE, zookeeprBaseNode, env)); + } + return result; +} + +HBaseConfiguration::~HBaseConfiguration() { + if (jobject_ != NULL) { + JNIEnv *env = JniHelper::GetJNIEnv(); + if (env != NULL) { + env->DeleteGlobalRef(jobject_); + } + } + } + +Status +HBaseConfiguration::SetProperty( + const char *propName, + const char *propValue, + JNIEnv *current_env) { + if (propName != NULL) { + JNI_GET_ENV(current_env); + jstring name = env->NewStringUTF(propName); + jstring value = env->NewStringUTF((propValue == NULL) ? "" : propValue); + + JniResult result = JniHelper::InvokeMethod( + env, jobject_, HBASE_CONF, "set", + JMETHOD2(JPARAM(JAVA_STRING), JPARAM(JAVA_STRING), "V"), + name, value); + return result; + } + return Status::EInvalid; +} + +} /* namespace hbase */ diff --git a/hbase-native-client/src/main/native/jni_impl/hbase_config.h b/hbase-native-client/src/main/native/jni_impl/hbase_config.h new file mode 100644 index 000000000000..03df8481a676 --- /dev/null +++ b/hbase-native-client/src/main/native/jni_impl/hbase_config.h @@ -0,0 +1,43 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef HBASE_JNI_IMPL_CONFIG_H__ +#define HBASE_JNI_IMPL_CONFIG_H__ + +#include + +#include "jnihelper.h" +#include "hbase_status.h" + +namespace hbase { + +class HBaseConfiguration : public JniObject { +public: + HBaseConfiguration() {} + + ~HBaseConfiguration(); + + Status Init(const char *zookeeprEnsemble, const char *zookeeprBaseNode, JNIEnv *current_env=NULL); + + Status SetProperty(const char *propName, const char *propValue, JNIEnv *current_env=NULL); + + jobject GetConf() const { return jobject_; } +}; + +} /* namespace hbase */ + +#endif /* HBASE_JNI_IMPL_CONFIG_H__ */ diff --git a/hbase-native-client/src/main/native/jni_impl/hbase_delete.cc b/hbase-native-client/src/main/native/jni_impl/hbase_delete.cc new file mode 100644 index 000000000000..bcb1a210cdb8 --- /dev/null +++ b/hbase-native-client/src/main/native/jni_impl/hbase_delete.cc @@ -0,0 +1,110 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#line 19 "hbase_delete.cc" // ensures short filename in logs. + +#include +#include + +#include "hbase_delete.h" + +#include "hbase_macros.h" +#include "hbase_msgs.h" +#include "jnihelper.h" + +namespace hbase { + +extern "C" { + +/** + * Creates a structure for delete operation and return its handle. + */ +HBASE_API int32_t +hb_delete_create( + const byte_t *rowkey, + const size_t rowkey_len, + hb_delete_t *delete_ptr) { + RETURN_IF_INVALID_PARAM((rowkey == NULL), + Msgs::ERR_KEY_NULL); + RETURN_IF_INVALID_PARAM((rowkey_len <= 0), + Msgs::ERR_KEY_LEN, rowkey_len); + RETURN_IF_INVALID_PARAM((delete_ptr == NULL), + Msgs::ERR_DELPTR_NULL); + + *delete_ptr = NULL; + Delete *del = new Delete(); + Status status = del->Init( + CLASS_DELETE_PROXY, rowkey, rowkey_len); + if (UNLIKELY(!status.ok())) { + delete del; + return status.GetCode(); + } + *delete_ptr = reinterpret_cast (del); + return 0; +} + +/** + * Optional. + * Sets the timestamp of the delete row or delete family operation. + * This does not override the timestamp of individual columns added via + * hb_delete_add_column(). + */ +HBASE_API int32_t +hb_delete_set_timestamp( + hb_delete_t d, + const int64_t timestamp) { + RETURN_IF_INVALID_PARAM((d == NULL), + Msgs::ERR_DEL_NULL); + RETURN_IF_INVALID_PARAM((timestamp <= 0), + Msgs::ERR_TIMESTAMP1, timestamp); + + return reinterpret_cast(d)-> + SetTS(timestamp).GetCode(); +} + +/** + * Optional. + * Set the column criteria for hb_delete_t object. + * Set the qualifier to NULL to delete all columns of a family. + * Only the cells with timestamp less than or equal to the specified timestamp + * are deleted. Set the timestamp to -1 to delete all versions of the column. + */ +HBASE_API int32_t +hb_delete_add_column( + hb_delete_t d, + const byte_t *family, + const size_t family_len, + const byte_t *qualifier, + const size_t qualifier_len, + const int64_t timestamp) { + RETURN_IF_INVALID_PARAM((d == NULL), + Msgs::ERR_DEL_NULL); + RETURN_IF_INVALID_PARAM((family == NULL), + Msgs::ERR_FAMILY_NULL); + RETURN_IF_INVALID_PARAM((family_len <= 0), + Msgs::ERR_FAMILY_LEN, family_len); + RETURN_IF_INVALID_PARAM((timestamp <= 0 && timestamp != -1), + Msgs::ERR_TIMESTAMP2, timestamp); + + return reinterpret_cast(d)-> + AddColumn(family, family_len, qualifier, + qualifier_len, NULL, 0, timestamp).GetCode(); +} + +} /* extern "C" */ + +} /* namespace hbase */ diff --git a/hbase-native-client/src/main/native/jni_impl/hbase_delete.h b/hbase-native-client/src/main/native/jni_impl/hbase_delete.h new file mode 100644 index 000000000000..71f63fb0ef03 --- /dev/null +++ b/hbase-native-client/src/main/native/jni_impl/hbase_delete.h @@ -0,0 +1,35 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef HBASE_JNI_IMPL_DELETE_H_ +#define HBASE_JNI_IMPL_DELETE_H_ + +#include "hbase_mutations.h" +#include "hbase_status.h" + +namespace hbase { + +class Delete : public BufferableRpc { +public: + Delete() {} + + ~Delete() {} +}; + +} /* namespace hbase */ + +#endif /* HBASE_JNI_IMPL_DELETE_H_ */ diff --git a/hbase-native-client/src/main/native/jni_impl/hbase_get.cc b/hbase-native-client/src/main/native/jni_impl/hbase_get.cc new file mode 100644 index 000000000000..0e4020895ce8 --- /dev/null +++ b/hbase-native-client/src/main/native/jni_impl/hbase_get.cc @@ -0,0 +1,236 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#line 19 "hbase_get.cc" // ensures short filename in logs. + +#include +#include + +#include "hbase_get.h" + +#include "hbase_macros.h" +#include "hbase_msgs.h" +#include "jnihelper.h" + +namespace hbase { + +extern "C" { + +/** + * Creates an hb_get_t object and populate the handle get_ptr. + */ +HBASE_API int32_t +hb_get_create( + const byte_t *rowkey, + const size_t rowkey_len, + hb_get_t *get_ptr) { + RETURN_IF_INVALID_PARAM((rowkey == NULL), + Msgs::ERR_KEY_NULL); + RETURN_IF_INVALID_PARAM((rowkey_len <= 0), + Msgs::ERR_KEY_LEN, rowkey_len); + RETURN_IF_INVALID_PARAM((get_ptr == NULL), + Msgs::ERR_GETPTR_NULL); + + *get_ptr = NULL; + Get *get = new Get(); + if (get == NULL) { + return ENOMEM; + } + Status status = get->Init( + CLASS_GET_PROXY, rowkey, rowkey_len); + if (UNLIKELY(!status.ok())) { + delete get; + return status.GetCode(); + } + *get_ptr = reinterpret_cast (get); + return 0; +} + +/** + * Sets the row key, required. + */ +HBASE_API int32_t +hb_get_set_row( + hb_get_t get, + const byte_t *rowkey, + const size_t rowkey_len) { + RETURN_IF_INVALID_PARAM((get == NULL), + Msgs::ERR_GET_NULL); + RETURN_IF_INVALID_PARAM((rowkey == NULL), + Msgs::ERR_KEY_NULL); + RETURN_IF_INVALID_PARAM((rowkey_len <= 0), + Msgs::ERR_KEY_LEN, rowkey_len); + + return reinterpret_cast(get)-> + SetRowKey(rowkey, rowkey_len).GetCode(); +} + +/** + * Sets the table name, required. + */ +HBASE_API int32_t +hb_get_set_table( + hb_get_t get, + const char *table, + const size_t table_len) { + RETURN_IF_INVALID_PARAM((get == NULL), + Msgs::ERR_GET_NULL); + RETURN_IF_INVALID_PARAM((table == NULL), + Msgs::ERR_TBL_NULL); + RETURN_IF_INVALID_PARAM((table_len <= 0), + Msgs::ERR_TBL_LEN, table_len); + + return reinterpret_cast(get)-> + SetTable(table, table_len).GetCode(); +} + +/** + * Sets the table namespace (0.96 and later) + */ +HBASE_API int32_t +hb_get_set_namespace( + hb_get_t get, + const char *name_space, + const size_t name_space_len) { + return ENOSYS; +} + +/** + * Adds a column family and optionally a column qualifier to + * the hb_get_t object, optional. + */ +HBASE_API int32_t +hb_get_add_column( + hb_get_t get, + const byte_t *family, + const size_t family_len, + const byte_t *qualifier, + const size_t qualifier_len) { + RETURN_IF_INVALID_PARAM((get == NULL), + Msgs::ERR_GET_NULL); + RETURN_IF_INVALID_PARAM((family == NULL), + Msgs::ERR_FAMILY_NULL); + RETURN_IF_INVALID_PARAM((family_len <= 0), + Msgs::ERR_FAMILY_LEN, family_len); + + return reinterpret_cast(get)-> + AddColumn(family, family_len, + qualifier, qualifier_len).GetCode(); +} + +/** + * Optional. Adds a filter to the hb_get_t object. + * + * The filter must be specified using HBase Filter Language. + * Refer to class org.apache.hadoop.hbase.filter.ParseFilter and + * https://issues.apache.org/jira/browse/HBASE-4176 or + * http://hbase.apache.org/book.html#thrift.filter-language for + * language syntax and additional details. + */ +HBASE_API int32_t +hb_get_set_filter( + hb_get_t get, + const char *filter) { + return ENOSYS; +} + +/** + * Optional. Sets maximum number of latest values of each column to be + * fetched. + */ +HBASE_API int32_t +hb_get_set_num_versions( + hb_get_t get, + const int32_t num_versions) { + RETURN_IF_INVALID_PARAM((get == NULL), + Msgs::ERR_GET_NULL); + RETURN_IF_INVALID_PARAM((num_versions <= 0), + Msgs::ERR_NUM_VERSIONS); + + return reinterpret_cast(get)-> + SetNumVersions(num_versions).GetCode(); +} + +/** + * Optional. Only columns with the specified timestamp will be included. + */ +HBASE_API int32_t +hb_get_set_timestamp( + hb_get_t get, + const int64_t ts) { + return ENOSYS; +} + +/** + * Release any resource held by hb_get_t object. + */ +HBASE_API int32_t +hb_get_destroy(hb_get_t get) { + RETURN_IF_INVALID_PARAM((get == NULL), + Msgs::ERR_GET_NULL); + + delete reinterpret_cast(get); + return 0; +} + +} /* extern "C" */ + +Status +Get::AddColumn( + const byte_t *f, + const size_t fLen, + const byte_t *q, + const size_t qLen, + JNIEnv *current_env) { + JNI_GET_ENV(current_env); + JniResult family = JniHelper::CreateJavaByteArray(env, f, 0, fLen); + RETURN_IF_ERROR(family); + + jobject qualifier = NULL; + if (q != NULL) { + JniResult result = JniHelper::CreateJavaByteArray(env, q, 0, qLen); + RETURN_IF_ERROR(result); + qualifier = result.GetObject(); + } + + return JniHelper::InvokeMethod( + env, jobject_, CLASS_GET_PROXY, "addColumn", + "([B[B)L"CLASS_GET_PROXY";", family.GetObject(), qualifier); +} + +Status +Get::SetNumVersions( + const int32_t numVersions, + JNIEnv *current_env) { + JNI_GET_ENV(current_env); + return JniHelper::InvokeMethod( + env, jobject_, CLASS_GET_PROXY, "setMaxVersions", + JMETHOD1("I", JPARAM(CLASS_GET_PROXY)), numVersions); +} + +Status +Get::SetFilter( + const char *filter, + JNIEnv *current_env) { + JNI_GET_ENV(current_env); + jstring filterString = env->NewStringUTF(filter); + return JniHelper::InvokeMethod( + env, jobject_, CLASS_GET_PROXY, "setFilter", + JMETHOD1(JPARAM(JAVA_STRING), JPARAM(CLASS_GET_PROXY)), filterString); +} + +} /* namespace hbase */ diff --git a/hbase-native-client/src/main/native/jni_impl/hbase_get.h b/hbase-native-client/src/main/native/jni_impl/hbase_get.h new file mode 100644 index 000000000000..8dcdcf013785 --- /dev/null +++ b/hbase-native-client/src/main/native/jni_impl/hbase_get.h @@ -0,0 +1,49 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef HBASE_JNI_IMPL_GET_H_ +#define HBASE_JNI_IMPL_GET_H_ + +#include + +#include + +#include "hbase_row.h" +#include "hbase_status.h" +#include "jnihelper.h" + +namespace hbase { + +class Get : public Row { +public: + Get() {} + + ~Get() {} + + Status AddColumn(const byte_t *family, const size_t familyLen, + const byte_t *qualifier, const size_t qualifierLen, JNIEnv *current_env=NULL); + + Status SetNumVersions(const int32_t numVersions, JNIEnv *current_env=NULL); + + Status SetFilter(const char *filter, JNIEnv *current_env=NULL); + + friend class HTable; +}; + +} /* namespace hbase */ + +#endif /* HBASE_JNI_IMPL_GET_H_ */ diff --git a/hbase-native-client/src/main/native/jni_impl/hbase_mutations.cc b/hbase-native-client/src/main/native/jni_impl/hbase_mutations.cc new file mode 100644 index 000000000000..35462607f6a5 --- /dev/null +++ b/hbase-native-client/src/main/native/jni_impl/hbase_mutations.cc @@ -0,0 +1,182 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#line 19 "hbase_mutations.cc" // ensures short filename in logs. + +#include +#include + +#include "hbase_mutations.h" + +#include "hbase_macros.h" +#include "hbase_msgs.h" +#include "jnihelper.h" + +namespace hbase { + +extern "C" { + +/** + * Sets the table name for the mutation. + */ +HBASE_API int32_t +hb_mutation_set_table( + hb_mutation_t mutation, + const char *table, + size_t const table_len) { + RETURN_IF_INVALID_PARAM((mutation == NULL), + Msgs::ERR_MUTATION_NULL); + RETURN_IF_INVALID_PARAM((table == NULL), + Msgs::ERR_TBL_NULL); + RETURN_IF_INVALID_PARAM((table_len <= 0), + Msgs::ERR_TBL_LEN, table_len); + + return reinterpret_cast(mutation)-> + SetTable(table, table_len).GetCode(); +} + +/** + * Sets the row key for the mutation. + */ +HBASE_API int32_t +hb_mutation_set_row( + hb_mutation_t mutation, + const byte_t *rowkey, + const size_t rowkey_len) { + RETURN_IF_INVALID_PARAM((mutation == NULL), + Msgs::ERR_MUTATION_NULL); + RETURN_IF_INVALID_PARAM((rowkey == NULL), + Msgs::ERR_KEY_NULL); + RETURN_IF_INVALID_PARAM((rowkey_len <= 0), + Msgs::ERR_KEY_LEN, rowkey_len); + + return reinterpret_cast(mutation)-> + SetRowKey(rowkey, rowkey_len).GetCode(); +} + +/** + * Optional (default = DURABILITY_USE_DEFAULT). Sets the durability + * for this mutation. Note that RegionServers prior to 0.94.7 will + * only honor SKIP_WAL. + */ +HBASE_API int32_t +hb_mutation_set_durability( + hb_mutation_t mutation, + const hb_durability_t durability) { + RETURN_IF_INVALID_PARAM((mutation == NULL), + Msgs::ERR_MUTATION_NULL); + + return reinterpret_cast(mutation)-> + SetDurability(durability).GetCode(); +} + +/** + * Sets whether or not this RPC can be buffered on the client side. + * + * Currently only puts and deletes can be buffered. Calling this for + * any other mutation type will return EINVAL. + * + * The default is 'true'. + */ +HBASE_API int32_t +hb_mutation_set_bufferable( + hb_mutation_t mutation, + const bool bufferable) { + RETURN_IF_INVALID_PARAM((mutation == NULL), + Msgs::ERR_MUTATION_NULL); + + return reinterpret_cast(mutation)-> + SetBufferable(bufferable).GetCode(); +} + +/** + * Frees up any resource held by the mutation structure. + */ +HBASE_API int32_t +hb_mutation_destroy(hb_mutation_t mutation) { + RETURN_IF_INVALID_PARAM((mutation == NULL), + Msgs::ERR_MUTATION_NULL); + + delete reinterpret_cast(mutation); + return 0; +} + +} /* extern "C" */ + +Status +Mutation::SetDurability( + const hb_durability_t durability, + JNIEnv *current_env) { + JNI_GET_ENV(current_env); + return JniHelper::InvokeMethod( + env, jobject_, CLASS_MUTATION_PROXY, + "setDurability", "(I)V", (int32_t)durability); +} + +Status inline +Mutation::SetBufferable( + const bool bufferable, + JNIEnv *current_env) { + return ENOTSUP; +} + +Status +BufferableRpc::SetBufferable( + const bool bufferable, + JNIEnv *current_env) { + JNI_GET_ENV(current_env); + return JniHelper::InvokeMethod( + env, jobject_, CLASS_MUTATION_PROXY, + "setBufferable", "(Z)V", (jboolean)bufferable); +} + +Status +Mutation::AddColumn( + const byte_t *f, + const size_t fLen, + const byte_t *q, + const size_t qLen, + const byte_t *v, + const size_t vLen, + const int64_t ts, + JNIEnv *current_env) { + JNI_GET_ENV(current_env); + + JniResult family = JniHelper::CreateJavaByteArray(env, f, 0, fLen); + RETURN_IF_ERROR(family); + + jobject qualObj = NULL; + if (q) { + JniResult qualifier = JniHelper::CreateJavaByteArray(env, q, 0, qLen); + RETURN_IF_ERROR(qualifier); + qualObj = qualifier.GetObject(); + } + + jobject valueObj = NULL; + if (v) { + JniResult value = JniHelper::CreateJavaByteArray(env, v, 0, vLen); + RETURN_IF_ERROR(value); + valueObj = value.GetObject(); + } + + return JniHelper::InvokeMethod( + env, jobject_, CLASS_MUTATION_PROXY, + "addColumn", "([B[BJ[B)L"CLASS_MUTATION_PROXY";", + family.GetObject(), qualObj, (jlong)ts, valueObj); +} + +} /* namespace hbase */ diff --git a/hbase-native-client/src/main/native/jni_impl/hbase_mutations.h b/hbase-native-client/src/main/native/jni_impl/hbase_mutations.h new file mode 100644 index 000000000000..46f184d67a22 --- /dev/null +++ b/hbase-native-client/src/main/native/jni_impl/hbase_mutations.h @@ -0,0 +1,59 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef HBASE_JNI_IMPL_MUTATIONS_H_ +#define HBASE_JNI_IMPL_MUTATIONS_H_ + +#include + +#include + +#include "hbase_row.h" +#include "hbase_status.h" +#include "jnihelper.h" + +namespace hbase { + +class Mutation : public Row { +public: + Status SetDurability(const hb_durability_t durability, JNIEnv *current_env=NULL); + + Status AddColumn(const byte_t *family, const size_t family_len, + const byte_t *qualifier, const size_t qualifierLen, const byte_t *value, + const size_t valueLen, const int64_t ts=HBASE_LATEST_TIMESTAMP, JNIEnv *current_env=NULL); + + virtual Status SetBufferable(const bool bufferable, JNIEnv *current_env=NULL); + + friend class HTable; + +protected: + Mutation(bool isIncrement) : isIncrement_(isIncrement) {} + + bool isIncrement_; +}; + +class BufferableRpc : public Mutation { +protected: + BufferableRpc() : Mutation(false) { } + +public: + Status SetBufferable(const bool bufferable, JNIEnv *current_env=NULL); +}; + +} /* namespace hbase */ + +#endif /* HBASE_JNI_IMPL_MUTATIONS_H_ */ diff --git a/hbase-native-client/src/main/native/jni_impl/hbase_objects.cc b/hbase-native-client/src/main/native/jni_impl/hbase_objects.cc new file mode 100644 index 000000000000..5771ba600c94 --- /dev/null +++ b/hbase-native-client/src/main/native/jni_impl/hbase_objects.cc @@ -0,0 +1,39 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#include +#include + +#include "jnihelper.h" + +namespace hbase { + +JniObject::~JniObject() { + Destroy(); +} + +Status +JniObject::Destroy(JNIEnv *current_env) { + if (jobject_ != NULL) { + JNI_GET_ENV(current_env); + env->DeleteGlobalRef(jobject_); + jobject_= NULL; + } + return Status::Success; +} + +} /* namespace hbase */ diff --git a/hbase-native-client/src/main/native/jni_impl/hbase_put.cc b/hbase-native-client/src/main/native/jni_impl/hbase_put.cc new file mode 100644 index 000000000000..9b44c9a48f7d --- /dev/null +++ b/hbase-native-client/src/main/native/jni_impl/hbase_put.cc @@ -0,0 +1,132 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#line 19 "hbase_put.cc" // ensures short filename in logs. + +#include +#include +#include + +#include + +#include "hbase_put.h" + +#include "hbase_macros.h" +#include "hbase_msgs.h" +#include "jnihelper.h" + +namespace hbase { + +extern "C" { + +/** + * Create empty put object with row key set to 'rowkey'. + */ +HBASE_API int32_t +hb_put_create( + const byte_t *rowkey, + const size_t rowkey_len, + hb_put_t *put_ptr) { + RETURN_IF_INVALID_PARAM((rowkey == NULL), + Msgs::ERR_KEY_NULL); + RETURN_IF_INVALID_PARAM((rowkey_len <= 0), + Msgs::ERR_KEY_LEN, rowkey_len); + RETURN_IF_INVALID_PARAM((put_ptr == NULL), + Msgs::ERR_PUTPTR_NULL); + + *put_ptr = NULL; + Put *put = new Put(); + Status status = put->Init( + CLASS_PUT_PROXY, rowkey, rowkey_len); + if (UNLIKELY(!status.ok())) { + delete put; + return status.GetCode(); + } + *put_ptr = reinterpret_cast (put); + return 0; +} + +HBASE_API int32_t +hb_put_add_cell( + hb_put_t p, + const hb_cell_t *cell) { + RETURN_IF_INVALID_PARAM((cell == NULL), + Msgs::ERR_CELLPTR_NULL); + + return hb_put_add_ts_column(p, + cell->family, cell->family_len, + cell->qualifier, cell->qualifier_len, + cell->value, cell->value_len, cell->ts); +} + +/** + * Adds a cell (key-value) with latest timestamp to the put. + */ +HBASE_API int32_t +hb_put_add_column( + hb_put_t p, + const byte_t *family, + const size_t family_len, + const byte_t *qualifier, + const size_t qualifier_len, + const byte_t *value, + const size_t value_len) { + return hb_put_add_ts_column(p, + family, family_len, + qualifier, qualifier_len, + value, value_len, HBASE_LATEST_TIMESTAMP); +} + +/** + * Adds a cell (key-value) with the specified timestamp to the put. + */ +HBASE_API int32_t +hb_put_add_ts_column( + hb_put_t p, + const byte_t *family, + const size_t family_len, + const byte_t *qualifier, + const size_t qualifier_len, + const byte_t *value, + const size_t value_len, + const int64_t timestamp) { + RETURN_IF_INVALID_PARAM((p == NULL), + Msgs::ERR_PUT_NULL); + RETURN_IF_INVALID_PARAM((family == NULL), + Msgs::ERR_FAMILY_NULL); + RETURN_IF_INVALID_PARAM((family_len <= 0), + Msgs::ERR_FAMILY_LEN, family_len); + RETURN_IF_INVALID_PARAM((qualifier == NULL), + Msgs::ERR_QUAL_NULL); + RETURN_IF_INVALID_PARAM((qualifier_len <= 0), + Msgs::ERR_QUAL_LEN, qualifier_len); + RETURN_IF_INVALID_PARAM((value == NULL), + Msgs::ERR_VALUE_NULL); + RETURN_IF_INVALID_PARAM((value_len <= 0), + Msgs::ERR_VALUE_LEN, value_len); + RETURN_IF_INVALID_PARAM((timestamp <= 0), + Msgs::ERR_TIMESTAMP1, timestamp); + + return reinterpret_cast(p)-> + AddColumn(family, family_len, + qualifier, qualifier_len, + value, value_len, timestamp).GetCode(); +} + +} /* extern "C" */ + +} /* namespace hbase */ diff --git a/hbase-native-client/src/main/native/jni_impl/hbase_put.h b/hbase-native-client/src/main/native/jni_impl/hbase_put.h new file mode 100644 index 000000000000..152316a3ad7a --- /dev/null +++ b/hbase-native-client/src/main/native/jni_impl/hbase_put.h @@ -0,0 +1,35 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef HBASE_JNI_IMPL_PUT_H_ +#define HBASE_JNI_IMPL_PUT_H_ + +#include "hbase_mutations.h" +#include "hbase_status.h" + +namespace hbase { + +class Put : public BufferableRpc { +public: + Put() {} + + ~Put() {} +}; + +} /* namespace hbase */ + +#endif /* HBASE_JNI_IMPL_PUT_H_ */ diff --git a/hbase-native-client/src/main/native/jni_impl/hbase_result.cc b/hbase-native-client/src/main/native/jni_impl/hbase_result.cc new file mode 100644 index 000000000000..49dfe6c506da --- /dev/null +++ b/hbase-native-client/src/main/native/jni_impl/hbase_result.cc @@ -0,0 +1,430 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#line 19 "hbase_result.cc" // ensures short filename in logs. + +#include +#include + +#include "hbase_macros.h" +#include "hbase_msgs.h" +#include "hbase_result.h" +#include "jnihelper.h" + +namespace hbase { + +extern "C" { + +/** + * Frees any resources held by the hb_result_t object. + */ +HBASE_API int32_t +hb_result_destroy(hb_result_t r) { + RETURN_IF_INVALID_PARAM((r == NULL), + Msgs::ERR_RESULT_NULL); + + delete reinterpret_cast(r); + return 0; +} + +/** + * Returns the row key of this hb_result_t object. + * This buffer is valid until hb_result_destroy() is called. + * Callers should not modify this buffer. + */ +HBASE_API int32_t +hb_result_get_key( + const hb_result_t r, + const byte_t **key_ptr, + size_t *key_length_ptr) { + RETURN_IF_INVALID_PARAM((r == NULL), + Msgs::ERR_RESULT_NULL); + RETURN_IF_INVALID_PARAM((key_ptr == NULL), + Msgs::ERR_TBLPTR_NULL); + RETURN_IF_INVALID_PARAM((key_length_ptr == NULL), + Msgs::ERR_KEY_LENPTR); + + return reinterpret_cast(r)-> + GetRowKey(key_ptr, key_length_ptr).GetCode(); +} + +/** + * Returns the table name of this hb_result_t object. + * This buffer is valid until hb_result_destroy() is called. + * Callers should not modify this buffer. + */ +HBASE_API int32_t +hb_result_get_table( + const hb_result_t r, + const char **table_ptr, + size_t *table_length_ptr) { + RETURN_IF_INVALID_PARAM((r == NULL), + Msgs::ERR_RESULT_NULL); + RETURN_IF_INVALID_PARAM((table_ptr == NULL), + Msgs::ERR_TBLPTR_NULL); + RETURN_IF_INVALID_PARAM((table_length_ptr == NULL), + Msgs::ERR_TBL_LENPTR_NULL); + + return reinterpret_cast(r)-> + GetTable(table_ptr, table_length_ptr).GetCode(); +} + +/** + * HBase 0.96 or later. + * Returns the namespace of this hb_result_t object. + * This buffer is valid until hb_result_destroy() is called. + * Callers should not modify this buffer. + */ +HBASE_API int32_t +hb_result_get_namespace( + const hb_result_t result, + const char **name_space, + size_t *name_space_length_ptr) { + return ENOSYS; +} + +/** + * Returns the total number of cells in this hb_result_t object. + */ +HBASE_API int32_t +hb_result_get_cell_count( + const hb_result_t r, + size_t *cell_count_ptr) { + RETURN_IF_INVALID_PARAM((r == NULL), + Msgs::ERR_RESULT_NULL); + RETURN_IF_INVALID_PARAM((cell_count_ptr == NULL), + Msgs::ERR_CELL_COUNTPTR_NULL); + + return reinterpret_cast(r)-> + GetCellCount(cell_count_ptr).GetCode(); +} + +/** + * Returns the pointer to a constant hb_cell_t structure with the most recent + * value of the given column. The buffers are valid until hb_result_destroy() + * is called. Callers should not modify these buffers. + * + * @returns 0 if operation succeeds. + * @returns ENOENT if a matching cell is not found. + */ +HBASE_API int32_t +hb_result_get_cell( + const hb_result_t r, + const byte_t *family, + const size_t family_len, + const byte_t *qualifier, + const size_t qualifier_len, + const hb_cell_t **cell_ptr) { + RETURN_IF_INVALID_PARAM((r == NULL), + Msgs::ERR_RESULT_NULL); + RETURN_IF_INVALID_PARAM((family == NULL), + Msgs::ERR_FAMILY_NULL); + RETURN_IF_INVALID_PARAM((family_len <= 0), + Msgs::ERR_FAMILY_LEN, family_len); + RETURN_IF_INVALID_PARAM((qualifier == NULL), + Msgs::ERR_QUAL_NULL); + RETURN_IF_INVALID_PARAM((qualifier_len <= 0), + Msgs::ERR_QUAL_LEN, qualifier_len); + RETURN_IF_INVALID_PARAM((cell_ptr == NULL), + Msgs::ERR_CELLPTR_NULL); + + return reinterpret_cast(r)-> + GetCell(family, family_len, qualifier, + qualifier_len, cell_ptr).GetCode(); +} + +/** + * Returns the pointer to a constant hb_cell_t structure containing the cell + * value at the given 0 based index of the result. The buffers are valid until + * hb_result_destroy() is called. Callers should not modify these buffers. + * + * @returns 0 if operation succeeds. + * @returns ERANGE if the index is outside the bounds. + */ +HBASE_API int32_t +hb_result_get_cell_at( + const hb_result_t r, + const size_t index, + const hb_cell_t **cell_ptr) { + RETURN_IF_INVALID_PARAM((r == NULL), + Msgs::ERR_RESULT_NULL); + RETURN_IF_INVALID_PARAM((cell_ptr == NULL), + Msgs::ERR_CELLPTR_NULL); + + return reinterpret_cast(r)-> + GetCellAt(index, cell_ptr).GetCode(); +} + +/** + * Returns the array of pointers to constant hb_cell_t structures with the cells + * of the result. The buffers are valid until hb_result_destroy() is called. The + * variable pointed by num_cells_ptr is set to the number of cells in the result. + * + * Calling this function multiple times for the same hb_result_t may return + * the same buffers. Callers should not modify these buffers. + */ +HBASE_API int32_t +hb_result_get_cells( + const hb_result_t r, + const hb_cell_t ***cells_ptr, + size_t *num_cells) { + RETURN_IF_INVALID_PARAM((r == NULL), + Msgs::ERR_RESULT_NULL); + + return reinterpret_cast(r)-> + GetCells(cells_ptr, num_cells).GetCode(); +} + +} /* extern "C" */ + +/** + * Wraps a JNI object handle into @link Result class + */ +hb_result_t +Result::From( + const jthrowable jthr, + const jobject result, + JNIEnv *env) { + if (result) { + // TODO: may be wrap exception if not null + return (hb_result_t) new Result(env->NewGlobalRef(result)); + } + return NULL; +} + +void +Result::FreeCell(hb_cell_t *cell_ptr) { + if (cell_ptr) { + if (cell_ptr->family) { + delete[] cell_ptr->family; + cell_ptr->family = NULL; + } + if (cell_ptr->qualifier) { + delete[] cell_ptr->qualifier; + cell_ptr->qualifier = NULL; + } + if (cell_ptr->value) { + delete[] cell_ptr->value; + cell_ptr->value = NULL; + } + } +} + +Result::Result(jobject resultProxy) +: JniObject(resultProxy), + tableName_(NULL), + tableNameLen_(0), + rowKey_(NULL), + rowKeyLen_(0), + cells_(NULL), + cellCount_(0) { + Init(); +} + +Result::~Result() { + if (tableName_ != NULL) { + delete[] tableName_; + tableName_ = NULL; + } + + if (rowKey_ != NULL) { + delete[] rowKey_; + rowKey_ = NULL; + } + + if (cells_ != NULL) { + for (size_t i = 0; i < cellCount_; ++i) { + if (cells_[i]) { + FreeCell(cells_[i]); + delete cells_[i]; + } + } + delete[] cells_; + cells_ = NULL; + } +} + +Status +Result::Init(JNIEnv* current_env) { + JNI_GET_ENV(current_env); + + JniResult result = JniHelper::InvokeMethod( + env, jobject_, CLASS_RESULT_PROXY, "getTable", "()[B"); + RETURN_IF_ERROR(result); + RETURN_IF_ERROR(JniHelper::CreateByteArray( + env, result.GetObject(), + (byte_t **)&tableName_, &tableNameLen_)); + + JniResult row = JniHelper::InvokeMethod( + env, jobject_, CLASS_RESULT_PROXY, "getRowKey", "()[B"); + RETURN_IF_ERROR(row); + RETURN_IF_ERROR(JniHelper::CreateByteArray( + env, row.GetObject(), &rowKey_, &rowKeyLen_)); + + JniResult count = JniHelper::InvokeMethod( + env, jobject_, CLASS_RESULT_PROXY, "getCellCount", "()I"); + cellCount_ = (count.ok() ? count.GetValue().i : -1); + + return Status::Success; +} + +Status +Result::GetTable( + const char **table, + size_t *tableLength, + JNIEnv *current_env) { + if (table) { + *table = tableName_; + *tableLength = tableNameLen_; + } + return Status::Success; +} + +Status +Result::GetRowKey( + const byte_t **rowKey, + size_t *rowKeyLen, + JNIEnv *current_env) { + if (rowKey) { + *rowKey = rowKey_; + *rowKeyLen = rowKeyLen_; + } + return Status::Success; +} + +Status +Result::GetCellCount( + size_t *count_ptr, + JNIEnv *current_env) { + if (count_ptr) { + *count_ptr = cellCount_; + } + return Status::Success; +} + +Status +Result::GetCell( + const byte_t *f, + const size_t f_len, + const byte_t *q, + const size_t q_len, + const hb_cell_t **cell_ptr, + JNIEnv *current_env) { + if (!cellCount_) { + return Status::ENoEntry; + } + JNI_GET_ENV(current_env); + + JniResult family = JniHelper::CreateJavaByteArray(env, f, 0, f_len); + RETURN_IF_ERROR(family); + + JniResult qualifier = JniHelper::CreateJavaByteArray(env, q, 0, q_len); + RETURN_IF_ERROR(qualifier); + + JniResult result = JniHelper::InvokeMethod( + env, jobject_, CLASS_RESULT_PROXY, "indexOf", + "([B[B)I", family.GetObject(), qualifier.GetObject()); + RETURN_IF_ERROR(result); + + int32_t cellIndex = result.GetValue().i; + if (cellIndex < 0) { + return Status::ENoEntry; + } + + return GetCellAt(cellIndex, cell_ptr, env); +} + +/** + * Precondition: GetCellCount() and GetRowKey() has been called. + */ +Status +Result::GetCellAt( + const size_t index, + const hb_cell_t **cell_ptr, + JNIEnv *current_env) { + if (UNLIKELY(index < 0 || index >= cellCount_)) { + return Status::ERange; + } + + EnsureCells(); + if (!cells_[index]) { + hb_cell_t *cell = cells_[index] = new hb_cell_t(); + cell->row = rowKey_; + cell->row_len = rowKeyLen_; + + JNI_GET_ENV(current_env); + + JniResult result = JniHelper::InvokeMethod( + env, jobject_, CLASS_RESULT_PROXY, "getFamily", "(I)[B", index); + RETURN_IF_ERROR(result); + RETURN_IF_ERROR(JniHelper::CreateByteArray( + env, result.GetObject(), &cell->family, &cell->family_len)); + + result = JniHelper::InvokeMethod( + env, jobject_, CLASS_RESULT_PROXY, "getQualifier", "(I)[B", index); + RETURN_IF_ERROR(result); + RETURN_IF_ERROR(JniHelper::CreateByteArray( + env, result.GetObject(), &cell->qualifier, &cell->qualifier_len)); + + result = JniHelper::InvokeMethod( + env, jobject_, CLASS_RESULT_PROXY, "getValue", "(I)[B", index); + RETURN_IF_ERROR(result); + RETURN_IF_ERROR(JniHelper::CreateByteArray( + env, result.GetObject(), &cell->value, &cell->value_len)); + + result = JniHelper::InvokeMethod( + env, jobject_, CLASS_RESULT_PROXY, "getTS", "(I)J", index); + RETURN_IF_ERROR(result); + cell->ts = result.GetValue().j; + } + + if (cell_ptr) { + *(const_cast(cell_ptr)) = cells_[index]; + } + + return Status::Success; +} + +Status +Result::GetCells( + const hb_cell_t ***cell_ptr, + size_t *num_cells, + JNIEnv *current_env) { + Status status = Status::Success; + if (cellCount_) { + JNI_GET_ENV(current_env); + EnsureCells(); + for (size_t i = 0; i < cellCount_; ++i) { + if (!cells_[i]) { + GetCellAt(i, NULL, env); + } + } + } + + *(const_cast(cell_ptr)) = cells_; + *num_cells = cellCount_; + return status; +} + +inline void +Result::EnsureCells() { + if (cellCount_ > 0 && cells_ == NULL) { + cells_ = new hb_cell_t*[cellCount_](); + } +} + +} /* namespace hbase */ diff --git a/hbase-native-client/src/main/native/jni_impl/hbase_result.h b/hbase-native-client/src/main/native/jni_impl/hbase_result.h new file mode 100644 index 000000000000..159dd7b5b6a4 --- /dev/null +++ b/hbase-native-client/src/main/native/jni_impl/hbase_result.h @@ -0,0 +1,71 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef HBASE_JNI_IMPL_RESULT_H_ +#define HBASE_JNI_IMPL_RESULT_H_ + +#include + +#include + +#include "hbase_status.h" +#include "jnihelper.h" + +namespace hbase { + +class Result : public JniObject { +public: + ~Result(); + + Status Init(JNIEnv *current_env=NULL); + + Status GetTable(const char **table=NULL, size_t *tableLength=0, JNIEnv *current_env=NULL); + + Status GetRowKey(const byte_t **rowKey=NULL, size_t *rowKeyLength=0, JNIEnv *current_env=NULL); + + Status GetCellCount(size_t *countPtr=NULL, JNIEnv *current_env=NULL); + + Status GetCell(const byte_t *family, const size_t family_len, const byte_t *qualifier, + const size_t qualifier_len, const hb_cell_t **cell_ptr, JNIEnv *current_env=NULL); + + Status GetCellAt(const size_t index, const hb_cell_t **cell_ptr, JNIEnv *current_env=NULL); + + Status GetCells(const hb_cell_t ***cell_ptr, size_t *num_cells, JNIEnv *current_env=NULL); + + static hb_result_t From(jthrowable jthr, jobject result, JNIEnv *env); + +protected: + Result(jobject resultProxy); + + void EnsureCells(); + + static void FreeCell(hb_cell_t *cell_ptr); + +private: + char *tableName_; + size_t tableNameLen_; + + byte_t *rowKey_; + size_t rowKeyLen_; + + hb_cell_t **cells_; + size_t cellCount_; +}; + +} /* namespace hbase */ + +#endif /* HBASE_JNI_IMPL_RESULT_H_ */ diff --git a/hbase-native-client/src/main/native/jni_impl/hbase_row.cc b/hbase-native-client/src/main/native/jni_impl/hbase_row.cc new file mode 100644 index 000000000000..36669c944bc6 --- /dev/null +++ b/hbase-native-client/src/main/native/jni_impl/hbase_row.cc @@ -0,0 +1,85 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#line 19 "hbase_row.cc" // ensures short filename in logs. + +#include +#include + +#include "hbase_row.h" + +#include "hbase_macros.h" +#include "jnihelper.h" + +namespace hbase { + +Status +Row::Init( + const char *CLASS_NAME, + const byte_t *rowKey, + const size_t rowKeyLen, + JNIEnv *current_env) { + JNI_GET_ENV(current_env); + JniResult result = JniHelper::CreateJavaByteArray( + env, rowKey, 0, rowKeyLen); + RETURN_IF_ERROR(result); + result = JniHelper::NewObject( + env, CLASS_NAME, "([B)V", result.GetObject()); + if (result.ok()) { + jobject_ = env->NewGlobalRef(result.GetObject()); + } + return result; +} + +Status +Row::SetRowKey( + const byte_t *rowkey, + const size_t rowkey_len, + JNIEnv *current_env) { + JNI_GET_ENV(current_env); + JniResult rowKey = JniHelper::CreateJavaByteArray( + env, rowkey, 0, rowkey_len); + RETURN_IF_ERROR(rowKey); + return JniHelper::InvokeMethod( + env, jobject_, CLASS_ROW_PROXY, + "setRow", "([B)V", rowKey.GetObject()); +} + +Status +Row::SetTable( + const char *table, + const size_t tableLen, + JNIEnv *current_env) { + JNI_GET_ENV(current_env); + JniResult tableName = JniHelper::CreateJavaByteArray( + env, (const byte_t *)table, 0, tableLen); + RETURN_IF_ERROR(tableName); + return JniHelper::InvokeMethod( + env, jobject_, CLASS_ROW_PROXY, + "setTable", "([B)V", tableName.GetObject()); +} + +Status +Row::SetTS( + const int64_t ts, + JNIEnv *current_env) { + JNI_GET_ENV(current_env); + return JniHelper::InvokeMethod( + env, jobject_, CLASS_ROW_PROXY, "setTS", "(I)V", ts); +} + +} /* namespace hbase */ diff --git a/hbase-native-client/src/main/native/jni_impl/hbase_row.h b/hbase-native-client/src/main/native/jni_impl/hbase_row.h new file mode 100644 index 000000000000..4e99f6824d6e --- /dev/null +++ b/hbase-native-client/src/main/native/jni_impl/hbase_row.h @@ -0,0 +1,50 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef HBASE_JNI_IMPL_ROW_H_ +#define HBASE_JNI_IMPL_ROW_H_ + +#include + +#include + +#include "hbase_status.h" +#include "jnihelper.h" + +namespace hbase { + +class Row : public JniObject { +public: + Row() {} + + ~Row() {} + + Status Init(const char *CLASS_NAME, + const byte_t *rowKey, const size_t rowKeyLen, JNIEnv *current_env=NULL); + + Status SetRowKey(const byte_t *rowKey, const size_t rowKeyLen, JNIEnv *current_env=NULL); + + Status SetTable(const char *tableName, const size_t tableNameLen, JNIEnv *current_env=NULL); + + Status SetTS(const int64_t ts, JNIEnv *current_env=NULL); + + friend class HTable; +}; + +} /* namespace hbase */ + +#endif /* HBASE_JNI_IMPL_ROW_H_ */ diff --git a/hbase-native-client/src/main/native/jni_impl/hbase_scanner.cc b/hbase-native-client/src/main/native/jni_impl/hbase_scanner.cc new file mode 100644 index 000000000000..1ef5009d40cd --- /dev/null +++ b/hbase-native-client/src/main/native/jni_impl/hbase_scanner.cc @@ -0,0 +1,381 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#line 19 "hbase_scanner.cc" // ensures short filename in logs. + +#include + +#include "hbase_scanner.h" + +#include "hbase_client.h" +#include "hbase_msgs.h" +#include "hbase_result.h" + +#include "org_apache_hadoop_hbase_jni_CallbackHandlers.h" + +namespace hbase { + +extern "C" { + +/* + * Class: org_apache_hadoop_hbase_jni_CallbackHandlers + * Method: scanNextCallBack + * Signature: (Ljava/lang/Throwable;JJ[Ljava/lang/Object;IJ)V + */ +HBASE_API void JNICALL +Java_org_apache_hadoop_hbase_jni_CallbackHandlers_scanNextCallBack( + JNIEnv *env, jclass clazz, jthrowable jthr, jlong cb, + jlong scanner, jobjectArray results, jint num_results, jlong extra) { + if (cb) { + hb_result_t *rows = num_results ? new hb_result_t[num_results] : NULL; + for (int i = 0; i < num_results; ++i) { + jobject result = env->GetObjectArrayElement(results, i); + rows[i] = Result::From(jthr, result, env); + } + hb_scanner_cb scanner_next_cb = (hb_scanner_cb)cb; + scanner_next_cb(JniHelper::ErrorFromException(env, jthr), + (hb_scanner_t)scanner, + rows, + num_results, + (void*)extra); + if (rows) { + delete[] rows; + } + } +} + +/* + * Class: org_apache_hadoop_hbase_jni_CallbackHandlers + * Method: scannerCloseCallBack + * Signature: (Ljava/lang/Throwable;JJJ)V + */ +HBASE_API void JNICALL +Java_org_apache_hadoop_hbase_jni_CallbackHandlers_scannerCloseCallBack( + JNIEnv *env, jclass clazz, jthrowable jthr, + jlong cb, jlong scanner, jlong extra) { + if (cb) { + hb_scanner_destroy_cb close_cb = (hb_scanner_destroy_cb) cb; + close_cb(JniHelper::ErrorFromException(env, jthr), + (hb_scanner_t)scanner, + (void*)extra); + } + delete reinterpret_cast(scanner); +} + +/** + * Creates a client side row scanner. The returned scanner is not thread safe. + * No RPC will be invoked until the call to fetch the next set of rows is made. + * You can set the various attributes of this scanner until that point. + * @returns 0 on success, non-zero error code in case of failure. + */ +HBASE_API int32_t +hb_scanner_create( + hb_client_t client, + hb_scanner_t *scanner_ptr) { + RETURN_IF_INVALID_PARAM((client == NULL), + Msgs::ERR_CLIENT_NULL); + RETURN_IF_INVALID_PARAM((scanner_ptr == NULL), + Msgs::ERR_SCANNERPTR_NULL); + + HScanner *scanner = new HScanner(); + if (scanner == NULL) return ENOMEM; + + Status status = scanner->Init( + reinterpret_cast(client)); + if (status.ok()) { + *scanner_ptr = reinterpret_cast (scanner); + } else { + *scanner_ptr = NULL; + delete scanner_ptr; + } + + return status.GetCode(); +} + +/** + * Request the next set of results from the server. You can set the maximum + * number of rows returned by this call using hb_scanner_set_num_max_rows(). + */ +HBASE_API int32_t +hb_scanner_next( + hb_scanner_t scanner, + hb_scanner_cb cb, + void *extra) { + if (UNLIKELY((scanner == NULL))){ + HBASE_LOG_ERROR(Msgs::ERR_SCANNER_NULL); + if (cb) { + cb(EINVAL, scanner, NULL, 0, extra); + } + return 0; + } + + return reinterpret_cast(scanner)-> + NextRows(cb, extra).GetCode(); +} + +/** + * Close the scanner releasing any local and server side resources held. + * The call back is fired just before the scanner's memory is freed. + */ +HBASE_API int32_t +hb_scanner_destroy( + hb_scanner_t scanner, + hb_scanner_destroy_cb cb, + void *extra) { + if (UNLIKELY((scanner == NULL))){ + HBASE_LOG_ERROR(Msgs::ERR_SCANNER_NULL); + if (cb) { + cb(EINVAL, scanner, extra); + } + return 0; + } + + return reinterpret_cast(scanner)-> + Close(cb, extra).GetCode(); +} + +/** + * Set the table name for the scanner + */ +HBASE_API int32_t +hb_scanner_set_table( + hb_scanner_t scanner, + const char *table, + const size_t table_len) { + RETURN_IF_INVALID_PARAM((scanner == NULL), + Msgs::ERR_SCANNER_NULL); + RETURN_IF_INVALID_PARAM((table == NULL), + Msgs::ERR_TBL_NULL); + RETURN_IF_INVALID_PARAM((table_len <= 0), + Msgs::ERR_TBL_LEN, table_len); + + return reinterpret_cast(scanner)-> + SetTable(table, table_len).GetCode(); +} + +/** + * Set the name space for the scanner (0.96 and above) + */ +HBASE_API int32_t +hb_scanner_set_namespace( + hb_scanner_t scanner, + const char *name_space, + const size_t name_space_length) { + return ENOSYS; +} + +/** + * Specifies the start row key for this scanner (inclusive). + */ +HBASE_API int32_t +hb_scanner_set_start_row( + hb_scanner_t scanner, + const byte_t *start_row, + const size_t start_row_len) { + RETURN_IF_INVALID_PARAM((scanner == NULL), + Msgs::ERR_SCANNER_NULL); + RETURN_IF_INVALID_PARAM((start_row == NULL), + Msgs::ERR_START_ROW_NULL); + RETURN_IF_INVALID_PARAM((start_row_len <= 0), + Msgs::ERR_START_ROWL_LEN, start_row_len); + + return reinterpret_cast(scanner)-> + SetStartRow(start_row, start_row_len).GetCode(); +} + +/** + * Specifies the end row key for this scanner (exclusive). + */ +HBASE_API int32_t +hb_scanner_set_end_row( + hb_scanner_t scanner, + const byte_t *end_row, + const size_t end_row_len) { + RETURN_IF_INVALID_PARAM((scanner == NULL), + Msgs::ERR_SCANNER_NULL); + RETURN_IF_INVALID_PARAM((end_row == NULL), + Msgs::ERR_END_ROW_NULL); + RETURN_IF_INVALID_PARAM((end_row_len <= 0), + Msgs::ERR_END_ROWL_LEN, end_row_len); + + return reinterpret_cast(scanner)-> + SetEndRow(end_row, end_row_len).GetCode(); +} + +/** + * Sets the maximum versions of a column to fetch. + */ +HBASE_API int32_t +hb_scanner_set_num_versions( + hb_scanner_t scanner, + int8_t num_versions) { + RETURN_IF_INVALID_PARAM((scanner == NULL), + Msgs::ERR_SCANNER_NULL); + RETURN_IF_INVALID_PARAM((num_versions <= 0), + Msgs::ERR_NUM_VERSIONS, num_versions); + + return reinterpret_cast(scanner)-> + SetNumVersions(num_versions).GetCode(); +} + + +/** + * Sets the maximum number of rows to scan per call to hb_scanner_next(). + */ +HBASE_API int32_t +hb_scanner_set_num_max_rows( + hb_scanner_t scanner, + size_t cache_size) { + RETURN_IF_INVALID_PARAM((scanner == NULL), + Msgs::ERR_SCANNER_NULL); + RETURN_IF_INVALID_PARAM((cache_size <= 0), + Msgs::ERR_CACHE_SIZE, cache_size); + + return reinterpret_cast(scanner)-> + SetMaxNumRows(cache_size).GetCode(); +} + +} /* extern "C" */ + +#define ERROR_IF_SCANNER_OPEN() \ + if (is_open_) { \ + HBASE_LOG_ERROR(Msgs::ERR_SCANNER_OPEN); \ + return Status::EBusy; \ + } + +Status +HScanner::Init( + HBaseClient *client, + JNIEnv *current_env) { + JNI_GET_ENV(current_env); + + JniResult result = JniHelper::NewObject( + env, CLASS_SCANNER_PROXY, + JMETHOD1(JPARAM(CLASS_CLIENT_PROXY), "V"), + client->JObject()); + if (result.ok()) { + jobject_ = env->NewGlobalRef(result.GetObject()); + } + return result.GetCode(); +} + +Status +HScanner::NextRows( + hb_scanner_cb cb, + void *extra, + JNIEnv *current_env) { + JNI_GET_ENV(current_env); + + is_open_ = true; + return JniHelper::InvokeMethod( + env, jobject_, CLASS_SCANNER_PROXY, "next", "(JJJ)V", + (jlong) cb, (jlong) this, (jlong) extra).GetCode(); +} + +Status +HScanner::Close( + hb_scanner_destroy_cb cb, + void *extra, + JNIEnv *current_env) { + if (jobject_ != NULL) { + JNI_GET_ENV(current_env); + JniResult result = JniHelper::InvokeMethod( + env, jobject_, CLASS_SCANNER_PROXY, "close", "(JJJ)V", + (jlong) cb, (jlong) this, (jlong) extra); + env->DeleteGlobalRef(jobject_); + jobject_ = NULL; + return result.GetCode(); + } + return Status::Success; +} + +Status +HScanner::SetTable( + const char *table, + const size_t tableLen, + JNIEnv *current_env) { + ERROR_IF_SCANNER_OPEN(); + JNI_GET_ENV(current_env); + + JniResult tableName = JniHelper::CreateJavaByteArray( + env, (const byte_t *)table, 0, tableLen); + RETURN_IF_ERROR(tableName); + + return JniHelper::InvokeMethod( + env, jobject_, CLASS_SCANNER_PROXY, + "setTable", "([B)V", tableName.GetObject()); +} + +Status +HScanner::SetMaxNumRows( + const size_t cache_size, + JNIEnv *current_env) { + ERROR_IF_SCANNER_OPEN(); + JNI_GET_ENV(current_env); + + return JniHelper::InvokeMethod( + env, jobject_, CLASS_SCANNER_PROXY, + "setMaxNumRows", "(I)V", (int32_t)cache_size); +} + +Status +HScanner::SetNumVersions( + const size_t num_versions, + JNIEnv *current_env) { + ERROR_IF_SCANNER_OPEN(); + JNI_GET_ENV(current_env); + + return JniHelper::InvokeMethod( + env, jobject_, CLASS_SCANNER_PROXY, + "setNumVersions", "(I)V", (int32_t)num_versions); +} + +Status +HScanner::SetStartRow( + const byte_t *start_row, + const size_t start_row_len, + JNIEnv *current_env) { + ERROR_IF_SCANNER_OPEN(); + JNI_GET_ENV(current_env); + + JniResult startRow = JniHelper::CreateJavaByteArray( + env, (const byte_t *)start_row, 0, start_row_len); + RETURN_IF_ERROR(startRow); + + return JniHelper::InvokeMethod( + env, jobject_, CLASS_SCANNER_PROXY, + "setRow", "([B)V", startRow.GetObject()); +} + +Status +HScanner::SetEndRow( + const byte_t *end_row, + const size_t end_row_len, + JNIEnv *current_env) { + ERROR_IF_SCANNER_OPEN(); + JNI_GET_ENV(current_env); + + JniResult endRow = JniHelper::CreateJavaByteArray( + env, (const byte_t *)end_row, 0, end_row_len); + RETURN_IF_ERROR(endRow); + + return JniHelper::InvokeMethod( + env, jobject_, CLASS_SCANNER_PROXY, + "setEndRow", "([B)V", endRow.GetObject()); +} + +} /* namespace hbase */ diff --git a/hbase-native-client/src/main/native/jni_impl/hbase_scanner.h b/hbase-native-client/src/main/native/jni_impl/hbase_scanner.h new file mode 100644 index 000000000000..2a4a213fede0 --- /dev/null +++ b/hbase-native-client/src/main/native/jni_impl/hbase_scanner.h @@ -0,0 +1,59 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#include +#include + +#include + +#include "hbase_client.h" +#include "jnihelper.h" + +#ifndef HBASE_JNI_IMPL_SCANNER_H_ +#define HBASE_JNI_IMPL_SCANNER_H_ + +namespace hbase { + +class HScanner : public JniObject { +public: + HScanner() : is_open_(false) {} + + ~HScanner() {} + + Status Init(HBaseClient *client, JNIEnv *current_env=NULL); + + Status NextRows(hb_scanner_cb cb, void *extra, JNIEnv *current_env=NULL); + + Status Close(hb_scanner_destroy_cb cb, void *extra, JNIEnv *current_env=NULL); + + Status SetMaxNumRows(const size_t cache_size, JNIEnv *current_env=NULL); + + Status SetNumVersions(const size_t num_versions, JNIEnv *current_env=NULL); + + Status SetTable(const char *table, const size_t table_len, JNIEnv *current_env=NULL); + + Status SetStartRow(const byte_t *start_row, const size_t start_row_len, JNIEnv *current_env=NULL); + + Status SetEndRow(const byte_t *start_row, const size_t start_row_len, JNIEnv *current_env=NULL); + +private: + bool is_open_; +}; + +} /* namespace hbase */ + +#endif /* HBASE_JNI_IMPL_SCANNER_H_ */ diff --git a/hbase-native-client/src/main/native/jni_impl/hbase_table.cc b/hbase-native-client/src/main/native/jni_impl/hbase_table.cc new file mode 100644 index 000000000000..debbaac36a28 --- /dev/null +++ b/hbase-native-client/src/main/native/jni_impl/hbase_table.cc @@ -0,0 +1,197 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#line 19 "hbase_table.cc" // ensures short filename in logs. + +#include +#include + +#include "hbase_table.h" + +#include "hbase_client.h" +#include "hbase_config.h" +#include "hbase_msgs.h" +#include "hbase_mutations.h" +#include "hbase_put.h" +#include "jnihelper.h" + +namespace hbase { + +extern "C" { + +HBASE_API int32_t +hb_table_open( + const hb_connection_t conn, + const char *name_space, + const char *tableName, + hb_table_t *t_ptr) { + RETURN_IF_INVALID_PARAM((conn == NULL), + Msgs::ERR_CONN_NULL); + RETURN_IF_INVALID_PARAM((tableName == NULL), + Msgs::ERR_TBL_NAME_NULL); + RETURN_IF_INVALID_PARAM((t_ptr == NULL), + Msgs::ERR_HTBLPTR_NULL); + + if (name_space == NULL) { + HTable *table = new HTable(); + Status status = table->Init( + reinterpret_cast(conn), tableName); + if (status.ok()) { + *t_ptr = reinterpret_cast (table); + } else { + *t_ptr = NULL; + delete table; + } + return status.GetCode(); + } + + // HBase 0.96 not implemented yet + return ENOSYS; +} + +HBASE_API int32_t +hb_table_close(hb_table_t t) { + RETURN_IF_INVALID_PARAM((t == NULL), + Msgs::ERR_HTBL_NULL); + + HTable *table = reinterpret_cast(t); + Status status = table->Close(); + delete table; + return status.GetCode(); +} + +HBASE_API int32_t +hb_table_send_mutations( + hb_table_t t, + hb_mutation_t mutations[], + int32_t num_mutations) { + RETURN_IF_INVALID_PARAM((t == NULL), + Msgs::ERR_HTBL_NULL); + RETURN_IF_INVALID_PARAM((mutations == NULL), + Msgs::ERR_MUTATIONS_NULL); + RETURN_IF_INVALID_PARAM((num_mutations <= 0), + Msgs::ERR_NUM_MUTATIONS, num_mutations); + + return reinterpret_cast(t)-> + Batch(reinterpret_cast(mutations), + num_mutations).GetCode(); +} + +HBASE_API int32_t +hb_table_send_puts( + hb_table_t t, + hb_put_t puts[], + int32_t num_puts) { + RETURN_IF_INVALID_PARAM((t == NULL), + Msgs::ERR_HTBL_NULL); + RETURN_IF_INVALID_PARAM((puts == NULL), + Msgs::ERR_PUTS_NULL); + RETURN_IF_INVALID_PARAM((num_puts <= 0), + Msgs::ERR_NUM_PUTS, num_puts); + + return reinterpret_cast(t)-> + SendPut(reinterpret_cast(puts), + num_puts).GetCode(); +} + +HBASE_API int32_t +hb_table_flush_puts(hb_table_t t) { + RETURN_IF_INVALID_PARAM((t == NULL), + Msgs::ERR_HTBL_NULL); + + return reinterpret_cast(t)-> + Flush().GetCode(); +} + +} /* extern "C" */ + +HTable::~HTable() { + if (jobject_ != NULL) { + Close(); + } +} + +Status +HTable::Init( + const HBaseConfiguration *conf, + const char *tableName, + JNIEnv *current_env) { + JNI_GET_ENV(current_env); + jstring tableNameString = env->NewStringUTF(tableName); + JniResult result = JniHelper::NewObject( + env, CLASS_TABLE_PROXY, + JMETHOD2(JPARAM(HADOOP_CONF), JPARAM(JAVA_STRING), "V"), + conf->GetConf(), tableNameString); + if (result.ok()) { + jobject_ = env->NewGlobalRef(result.GetObject()); + JniHelper::InvokeMethod(env, jobject_, + CLASS_TABLE_PROXY, "setAutoFlush", "(Z)V", (jboolean)0); + } + + return result; +} + +Status +HTable::Close(JNIEnv *current_env) { + if (jobject_ != NULL) { + JNI_GET_ENV(current_env); + JniResult result = JniHelper::InvokeMethod( + env, jobject_, CLASS_TABLE_PROXY, "close", "()V"); + env->DeleteGlobalRef(jobject_); + jobject_ = NULL; + } + return Status::Success; +} + +Status +HTable::Batch( + Mutation *mutations[], + size_t num_mutations, + JNIEnv *current_env) { + JNI_GET_ENV(current_env); + JniResult list = JniHelper::CreateJniObjectList(env, + reinterpret_cast(mutations), num_mutations); + RETURN_IF_ERROR(list); + + return JniHelper::InvokeMethod(env, + jobject_, CLASS_TABLE_PROXY, "batch", + JMETHOD1(JPARAM(JAVA_LIST), JARRPARAM(JAVA_OBJECT)), + list.GetObject()); +} + +Status +HTable::SendPut( + Put *puts[], + size_t num_puts, + JNIEnv *current_env) { + JNI_GET_ENV(current_env); + JniResult list = JniHelper::CreateJniObjectList( + env, reinterpret_cast(puts), num_puts); + RETURN_IF_ERROR(list); + return JniHelper::InvokeMethod(env, + jobject_, CLASS_TABLE_PROXY, "put", + JMETHOD1(JPARAM(JAVA_LIST), "V"), list.GetObject()); +} + +Status +HTable::Flush(JNIEnv *current_env) { + JNI_GET_ENV(current_env); + return JniHelper::InvokeMethod(env, + jobject_, CLASS_TABLE_PROXY, "flushCommits", "()V"); +} + +} /* namespace hbase */ diff --git a/hbase-native-client/src/main/native/jni_impl/hbase_table.h b/hbase-native-client/src/main/native/jni_impl/hbase_table.h new file mode 100644 index 000000000000..914ed2d69611 --- /dev/null +++ b/hbase-native-client/src/main/native/jni_impl/hbase_table.h @@ -0,0 +1,46 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef HBASE_JNI_IMPL_HTABLE_H__ +#define HBASE_JNI_IMPL_HTABLE_H__ + +#include "hbase_config.h" +#include "hbase_mutations.h" +#include "hbase_put.h" +#include "hbase_status.h" + +namespace hbase { + +class HTable : public JniObject { +public: + HTable() {} + ~HTable(); + + Status Init(const HBaseConfiguration *conf, const char *tableName, JNIEnv *current_env=NULL); + + Status Close(JNIEnv *current_env=NULL); + + Status Batch(Mutation *mutations[], size_t num_mutations, JNIEnv *current_env=NULL); + + Status SendPut(Put *puts[], size_t num_puts, JNIEnv *current_env=NULL); + + Status Flush(JNIEnv *current_env=NULL); +}; + +} /* namespace hbase */ + +#endif /* HBASE_JNI_IMPL_HTABLE_H__ */ diff --git a/hbase-native-client/src/main/native/jni_impl/jnihelper.cc b/hbase-native-client/src/main/native/jni_impl/jnihelper.cc new file mode 100644 index 000000000000..13f581d45b5d --- /dev/null +++ b/hbase-native-client/src/main/native/jni_impl/jnihelper.cc @@ -0,0 +1,882 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#line 19 "jnihelper.cc" // ensures short filename in logs. + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef __CYGWIN__ + #include +#endif + +#include + +#include "hbase_consts.h" +#include "hbase_macros.h" +#include "hbase_status.h" +#include "jnihelper.h" + +namespace hbase { + +#ifdef __CYGWIN__ + #define PATH_SEPARATOR ";" + #define FILE_SEPARATOR "\\" +#else + #define PATH_SEPARATOR ":" + #define FILE_SEPARATOR "/" +#endif + +#define JAVA_CLASSPATH "CLASSPATH" +#define HBASE_LIB_DIR "HBASE_LIB_DIR" +#define HBASE_CONF_DIR "HBASE_CONF_DIR" + +static pthread_mutex_t hbaseHashMutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t jvmMutex = PTHREAD_MUTEX_INITIALIZER; + +static volatile int hashTableInited = 0; + +#define LOCK_HASH_TABLE() pthread_mutex_lock(&hbaseHashMutex) +#define UNLOCK_HASH_TABLE() pthread_mutex_unlock(&hbaseHashMutex) +#define LOCK_JVM_MUTEX() pthread_mutex_lock(&jvmMutex) +#define UNLOCK_JVM_MUTEX() pthread_mutex_unlock(&jvmMutex) + +/** The Native return types that methods could return */ +#define JVOID 'V' +#define JOBJECT 'L' +#define JARRAYOBJECT '[' +#define JBOOLEAN 'Z' +#define JBYTE 'B' +#define JCHAR 'C' +#define JSHORT 'S' +#define JINT 'I' +#define JLONG 'J' +#define JFLOAT 'F' +#define JDOUBLE 'D' + +/** Java string hash codes of the exception class name */ +static const int32_t java_lang_OutOfMemoryError = 0xbca8c7d6; +static const int32_t org_apache_hadoop_hbase_NotServingRegionException = 0xf9e9577a; +static const int32_t org_apache_hadoop_hbase_RegionTooBusyException = 0x44f9bcbe; +static const int32_t org_apache_hadoop_hbase_TableExistsException = 0xed09f7ed; +static const int32_t org_apache_hadoop_hbase_TableNotDisabledException = 0x1e30f246; +static const int32_t org_apache_hadoop_hbase_TableNotEnabledException = 0x725f5e9b; +static const int32_t org_apache_hadoop_hbase_TableNotFoundException = 0x99394aba; +static const int32_t org_apache_hadoop_hbase_UnknownScannerException = 0x6021c113; +static const int32_t org_apache_hadoop_hbase_client_RegionOfflineException = 0x10d6f53b; +static const int32_t org_apache_hadoop_hbase_regionserver_NoSuchColumnFamilyException = 0x8669901e; +static const int32_t org_apache_hadoop_hbase_security_AccessDeniedException = 0xf8e728ca; +static const int32_t org_hbase_async_ConnectionResetException = 0x76e397af; +static const int32_t org_hbase_async_MultiAction_MultiPutFailedException = 0x8706944c; +static const int32_t org_hbase_async_NoSuchColumnFamilyException = 0x8ccb093c; +static const int32_t org_hbase_async_NotServingRegionException = 0xf9da3971; +static const int32_t org_hbase_async_PleaseThrottleException = 0x0f0c51ea; +static const int32_t org_hbase_async_RegionOfflineException = 0x33bcca71; +static const int32_t org_hbase_async_RemoteException = 0xa7fd8618; +static const int32_t org_hbase_async_TableNotFoundException = 0x42618423; +static const int32_t org_hbase_async_UnknownScannerException = 0xdc00b4ca; + +/** Denote the method we want to invoke as STATIC or INSTANCE */ +typedef enum { + STATIC, + INSTANCE +} MemberType; + +typedef enum { + REF_LOCAL, + REF_GLOBAL +} RefType; + +JniResult::JniResult(int32_t code, const char *msg) +: Status(code, msg) { +} + +/** + * MAX_HASH_TABLE_ELEM: The maximum no. of entries in the hashtable. + * It's set to 4096 to account for (classNames + No. of threads) + */ +static const int MAX_HASH_TABLE_ELEM = 4096; + +static int +HashTableInit(void) { + if (!hashTableInited) { + LOCK_HASH_TABLE(); + if (!hashTableInited) { + if (hcreate(MAX_HASH_TABLE_ELEM) == 0) { + HBASE_LOG_ERROR("Error creating hashtable, <%d>: %s", + errno, strerror(errno)); + UNLOCK_HASH_TABLE(); + return 0; + } + hashTableInited = 1; + } + UNLOCK_HASH_TABLE(); + } + return 1; +} + +static int +InsertEntryIntoTable(const char *key, void *data) { + ENTRY e, *ep; + if (key == NULL || data == NULL) { + return 0; + } + if (! HashTableInit()) { + return -1; + } + e.data = data; + e.key = (char*)key; + LOCK_HASH_TABLE(); + ep = hsearch(e, ENTER); + UNLOCK_HASH_TABLE(); + if (UNLIKELY(ep == NULL)) { + HBASE_LOG_ERROR("Warn adding key (%s) to hash table, <%d>: %s", + key, errno, strerror(errno)); + } + return 0; +} + +static void* +SearchEntryFromTable(const char *key) { + ENTRY e,*ep; + if (key == NULL) { + return NULL; + } + HashTableInit(); + e.key = (char*)key; + LOCK_HASH_TABLE(); + ep = hsearch(e, FIND); + UNLOCK_HASH_TABLE(); + if (ep != NULL) { + return ep->data; + } + return NULL; +} + + +static int +JarFilesOnly(const struct dirent *entry) { + const char *filename = entry->d_name; + unsigned int filenameLen = strlen(filename); + // filename length should be greater than strlen(".jar") + if (filenameLen < 4) + return 0; + const char *suffixStart = filename+(filenameLen-strlen(".jar")); + // filename should end with "-filters.so" + if (strcmp(suffixStart, ".jar") != 0) + return 0; + // All Okay + return 1; +} + +#define PATH_BUFFER_SIZE 4096 +static std::string +AdjustCygwinPath(std::string originalPath) { +#ifdef __CYGWIN__ + char buffer[PATH_BUFFER_SIZE]; + cygwin_conv_path (CCP_POSIX_TO_WIN_A, originalPath.data(), buffer, PATH_BUFFER_SIZE); + return buffer; +#endif + return originalPath; +} + +static std::string +BuildHBaseClassPath( + const std::string& hbaseConfDir, + const std::string& hbaseLibDir, + const std::string& jvmClassPath) { + std::string hbaseClassPath = "-Djava.class.path="; + + if (!hbaseConfDir.empty()) { + char *absConfDir = realpath(hbaseConfDir.c_str(), NULL); + if (UNLIKELY(absConfDir == NULL)) { + HBASE_LOG_ERROR("Error accessing " HBASE_CONF_DIR ": '%s'. %s", + hbaseConfDir.c_str(), strerror(errno)); + return HConstants::EMPTY_STRING; + } + + hbaseClassPath.append(AdjustCygwinPath(absConfDir)); + free(absConfDir); + } + + if (!hbaseLibDir.empty()) { + char *absLibPath = realpath(hbaseLibDir.c_str(), NULL); + if (UNLIKELY(absLibPath == NULL)) { + HBASE_LOG_ERROR("Error accessing " HBASE_LIB_DIR " '%s'. %s", + hbaseLibDir.c_str(), strerror(errno)); + return HConstants::EMPTY_STRING; + } + + int jarCount = 0; + struct dirent **jarList; + // scan all the files matching glob "*.jar" + if ((jarCount = scandir(absLibPath, &jarList, JarFilesOnly, alphasort)) > 0) { + std::string dirPath = AdjustCygwinPath(absLibPath); + for (int i = 0; i < jarCount; ++i) { + hbaseClassPath.append(PATH_SEPARATOR) + .append(dirPath) + .append(FILE_SEPARATOR) + .append(jarList[i]->d_name); + free(jarList[i]); + } + free(jarList); + free(absLibPath); + } + } + + if (!jvmClassPath.empty()) { + hbaseClassPath.append(PATH_SEPARATOR) + .append(jvmClassPath); + } + + HBASE_LOG_DEBUG("Java classpath argument: %s", hbaseClassPath.c_str()); + + return hbaseClassPath; +} + +/** + * Helper function to get the JNI class reference for the requested class. + * This class caches the references and hence is faster than calling the JNI + * method every time. + */ +static jclass +GetClassReference( + JNIEnv *env, + const char *className) { + jclass clsLocalRef; + jclass cls = (jclass) SearchEntryFromTable(className); + if (cls) { + return cls; + } + + clsLocalRef = env->FindClass(className); + if (UNLIKELY(clsLocalRef == NULL)) { + HBASE_LOG_ERROR("Unable to get class id for class '%s'", className); + env->ExceptionDescribe(); + env->ExceptionClear(); + return NULL; + } + cls = static_cast(env->NewGlobalRef(clsLocalRef)); + if (UNLIKELY(cls == NULL)) { + HBASE_LOG_ERROR("Unable to create a reference for class '%s'", className); + env->ExceptionDescribe(); + env->ExceptionClear(); + return NULL; + } + env->DeleteLocalRef(clsLocalRef); + InsertEntryIntoTable(className, cls); + return cls; +} + +static jmethodID +GetClassMethodId( + JNIEnv *env, + jclass cls, + const char *className, + const char *methName, + const char *methSignature, + MemberType methType) { + jmethodID mid = 0; + if (methType == STATIC) { + mid = env->GetStaticMethodID(cls, methName, methSignature); + } + else if (methType == INSTANCE) { + mid = env->GetMethodID(cls, methName, methSignature); + } + if (UNLIKELY(mid == NULL)) { + HBASE_LOG_ERROR( + "Could not find method %s from class %s with signature %s.", + methName, className, methSignature); + } + return mid; +} + +static std::string +GetClassNameOfObject( + JNIEnv *env, + jobject jobj) { + jclass cls, clsClass; + jmethodID mid; + jstring str; + + cls = env->GetObjectClass(jobj); + if (UNLIKELY(cls == NULL)) { + HBASE_LOG_ERROR("env->GetObjectClass() failed"); + env->ExceptionDescribe(); + env->ExceptionClear(); + return HConstants::EMPTY_STRING; + } + clsClass = GetClassReference(env, "java/lang/Class"); + if (UNLIKELY(clsClass == NULL)) { + return HConstants::EMPTY_STRING; + } + mid = env->GetMethodID(clsClass, "getName", "()Ljava/lang/String;"); + if (UNLIKELY(mid == NULL)) { + HBASE_LOG_ERROR("env->GetMethodID() failed"); + env->ExceptionDescribe(); + env->ExceptionClear(); + return NULL; + } + str = (jstring)env->CallObjectMethod(cls, mid); + if (UNLIKELY(str == NULL)) { + HBASE_LOG_ERROR("env->CallObjectMethod() failed"); + env->ExceptionDescribe(); + env->ExceptionClear(); + return HConstants::EMPTY_STRING; + } + + const char *cstr = env->GetStringUTFChars(str, NULL); + if (UNLIKELY(cstr == NULL)) { + HBASE_LOG_ERROR("env->GetStringUTFChars() failed"); + env->ExceptionDescribe(); + env->ExceptionClear(); + return HConstants::EMPTY_STRING; + } + + std::string newstr(cstr); + env->ReleaseStringUTFChars(str, cstr); + return newstr; +} + + +static inline int32_t +JavaHashOfString(const char *buffer, size_t offset, + size_t len) { + int32_t hash = 0; + size_t off = offset; + for (size_t i = 0; i < len; ++off, ++i) { + hash = 31*hash + buffer[off]; + } + return hash; +} + +int32_t +JniHelper::ParseJavaException( + JNIEnv *env, + jthrowable jthr, + bool logException) { + if (jthr == NULL) { + return 0; + } + + std::string excClass = GetClassNameOfObject(env, (jobject) jthr); + int32_t excClassHash = JavaHashOfString(excClass.c_str(), 0, excClass.size()); + + if (excClassHash == org_hbase_async_RemoteException) { + // extract the wrapped exception + static jmethodID getType = NULL; + if (getType == NULL) { + jclass cls = GetClassReference(env, ASYNC_REMOTEEXCEPTION); + if (cls == NULL) { + return HBASE_INTERNAL_ERR; + } + getType = GetClassMethodId(env, cls, ASYNC_REMOTEEXCEPTION, + "getType", "()Ljava/lang/String;", INSTANCE); + if (getType == NULL) { + return HBASE_INTERNAL_ERR; + } + } + jstring jExcType = (jstring) env->CallObjectMethod(jthr, getType); + const char *execType = env->GetStringUTFChars(jExcType, NULL); + excClassHash = JavaHashOfString(execType, 0, strlen(execType)); + env->ReleaseStringUTFChars(jExcType, execType); + } + + bool throttleException = false; + switch (excClassHash) { + case org_hbase_async_PleaseThrottleException: + case org_apache_hadoop_hbase_RegionTooBusyException: + throttleException = true; + break; + } + if (logException + && (!throttleException + || (hb_log_get_level() >= HBASE_LOG_LEVEL_TRACE))) { + static jmethodID getMessage = NULL; + if (getMessage == NULL) { + jclass cls = GetClassReference(env, JAVA_THROWABLE); + if (cls == NULL) { + return HBASE_INTERNAL_ERR; + } + getMessage = GetClassMethodId(env, cls, JAVA_THROWABLE, + "getMessage", "()L"JAVA_STRING";", INSTANCE); + if (getMessage == NULL) { + return HBASE_INTERNAL_ERR; + } + } + jstring jMessage = (jstring) env->CallObjectMethod(jthr, getMessage); + const char *message = env->GetStringUTFChars(jMessage, NULL); + HBASE_LOG_ERROR("Java exception: %s\n\t%s", excClass.c_str(), message); + env->ReleaseStringUTFChars(jMessage, message); + } + + return excClassHash; +} + +int32_t +JniHelper::ErrorFromException( + JNIEnv *env, + jthrowable jthr) { + if (jthr == NULL) { + return 0; + } + + int32_t errnum = HBASE_INTERNAL_ERR; + int32_t exceptionCode = ParseJavaException(env, jthr); + + switch(exceptionCode) { + case java_lang_OutOfMemoryError: + errnum = ENOMEM; + break; + case org_apache_hadoop_hbase_security_AccessDeniedException: + errnum = EACCES; + break; + case org_apache_hadoop_hbase_TableNotFoundException: + case org_apache_hadoop_hbase_regionserver_NoSuchColumnFamilyException: + case org_hbase_async_TableNotFoundException: + case org_hbase_async_NoSuchColumnFamilyException: + errnum = ENOENT; + break; + case org_apache_hadoop_hbase_TableExistsException: + errnum = EEXIST; + break; + case org_apache_hadoop_hbase_TableNotEnabledException: + errnum = HBASE_TABLE_DISABLED; + break; + case org_apache_hadoop_hbase_TableNotDisabledException: + errnum = HBASE_TABLE_NOT_DISABLED; + break; + case org_hbase_async_UnknownScannerException: + case org_apache_hadoop_hbase_UnknownScannerException: + errnum = HBASE_UNKNOWN_SCANNER; + break; + case org_apache_hadoop_hbase_NotServingRegionException: + case org_hbase_async_NotServingRegionException: + case org_apache_hadoop_hbase_client_RegionOfflineException: + case org_hbase_async_RegionOfflineException: + case org_hbase_async_MultiAction_MultiPutFailedException: + case org_hbase_async_ConnectionResetException: + errnum = EAGAIN; + break; + case org_hbase_async_PleaseThrottleException: + case org_apache_hadoop_hbase_RegionTooBusyException: + errnum = ENOBUFS; + break; + default: + //TODO: interpret more exceptions + break; + } + + return errnum; +} + +/** + * This method has been intentionally placed below the other JNI helper + * methods and none of the method above this should call it to avoid + * infinite loop. + */ +static inline int32_t +CheckException(JNIEnv *env) { + jthrowable jthr = env->ExceptionOccurred(); + if (LIKELY(jthr == NULL)) return 0; + env->ExceptionClear(); + return JniHelper::ErrorFromException(env, jthr); +} + +JniResult +JniHelper::InvokeMethodInternal( + JNIEnv *env, + const char *className, + const char *methName, + const char *methSignature, + va_list args, + jobject instObj) { + MemberType methType = INSTANCE; + if (instObj == NULL) { + methType = STATIC; + } + jclass cls = GetClassReference(env, className); + if (cls == NULL) { + return JniResult(CheckException(env)); + } + + jmethodID method = GetClassMethodId( + env, cls, className, methName, methSignature, methType); + if (method == NULL) { + return JniResult(CheckException(env)); + } + + JniResult result; + const char *str = methSignature; + while (*str != ')') str++; + str++; + switch(*str) { + case JOBJECT: + case JARRAYOBJECT: + result.value.l = (methType == INSTANCE) + ? env->CallObjectMethodV(instObj, method, args) + : env->CallStaticObjectMethodV(cls, method, args); + break; + case JVOID: + if (methType == INSTANCE) { + env->CallVoidMethodV(instObj, method, args); + } else { + env->CallStaticVoidMethodV(cls, method, args); + } + break; + case JBOOLEAN: + result.value.z = (methType == INSTANCE) + ? env->CallBooleanMethodV(instObj, method, args) + : env->CallStaticBooleanMethodV(cls, method, args); + break; + case JSHORT: + result.value.s = (methType == INSTANCE) + ? env->CallShortMethodV(instObj, method, args) + : env->CallStaticShortMethodV(cls, method, args); + break; + case JLONG: + result.value.j = (methType == INSTANCE) + ? env->CallLongMethodV(instObj, method, args) + : env->CallStaticLongMethodV(cls, method, args); + break; + case JINT: + result.value.i = (methType == INSTANCE) + ? env->CallIntMethodV(instObj, method, args) + : env->CallStaticIntMethodV(cls, method, args); + break; + } + result.SetCode(CheckException(env)); + + return result; +} + +/** + * In-place URL decoding + */ +static char* +urlDecode(char *orig) { + char c1, c2; + char *dest = orig, *src = orig; + while (*src) { + if ((*src == '%') + && (c1 = *(src+1)) && isxdigit(c1) + && (c2 = *(src+2)) && isxdigit(c2)) { + c1 = tolower(c1); + c1 -= (c1 >= 'a') ? ('a'-10) : '0'; + c2 = tolower(c2); + c2 -= (c2 >= 'a') ? ('a'-10) : '0'; + *dest++ = (c1<<4)|c2; + src += 3; + } else { + *dest++ = *src++; + } + } + *dest = '\0'; + return orig; +} + +static std::string +GetEnv(const char *name) { + char *env_val = getenv(name); + return (env_val == NULL) ? HConstants::EMPTY_STRING : env_val; +} + +/** flag to record if the JVM was created by libhbase */ +static volatile bool s_VMCreated = false; + +JNIEnv* +JniHelper::GetJNIEnv(void) { + // Only the first thread should create the JVM. The other threads should + // just use the JVM created by the first thread. + LOCK_JVM_MUTEX(); + + jint noVMs = 0; + const jsize vmBufLength = 1; + JavaVM *vmBuf[vmBufLength]; + jint rv = JNI_GetCreatedJavaVMs(&(vmBuf[0]), vmBufLength, &noVMs); + if (rv != 0) { + HBASE_LOG_FATAL("JNI_GetCreatedJavaVMs failed with error: %d", rv); + UNLOCK_JVM_MUTEX(); + return NULL; + } + + JNIEnv *env = NULL; + if (noVMs == 0) { + //Get the environment variables for initializing the JVM + std::string hbaseConfDir = GetEnv(HBASE_CONF_DIR); + if (hbaseConfDir.empty()) { + HBASE_LOG_WARN("Environment variable HBASE_CONF_DIR not set!"); + } else { + HBASE_LOG_DEBUG("HBASE_CONF_DIR is set to [%s]", hbaseConfDir.c_str()); + } + + std::string hbaseClassPath = GetEnv(JAVA_CLASSPATH); + std::string hbaseLibDir = GetEnv(HBASE_LIB_DIR); + if (hbaseClassPath.empty() && hbaseLibDir.empty()) { + HBASE_LOG_FATAL("At least one of the environment variables" + " 'CLASSPATH' or 'HBASE_LIB_DIR' must be set!"); + UNLOCK_JVM_MUTEX(); + return NULL; + } + + std::string optHBaseClassPath = + BuildHBaseClassPath(hbaseConfDir, hbaseLibDir, hbaseClassPath); + if (optHBaseClassPath.empty()) { + UNLOCK_JVM_MUTEX(); + return NULL; + } + + int noArgs = 1; + //determine how many arguments were passed as LIBHBASE_OPTS env var + char *hbaseJvmArgs = getenv("LIBHBASE_OPTS"); + char *copyOfhbaseJvmArgs = NULL; + char jvmArgDelims[] = " "; + if (hbaseJvmArgs != NULL) { + HBASE_LOG_DEBUG("LIBHBASE_OPTS is set to [%s]", hbaseJvmArgs); + char *result = NULL; + copyOfhbaseJvmArgs = strdup(hbaseJvmArgs); + result = strtok(copyOfhbaseJvmArgs, jvmArgDelims); + while (result != NULL) { + noArgs++; + result = strtok(NULL, jvmArgDelims); + } + } + JavaVMOption options[noArgs]; + options[0].optionString = (char*)optHBaseClassPath.c_str(); + //fill in any specified arguments + if (noArgs > 1) { + char *result = NULL; + strcpy(copyOfhbaseJvmArgs, hbaseJvmArgs); + result = strtok(copyOfhbaseJvmArgs, jvmArgDelims); + int argNum = 1; + while(result != NULL) { + options[argNum++].optionString = urlDecode(result); + result = strtok(NULL, jvmArgDelims); + } + } + + fflush(stdout); + //Create the VM + JavaVMInitArgs vm_args; + JavaVM *vm; + vm_args.version = JNI_VERSION_1_2; + vm_args.options = options; + vm_args.nOptions = noArgs; + vm_args.ignoreUnrecognized = 0; + + rv = JNI_CreateJavaVM(&vm, (void**)&env, (void*)&vm_args); + if (rv != 0) { + HBASE_LOG_FATAL("Call to JNI_CreateJavaVM failed " + "with error: %d", rv); + UNLOCK_JVM_MUTEX(); + return NULL; + } + s_VMCreated = true; + free(copyOfhbaseJvmArgs); + } + else { + if (!s_VMCreated) { + HBASE_LOG_WARN("Found a JVM not created by libhbase."); + } + //Attach this thread to the VM + JavaVM *vm = vmBuf[0]; + rv = vm->AttachCurrentThread((void**)&env, (void *)NULL); + if (rv != 0) { + HBASE_LOG_FATAL("Call to AttachCurrentThread failed with error: %d", rv); + UNLOCK_JVM_MUTEX(); + return NULL; + } + } + UNLOCK_JVM_MUTEX(); + + return env; +} + +JniResult +JniHelper::InvokeMethod( + JNIEnv *env, + jobject instObj, + const char *className, + const char *methName, + const char *methSignature, + ...) { + va_list args; + va_start(args, methSignature); + JniResult result = InvokeMethodInternal( + env, className, methName, methSignature, args, instObj); + va_end(args); + return result; +} + +JniResult +JniHelper::InvokeMethodS( + JNIEnv *env, + const char *className, + const char *methName, + const char *methSignature, + ...) { + va_list args; + va_start(args, methSignature); + JniResult result = InvokeMethodInternal( + env, className, methName, methSignature, args); + va_end(args); + return result; +} + +JniResult +JniHelper::NewObject( + JNIEnv *env, + const char *className, + const char *ctorSignature, + ...) { + jclass cls = GetClassReference(env, className); + if (cls == NULL) { + return JniResult(CheckException(env)); + } + jmethodID mid = GetClassMethodId( + env, cls, className, "", ctorSignature, INSTANCE); + if (mid == NULL) { + return JniResult(CheckException(env)); + } + + va_list args; + va_start(args, ctorSignature); + JniResult result; + result.value.l = env->NewObjectV(cls, mid, args); + va_end(args); + if (result.value.l == NULL) { + result.SetCode(CheckException(env)); + HBASE_LOG_ERROR("Unable to create Java object with signature %s(%s)", + className, ctorSignature); + } + result.SetCode(CheckException(env)); + + return result; +} + +JniResult +JniHelper::CreateJavaByteArray( + JNIEnv *env, + const byte_t *buf, + const jsize start, + const jsize len) { + JniResult result; + if (buf == NULL || len < 0) { + result.SetCode(EINVAL); + } else { + result.value.l = env->NewByteArray(len); + if (result.value.l == NULL) { + HBASE_LOG_ERROR("Unable to create Java byte[] with length %d", len); + result.SetCode(CheckException(env)); + } else { + env->SetByteArrayRegion( + (jbyteArray)result.value.l, start, len, (const jbyte *)buf); + } + } + return result; +} + +Status +JniHelper::CreateByteArray( + JNIEnv *env, + jobject byteArray, + byte_t **bufPtr, + size_t *bufLen) { + if (byteArray) { + jbyteArray javaByteArray = static_cast(byteArray); + *bufLen = (size_t) env->GetArrayLength(javaByteArray); + *bufPtr = new byte_t[*bufLen]; + if (*bufPtr == NULL) { + *bufLen = 0; + return Status::ENoMem; + } + env->GetByteArrayRegion(javaByteArray, 0, *bufLen, (jbyte*)*bufPtr); + } else { + *bufPtr = NULL; + *bufLen = 0; + } + return Status::Success; +} + +const Status +JniHelper::SetField( + JNIEnv *env, + const char *className, + const char *fieldName, + const char *fieldSignature, + jobject val, + jobject obj) { + jclass cls = GetClassReference(env, className); + if (cls == NULL) { + return Status(CheckException(env)); + } + + if (obj == NULL) { + jfieldID fid = env->GetStaticFieldID(cls, fieldName, fieldSignature); + if (fid == NULL) { + return Status(CheckException(env)); + } + env->SetObjectField(obj, fid, val); + } else { + jfieldID fid = env->GetFieldID(cls, fieldName, fieldSignature); + if (fid == NULL) { + return Status(CheckException(env)); + } + env->SetObjectField(obj, fid, val); + } + + return Status::Success; +} + +JniResult +JniHelper::CreateJniObjectList( + JNIEnv *env, + JniObject **jniObjects, + size_t numObjects) { + JniResult list; + if (numObjects <= 0 || jniObjects == NULL) { + list.SetCode(EINVAL); + return list; + } + + list = JniHelper::NewObject( + env, JAVA_ARRAYLIST, "(I)V", numObjects); + if (UNLIKELY(!list.ok())) { + return list; + } + + for (size_t i = 0; i < numObjects; ++i) { + JniResult result = InvokeMethod( + env, list.GetObject(), JAVA_ARRAYLIST, "add", + JMETHOD1(JPARAM(JAVA_OBJECT), "Z"), jniObjects[i]->JObject()); + if (UNLIKELY(!result.ok())) { + return result; + } + } + return list; +} + +} /* namespace hbase */ diff --git a/hbase-native-client/src/main/native/jni_impl/jnihelper.h b/hbase-native-client/src/main/native/jni_impl/jnihelper.h new file mode 100644 index 000000000000..64a319c501dc --- /dev/null +++ b/hbase-native-client/src/main/native/jni_impl/jnihelper.h @@ -0,0 +1,259 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef HBASE_JNI_IMPL_JNIHELPER_H__ +#define HBASE_JNI_IMPL_JNIHELPER_H__ + +#include +#include + +#include +#include + +#include "hbase_status.h" + +#line __LINE__ "jnihelper.h" + +/* Macros for constructing method signatures */ +#define JPARAM(X) "L" X ";" +#define JARRPARAM(X) "[L" X ";" +#define JMETHOD1(X, R) "(" X ")" R +#define JMETHOD2(X, Y, R) "(" X Y ")" R +#define JMETHOD3(X, Y, Z, R) "(" X Y Z")" R + +#define HADOOP_CONF "org/apache/hadoop/conf/Configuration" +#define HBASE_CONF "org/apache/hadoop/hbase/HBaseConfiguration" +#define HBASE_GET "org/apache/hadoop/hbase/client/Get" +#define HBASE_PUT "org/apache/hadoop/hbase/client/Put" +#define HBASE_MUTATION "org/apache/hadoop/hbase/client/Mutation" +#define HBASE_RESULT "org/apache/hadoop/hbase/client/Result" +#define HBASE_HTABLE "org/apache/hadoop/hbase/client/HTable" +#define HBASE_HADMIN "org/apache/hadoop/hbase/client/HBaseAdmin" +#define HBASE_TBLDSC "org/apache/hadoop/hbase/HTableDescriptor" +#define HBASE_CLMDSC "org/apache/hadoop/hbase/HColumnDescriptor" +#define HBASE_DURABILITY "org/apache/hadoop/hbase/client/Durability" + +#define CLASS_CLIENT_PROXY "org/apache/hadoop/hbase/jni/ClientProxy" +#define CLASS_GET_PROXY "org/apache/hadoop/hbase/jni/GetProxy" +#define CLASS_PUT_PROXY "org/apache/hadoop/hbase/jni/PutProxy" +#define CLASS_ROW_PROXY "org/apache/hadoop/hbase/jni/RowProxy" +#define CLASS_RESULT_PROXY "org/apache/hadoop/hbase/jni/ResultProxy" +#define CLASS_DELETE_PROXY "org/apache/hadoop/hbase/jni/DeleteProxy" +#define CLASS_MUTATION_PROXY "org/apache/hadoop/hbase/jni/MutationProxy" +#define CLASS_SCANNER_PROXY "org/apache/hadoop/hbase/jni/ScannerProxy" +#define CLASS_TABLE_PROXY "org/apache/hadoop/hbase/jni/TableProxy" + +#define ASYNC_REMOTEEXCEPTION "org/hbase/async/RemoteException" + +#define JAVA_OBJECT "java/lang/Object" +#define JAVA_THROWABLE "java/lang/Throwable" +#define JAVA_STACKTRACEELM "java/lang/StackTraceElement" +#define JAVA_STRING "java/lang/String" +#define JAVA_LIST "java/util/List" +#define JAVA_ARRAYLIST "java/util/ArrayList" + +/** + * Retrieves a JNIEnv* unless one was provided. + * Pushes a JNI local frame on the stack. + */ +#define JNI_GET_ENV(current_env) \ + JNIEnv *env = current_env; \ + if (env == NULL) { \ + env = JniHelper::GetJNIEnv(); \ + if (env == NULL) return Status::HBaseInternalError; \ + } \ + JniLocalFrame jni_frame(env); \ + RETURN_IF_ERROR(jni_frame.push()); + +namespace hbase { + +class JniLocalFrame { + public: + JniLocalFrame(JNIEnv *env) : env_(env) {} + ~JniLocalFrame() { + if (env_ != NULL) { + env_->PopLocalFrame(NULL); + } + } + + Status push(int max_local_ref=10) { + int err = 0; + if (env_ == NULL) { + HBASE_LOG_ERROR("Can not push JNI local frame since JNIEnv* is NULL."); + return Status::EInvalid; + } else if ((err = env_->PushLocalFrame(max_local_ref)) < 0) { + HBASE_LOG_ERROR("Error %d pushing JNI local frame ", err); + env_->ExceptionClear(); + return Status::HBaseInternalError; + } + return Status::Success; + } + + private: + JNIEnv *env_; +}; + +class JniResult : public Status { +public: + JniResult(int32_t code=0, const char *msg=""); + + jvalue GetValue() { return value; } + + jobject GetObject() { return value.l; } + + friend class JniHelper; + +private: + jvalue value; +}; + +/** + * All HBase object wrapping a JAVA proxy object derives from JniObject. + */ +class JniObject { +public: + JniObject() : jobject_(NULL) {} + + JniObject(jobject object) : jobject_(object) {} + + virtual ~JniObject(); + + jobject JObject() const { return jobject_; } + +protected: + jobject jobject_; + +private: + Status Destroy(JNIEnv *current_env=NULL); +}; + +class JniHelper { +public: + + /** + * GetJNIEnv: A helper function to get the JNIEnv* for the given thread. + * If no JVM exists, then one will be created. JVM command line arguments + * are obtained from the LIBHDFS_OPTS environment variable. + * + * @param: None. + * @returns The JNIEnv* corresponding to the thread. + */ + static JNIEnv *GetJNIEnv(void); + + /** + * Invokes a constructor. + * + * env: The JNIEnv pointer + * className: Name of the class + * ctorSignature: the signature of the constructor "(arg-types)V" + * + * Arguments to the constructor must be passed after ctorSignature + */ + static JniResult NewObject( + JNIEnv *env, + const char *className, + const char *ctorSignature, + ...); /* the constructor arguments */ + + /** + * Invokes an Instance method. + * + * RETURNS: a JniResult object + */ + static JniResult InvokeMethod( + JNIEnv *env, /* The JNIEnv pointer */ + jobject instObj, /* The object to invoke the method on. */ + const char *className, /* Name of the class where the method can be found */ + const char *methName, /* Name of the method */ + const char *methSignature, /* the signature of the method "(arg-types)ret-type" */ + ...); /* the method arguments */ + + /** + * Invokes an Static method. + * + * RETURNS: a JniResult object + */ + static JniResult InvokeMethodS( + JNIEnv *env, /* The JNIEnv pointer */ + const char *className, /* Name of the class where the method can be found */ + const char *methName, /* Name of the method */ + const char *methSignature, /* the signature of the method "(arg-types)ret-type" */ + ...); /* the method arguments */ + + /** + * Parse the Java exception, optionally logging it and returns the + * unique code identifying the exception. + * + * @returns The unique code of the exception or 0 if the exception was null. + */ + static int32_t ParseJavaException( + JNIEnv *env, /* The JNIEnv pointer */ + jthrowable jthr, /* The Java exception to translate */ + bool logException = true); + + /** + * Translates an exception into errno. + * + * @returns The translated error code or 0 if the exception was null. + */ + static int32_t ErrorFromException( + JNIEnv *env, /* The JNIEnv pointer */ + jthrowable jthr); /* The Java exception to translate */ + + /** + * Convert a C/C++ char array to Java byte array + * + * @returns A JniResult referring to the created byte array. + */ + static JniResult CreateJavaByteArray( + JNIEnv *env, + const byte_t *buf, + const jsize start, + const jsize len); + + static Status CreateByteArray( + JNIEnv *env, + jobject jbyteArray, + byte_t **bufPtr, + size_t *bufLen); + + static JniResult CreateJniObjectList( + JNIEnv *env, + JniObject **jniObjects, + size_t numObjects); + + static const Status SetField( + JNIEnv *env, + const char *className, + const char *fieldName, + const char *fieldSignature, + jobject val, + jobject obj = NULL); + +private: + static JniResult InvokeMethodInternal( + JNIEnv *env, + const char *className, + const char *methName, + const char *methSignature, + va_list args, + jobject instObj = NULL); /* static method if NULL, instance otherwise */ +}; + +} /* namespace hbase */ + +#endif /* HBASE_JNI_IMPL_JNIHELPER_H__ */ diff --git a/hbase-native-client/src/main/resources/log4j.xml b/hbase-native-client/src/main/resources/log4j.xml new file mode 100644 index 000000000000..0649daff74d5 --- /dev/null +++ b/hbase-native-client/src/main/resources/log4j.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hbase-native-client/src/rpc/CMakeLists.txt b/hbase-native-client/src/rpc/CMakeLists.txt deleted file mode 100644 index d9c0695f97ac..000000000000 --- a/hbase-native-client/src/rpc/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - diff --git a/hbase-native-client/src/sync/CMakeLists.txt b/hbase-native-client/src/sync/CMakeLists.txt deleted file mode 100644 index ddd221222e5a..000000000000 --- a/hbase-native-client/src/sync/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -set( SYNC_SRC - hbase_connection.cc - hbase_admin.cc -) - - -add_library(hsync OBJECT ${SYNC_SRC}) diff --git a/hbase-native-client/src/sync/hbase_admin.cc b/hbase-native-client/src/sync/hbase_admin.cc deleted file mode 100644 index d43c8ec1fb6d..000000000000 --- a/hbase-native-client/src/sync/hbase_admin.cc +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "sync/hbase_admin.h" - -#include -#include - -#include "core/admin.h" - -int32_t hb_admin_create(hb_admin_t** admin_ptr) { - (*admin_ptr) = reinterpret_cast(new Admin()); - return 0; -} - -/* - * Disconnect the admin releasing any internal objects - * or connections created in the background. - */ -int32_t hb_admin_destroy(hb_admin_t * admin) { - Admin * adm = reinterpret_cast(admin); - delete adm; - return 0; -} - -/* - * See if a table exists. - */ -int32_t hb_admin_table_exists(hb_admin_t * admin, - char * name_space, size_t name_space_length, - char * table, size_t table_length, - bool * exists) { - *exists = true; - return 0; -} diff --git a/hbase-native-client/src/sync/hbase_admin.h b/hbase-native-client/src/sync/hbase_admin.h deleted file mode 100644 index 860bfba4b849..000000000000 --- a/hbase-native-client/src/sync/hbase_admin.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef SYNC_HBASE_ADMIN_H_ -#define SYNC_HBASE_ADMIN_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include "core/hbase_macros.h" -#include "core/hbase_types.h" -#include "sync/hbase_connection.h" - - -/** - * Create a new hb_admin. - * All fields are initialized to the defaults. If you want to set - * connection or other properties, set those before calling any - * RPC functions. - */ -HBASE_API int32_t hb_admin_create(hb_admin_t* admin_ptr, - hb_connection_t connection); - -/* - * Disconnect the admin releasing any internal objects - * or connections created in the background. - */ -HBASE_API int32_t hb_admin_destroy(hb_admin_t admin); - -/* - * See if a table exists. - */ -HBASE_API int32_t hb_admin_table_exists(hb_admin_t admin, - char * name_space, size_t name_space_length, - char * table, size_t table_length, bool * exists); - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif // SYNC_HBASE_ADMIN_H_ diff --git a/hbase-native-client/src/sync/hbase_connection.cc b/hbase-native-client/src/sync/hbase_connection.cc deleted file mode 100644 index df05376d8088..000000000000 --- a/hbase-native-client/src/sync/hbase_connection.cc +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "sync/hbase_connection.h" - -#include "core/connection.h" -#include "core/hbase_types.h" - -extern "C" { -int32_t hb_connection_create(hb_connection_t * connection_ptr, - hb_connection_attr_t connection_attr) { - (*connection_ptr) = reinterpret_cast(new Connection()); - if ((*connection_ptr) == NULL) - return -1; - return 0; -} -int32_t hb_connection_destroy(hb_connection_t connection) { - free(connection); - return 0; -} -} // extern "C" diff --git a/hbase-native-client/src/sync/hbase_connection.h b/hbase-native-client/src/sync/hbase_connection.h deleted file mode 100644 index af9284d2e9c4..000000000000 --- a/hbase-native-client/src/sync/hbase_connection.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef SYNC_HBASE_CONNECTION_H_ -#define SYNC_HBASE_CONNECTION_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "core/hbase_macros.h" -#include "core/hbase_types.h" -#include "core/hbase_connection_attr.h" - -#include - -/** - * Create an hb_connection. - * - * if connection_attr is null everything will be left as default - */ -HBASE_API int32_t hb_connection_create(hb_connection_t * connection_ptr, - hb_connection_attr_t connection_attr); - -/** - * Destroy the connection and free all resources allocated at creation - * time. - */ -HBASE_API int32_t hb_connection_destroy(hb_connection_t connection); - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif // SYNC_HBASE_CONNECTION_H_ - diff --git a/hbase-native-client/src/test/native/common/admin_ops.cc b/hbase-native-client/src/test/native/common/admin_ops.cc new file mode 100644 index 000000000000..ef477a086e94 --- /dev/null +++ b/hbase-native-client/src/test/native/common/admin_ops.cc @@ -0,0 +1,99 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#line 19 "admin_ops.cc" // ensures short filename in logs. + +#include + +#include + +#include "test_types.h" + +namespace hbase { +namespace test { + +#define COULD_NOT_CREATE_TABLE "Could not create HBase admin : errorCode = %d." +#define TABLE_EXISTS_DELETING "Table '%s' exists, deleting..." +#define COULD_NOT_DELETE_TABLE "Could not delete table %s[%d]." +#define TABLE_EXISTS "Table '%s' exists, will use it for test." +#define ERROR_WHILE_TABLE_EXISTS "Error while checking if the table exists: errorCode = %d." +#define CREATING_TABLE "Creating table '%s'..." +#define TABLE_IS_ENABLED_OR "Table '%s' is %senabled, result %d." +#define TABLE_CREATED_VERIFYING "Table '%s' created, verifying if enabled." + +int32_t +ensureTable( + hb_connection_t connection, + bool createNew, + const char* table_name, + bytebuffer families[], + size_t numFamilies) { + int32_t retCode = 0; + hb_admin_t admin = NULL; + hb_columndesc *hcds = NULL; + + if ((retCode = hb_admin_create(connection, &admin)) != 0) { + HBASE_LOG_ERROR(COULD_NOT_CREATE_TABLE, retCode); + goto cleanup; + } + + if ((retCode = hb_admin_table_exists(admin, NULL, table_name)) == 0) { + if (createNew) { + HBASE_LOG_INFO(TABLE_EXISTS_DELETING, table_name); + if ((retCode = hb_admin_table_delete(admin, NULL, table_name)) != 0) { + HBASE_LOG_ERROR(COULD_NOT_DELETE_TABLE, table_name, retCode); + goto cleanup; + } + } else { + HBASE_LOG_INFO(TABLE_EXISTS, table_name); + goto cleanup; + } + } else if (retCode != ENOENT) { + HBASE_LOG_ERROR(ERROR_WHILE_TABLE_EXISTS, retCode); + goto cleanup; + } + + hcds = new hb_columndesc[numFamilies]; + for (size_t i = 0; i < numFamilies; ++i) { + hb_coldesc_create(families[i]->buffer, families[i]->length, &hcds[i]); + } + + HBASE_LOG_INFO(CREATING_TABLE, table_name); + if ((retCode = hb_admin_table_create( + admin, NULL, table_name, hcds, numFamilies)) == 0) { + HBASE_LOG_INFO(TABLE_CREATED_VERIFYING, table_name); + retCode = hb_admin_table_enabled(admin, NULL, table_name); + HBASE_LOG_MSG((retCode ? HBASE_LOG_LEVEL_ERROR : HBASE_LOG_LEVEL_INFO), + TABLE_IS_ENABLED_OR, table_name, (retCode?"not ":"")); + } + + for (size_t i = 0; i < numFamilies; ++i) { + hb_coldesc_destroy(hcds[i]); + } + +cleanup: + if (hcds) { + delete[] hcds; + } + if (admin) { + hb_admin_destroy(admin, NULL, NULL); + } + return retCode; +} + +} /* namespace test */ +} /* namespace hbase */ diff --git a/hbase-native-client/src/test/native/common/admin_ops.h b/hbase-native-client/src/test/native/common/admin_ops.h new file mode 100644 index 000000000000..b4b44c579976 --- /dev/null +++ b/hbase-native-client/src/test/native/common/admin_ops.h @@ -0,0 +1,38 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef HBASE_TESTS_ADMIN_OPS_H_ +#define HBASE_TESTS_ADMIN_OPS_H_ + +#include + +#include "byte_buffer.h" + +namespace hbase { +namespace test { + +int32_t +ensureTable( + hb_connection_t connection, + bool createNew, + const char* table_name, + bytebuffer families[], size_t numFamilies); + +} /* namespace test */ +} /* namespace hbase */ + +#endif /* HBASE_TESTS_ADMIN_OPS_H_ */ diff --git a/hbase-native-client/src/test/native/common/byte_buffer.cc b/hbase-native-client/src/test/native/common/byte_buffer.cc new file mode 100644 index 000000000000..f1d53f2dcc12 --- /dev/null +++ b/hbase-native-client/src/test/native/common/byte_buffer.cc @@ -0,0 +1,230 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#line 19 "byte_buffer.cc" // ensures short filename in logs. + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "byte_buffer.h" +#include "common_utils.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MALLOCED_BUFFER (1 << 0x00) +#define INLINE_BUFFER (1 << 0x01) + +static void +bytebuffer_release_node(bytebuffer byte_buf) { + free(byte_buf); +} + +static bytebuffer +bytebuffer_alloc_node() { + // TODO These fixed size nodes can be managed from a pool. + return (bytebuffer) malloc(sizeof(struct bytebuffer_)); +} + +/** + * Allocates and wrap a byte array of size 'length' in the provided bytebuffer. + * + * @returns 0 if allocation was successful, non-zero otherwise. + */ +static int32_t +bytebuffer_alloc_internal( + size_t len, + bytebuffer byte_buf) { + if (byte_buf != NULL) { + if (len > INLINE_BUFFER_SIZE) { + // would an aligned alloc be better? + byte_buf->buffer = (unsigned char*) malloc(len); + if (byte_buf->buffer == NULL) { + return ENOMEM; + } + byte_buf->flags_ = MALLOCED_BUFFER; + byte_buf->capacity_ = len; + } else { + byte_buf->buffer = byte_buf->internal_; + byte_buf->flags_ = INLINE_BUFFER; + byte_buf->capacity_ = INLINE_BUFFER_SIZE; + } + byte_buf->length = len; + return 0; + } + return EINVAL; +} + +/* exported functions */ + +uint64_t +currentTimeMicroSeconds() { + struct timeval te; + gettimeofday(&te, NULL); // get current time + return (te.tv_sec*1000000uLL + (te.tv_usec)); // calculate microseconds +} + +//from http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash +uint64_t +FNVHash64(uint64_t val) { + uint64_t hashval = 0xcbf29ce484222325uLL; + for (int32_t i = 0; i < 8; i++) { + long octet = val & 0xff; + val = val >> 8; + hashval = hashval ^ octet; + hashval = hashval * 0x100000001b3uLL; + } + return hashval; +} + +bytebuffer +generateRowKey( + const char* rowkey_prefix, + const bool hashKeys, + uint64_t opNum) { + return bytebuffer_printf("%s%llu", rowkey_prefix, + (hashKeys ? FNVHash64(opNum) : opNum)); +} + +/** + * @returns an allocated bytebuffer of size 'length' + */ +bytebuffer +bytebuffer_alloc(const size_t length) { + bytebuffer byte_buf = bytebuffer_alloc_node(); + if (byte_buf != NULL) { + if ((errno = bytebuffer_alloc_internal(length, byte_buf)) != 0) { + bytebuffer_release_node(byte_buf); + byte_buf = NULL; + } + } + return byte_buf; +} + +/** + * Deallocates any previously allocated block of memory buffer. + */ +int32_t +bytebuffer_free(bytebuffer byte_buf) { + if(byte_buf == NULL) return EINVAL; + + if (byte_buf->flags_ & MALLOCED_BUFFER) { + free(byte_buf->buffer); + } + byte_buf->capacity_ = byte_buf->length = byte_buf->flags_ = 0; + byte_buf->buffer = NULL; + bytebuffer_release_node(byte_buf); + return 0; +} + +/** + * Creates an bytebuffer with a copy of byte array bounded by + * 'start' and 'length'. + * + * @returns a pointer to an allocated bytebuffer structure which + * contains a copy of the byte array specified by 'start' and + * 'length', or NULL if fails. + */ +bytebuffer +bytebuffer_memcpy(const char *buffer, + const size_t length) { + bytebuffer byte_buf = bytebuffer_alloc(length); + if (byte_buf != NULL) { + memcpy(byte_buf->buffer, buffer, length); + } + return byte_buf; +} + +/** + * Creates an bytebuffer of specified length and fill it with + * random bytes. + * + * @returns a pointer to an allocated bytebuffer structure which + * contains an allocated byte array of length 'length' filled + * with pseudo random bytes, or NULL if fails. + */ +bytebuffer +bytebuffer_random(const size_t length) { + bytebuffer byte_buf = bytebuffer_alloc(length); + uint64_t *uint64_ptr = (uint64_t *)byte_buf->buffer; + uint64_t seed = currentTimeMicroSeconds(); + size_t numInts = length/sizeof(uint64_t); + for (size_t i = 0; i < numInts; ++i) { + *(uint64_ptr++) = seed = (uint64_t)FNVHash64(seed); + } + unsigned char *byte_ptr = (unsigned char *)uint64_ptr; + for (size_t i = numInts*sizeof(uint64_t); i < length; ++i) { + *(byte_ptr++) = (unsigned char)rand(); + } + return byte_buf; +} + +/** + * Create an bytebuffer with a copy of a C style NULL + * terminated string. The terminating NULL is NOT copied. + * + * @returns a pointer to an allocated bytebuffer structure + * which contains a copy of the NULL terminated string, + * or NULL if fails. + */ +bytebuffer +bytebuffer_strcpy(const char *string) { + return bytebuffer_memcpy(string, strlen(string)); +} + +/** + * Create an bytebuffer populated with formatted text in the + * same way as printf() function would output to stdout. + * + * A NULL terminator is NOT appended to the buffer. + * + * @returns a pointer to an allocated bytebuffer structure which + * contains the same text that would be printed if format and + * arguments were used with printf(format, ...). + */ +bytebuffer +bytebuffer_printf( + const char *format, + ...) { + va_list args_size; + va_start(args_size, format); + size_t length = vsnprintf(NULL, 0, format, args_size) + 1; + va_end(args_size); + + bytebuffer bytebuffer = bytebuffer_alloc(length); + if (bytebuffer != NULL) { + va_list args; + va_start(args, format); + vsnprintf((char *)bytebuffer->buffer, length, format, args); + bytebuffer->length--; + va_end(args); + } + + return bytebuffer; +} + +#ifdef __cplusplus +} +#endif diff --git a/hbase-native-client/src/test/native/common/byte_buffer.h b/hbase-native-client/src/test/native/common/byte_buffer.h new file mode 100644 index 000000000000..850aef720b45 --- /dev/null +++ b/hbase-native-client/src/test/native/common/byte_buffer.h @@ -0,0 +1,130 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef HBASE_TESTS_BYTE_BUFFER_H_ +#define HBASE_TESTS_BYTE_BUFFER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Size of the in-line buffer. + */ +#define INLINE_BUFFER_SIZE (128 - ( \ + sizeof(char*) + \ + sizeof(size_t) + \ + sizeof(size_t) + \ + sizeof(uint64_t))) +struct bytebuffer_ { +//public: + unsigned char *buffer; /* pointer to the data held in the buffer */ + size_t length; /* length of the available data in bytes */ + +//private: + size_t capacity_; /* size of allocated buffer, >= 'length' */ + uint64_t flags_; /* reserved for internal use */ + + /** + * An internal buffer which can be used to optimize allocation of short + * length byte arrays in-line with the structure thus avoiding double + * allocation. Application must never access it directly instead use + * 'buffer' and 'length' to access the data. + */ + unsigned char internal_[INLINE_BUFFER_SIZE]; +}; +typedef struct bytebuffer_ *bytebuffer; + +/** + * Use this function to allocate an bytebuffer structure. + * + * @returns a pointer to an allocated bytebuffer of size 'length', or NULL + * if fails. + */ +bytebuffer +bytebuffer_alloc(const size_t length); + +/** + * Deallocates any previously allocated block of memory buffer. Any application + * owned bytebuffer must be freed by calling this method. + */ +int32_t +bytebuffer_free(bytebuffer byteBuf); + +/** + * Creates an bytebuffer with a copy of byte array bounded by + * 'start' and 'length'. + * + * @returns a pointer to an allocated bytebuffer structure which + * contains a copy of the byte array specified by 'start' and + * 'length', or NULL if fails. + */ +bytebuffer +bytebuffer_memcpy(const char *start, const size_t length); + +/** + * Create an bytebuffer with a copy of a C style NULL + * terminated string. The terminating NULL is NOT copied. + * + * @returns a pointer to an allocated bytebuffer structure + * which contains a copy of the NULL terminated string, + * or NULL if fails. + */ +bytebuffer +bytebuffer_strcpy(const char *string); + +/** + * Create an bytebuffer populated with formatted text in the + * same way as printf() function would output to stdout. + * + * A NULL terminator is NOT appended to the buffer. + * + * @returns a pointer to an allocated bytebuffer structure which + * contains the same text that would be printed if format and + * arguments were used with printf(format, ...) or NULL if fails. + */ +bytebuffer +bytebuffer_printf(const char *format, ...); + +/** + * Creates an bytebuffer of specified length and fill it with + * random bytes. + * + * @returns a pointer to an allocated bytebuffer structure which + * contains an allocated byte array of length 'length' filled + * with pseudo random bytes, or NULL if fails. + */ +bytebuffer +bytebuffer_random(const size_t length); + + +bytebuffer +generateRowKey(const char *rowkey_prefix, + const bool hashKeys, + uint64_t opNum); + +uint64_t +currentTimeMicroSeconds(); + +uint64_t +FNVHash64(uint64_t val); + +#ifdef __cplusplus +} +#endif + +#endif /* HBASE_TESTS_BYTE_BUFFER_H_ */ diff --git a/hbase-native-client/src/test/native/common/common_utils.cc b/hbase-native-client/src/test/native/common/common_utils.cc new file mode 100644 index 000000000000..e3e9c40e9812 --- /dev/null +++ b/hbase-native-client/src/test/native/common/common_utils.cc @@ -0,0 +1,105 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#line 19 "common_utils.cc" // ensures short filename in logs. + +#include +#include + +#include + +#include "common_utils.h" + +namespace hbase { +namespace test { + +/** + * Client destroy synchronizer and callbacks + */ +static volatile bool client_destroyed = false; +static pthread_cond_t client_destroyed_cv = PTHREAD_COND_INITIALIZER; +static pthread_mutex_t client_destroyed_mutex = PTHREAD_MUTEX_INITIALIZER; + +static void +client_disconnection_callback( + int32_t err, + hb_client_t client, + void *extra) { + HBASE_LOG_INFO("Received client disconnection callback."); + pthread_mutex_lock(&client_destroyed_mutex); + client_destroyed = true; + pthread_cond_signal(&client_destroyed_cv); + pthread_mutex_unlock(&client_destroyed_mutex); +} + +static void +wait_client_disconnection() { + HBASE_LOG_INFO("Waiting for client to disconnect."); + pthread_mutex_lock(&client_destroyed_mutex); + while (!client_destroyed) { + pthread_cond_wait(&client_destroyed_cv, &client_destroyed_mutex); + } + pthread_mutex_unlock(&client_destroyed_mutex); + HBASE_LOG_INFO("Client disconnected."); +} + +/** + * Flush synchronizer and callback + */ +static volatile bool g_flushDone = false; +static pthread_cond_t flush_cv = PTHREAD_COND_INITIALIZER; +static pthread_mutex_t flush_mutex = PTHREAD_MUTEX_INITIALIZER; + +static void +client_flush_callback( + int32_t err, + hb_client_t client, + void *extra) { + HBASE_LOG_TRACE("Received client flush callback."); + pthread_mutex_lock(&flush_mutex); + g_flushDone = true; + pthread_cond_signal(&flush_cv); + pthread_mutex_unlock(&flush_mutex); +} + +static void +wait_for_flush() { + HBASE_LOG_TRACE("Waiting for flush to complete."); + pthread_mutex_lock(&flush_mutex); + while (!g_flushDone) { + pthread_cond_wait(&flush_cv, &flush_mutex); + } + pthread_mutex_unlock(&flush_mutex); + HBASE_LOG_TRACE("Flush completed."); +} + +void +flush_client_and_wait(hb_client_t client) { + g_flushDone = false; + hb_client_flush(client, client_flush_callback, NULL); + wait_for_flush(); +} + +void +disconnect_client_and_wait(hb_client_t client) { + HBASE_LOG_INFO("Disconnecting client."); + hb_client_destroy(client, client_disconnection_callback, NULL); + wait_client_disconnection(); +} + +} /* namespace test */ +} /* namespace hbase */ diff --git a/hbase-native-client/src/test/native/common/common_utils.h b/hbase-native-client/src/test/native/common/common_utils.h new file mode 100644 index 000000000000..3aa5b4b5bcb8 --- /dev/null +++ b/hbase-native-client/src/test/native/common/common_utils.h @@ -0,0 +1,42 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef HBASE_TESTS_COMMON_UTILS_H_ +#define HBASE_TESTS_COMMON_UTILS_H_ + +#include + +#include + +#include "test_types.h" + +namespace hbase { +namespace test { + +void +flush_client_and_wait(hb_client_t client); + +void +disconnect_client_and_wait(hb_client_t client); + +cell_data_t* +new_cell_data(); + +} /* namespace test */ +} /* namespace hbase */ + +#endif /* HBASE_TESTS_COMMON_UTILS_H_ */ diff --git a/hbase-native-client/src/test/native/common/test_types.cc b/hbase-native-client/src/test/native/common/test_types.cc new file mode 100644 index 000000000000..a826aaea672a --- /dev/null +++ b/hbase-native-client/src/test/native/common/test_types.cc @@ -0,0 +1,120 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#line 19 "test_types.cc" // ensures short filename in logs. + +#include +#include + +#include "byte_buffer.h" +#include "test_types.h" + +namespace hbase { +namespace test { + +cell_data_t* +new_cell_data() { + cell_data_t *cell_data = (cell_data_t*) calloc(1, sizeof(cell_data_t)); + cell_data->next_cell = NULL; + return cell_data; +} + +TaskRunner::TaskRunner() + : tid_(0), stop_(false) { +} + +void +TaskRunner::Start() { + pthread_create(&thread_, 0, ThreadFunction, this); +} + +void +TaskRunner::Stop() { + stop_ = true; + pthread_join(thread_, NULL); +} + +void* +TaskRunner::ThreadFunction(void* arg) { + TaskRunner* runner = (TaskRunner*) (arg); + runner->tid_ = (uint32_t) (pthread_self()); + return runner->Run(); +} + +Semaphore::Semaphore(uint32_t numPermits) + : numPermits_(numPermits) { + sem_init(&sem_, 0, numPermits); +} + +Semaphore::~Semaphore() { + sem_destroy(&sem_); +} + +void +Semaphore::Acquire(uint32_t num) { + for (uint32_t i = 0; i < num; ++i) { + sem_wait(&sem_); + } +} + +void +Semaphore::Release(uint32_t num) { + for (uint32_t i = 0; i < num; ++i) { + sem_post(&sem_); + } +} + +uint32_t +Semaphore::NumAcquired() { + int semVal = 0; + sem_getvalue(&sem_, &semVal); + return (numPermits_ - semVal); +} + +uint32_t +Semaphore::Drain() { + uint32_t permits = 0; + while (sem_trywait(&sem_) == 0) { + ++permits; + } + return permits; +} + +RowSpec::RowSpec() + : runner(NULL), key(NULL), first_cell(NULL) { +} + +void +RowSpec::Destroy() { + cell_data_t* cell = first_cell; + while (cell) { + bytebuffer_free(cell->value); + free(cell->hb_cell); + cell_data_t* cur_cell = cell; + cell = cell->next_cell; + free(cur_cell); + } + first_cell = NULL; + if (key) { + bytebuffer_free(key); + key = NULL; + } + delete this; +} + +} /* namespace test */ +} /* namespace hbase */ diff --git a/hbase-native-client/src/test/native/common/test_types.h b/hbase-native-client/src/test/native/common/test_types.h new file mode 100644 index 000000000000..75289a61f107 --- /dev/null +++ b/hbase-native-client/src/test/native/common/test_types.h @@ -0,0 +1,105 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef HBASE_TESTS_TYPES_H_ +#define HBASE_TESTS_TYPES_H_ + +#include +#include +#include +#include +#include + +#include + +#include "byte_buffer.h" + +namespace hbase { +namespace test { + +typedef struct cell_data_t_ { + bytebuffer value; + hb_cell_t *hb_cell; + struct cell_data_t_ *next_cell; +} cell_data_t; + +cell_data_t* new_cell_data(); + +class Semaphore { +public: + Semaphore(uint32_t numPermits=SEM_VALUE_MAX); + + ~Semaphore(); + + void Acquire(uint32_t num = 1); + + void Release(uint32_t num = 1); + + uint32_t NumAcquired(); + + uint32_t Drain(); + +private: + uint32_t numPermits_; + sem_t sem_; +}; + +class TaskRunner { +public: + TaskRunner(); + + virtual ~TaskRunner() {} + + void Start(); + + void Stop(); + +protected: + volatile bool Running() { return !stop_; } + + uint32_t Id() { return tid_; } + + virtual void* Run() = 0; + +private: + uint32_t tid_; + + volatile bool stop_; + + pthread_t thread_; + + static void* ThreadFunction(void* arg); +}; + + +class RowSpec { +public: + RowSpec(); + + void Destroy(); + + TaskRunner *runner; + + bytebuffer key; + + struct cell_data_t_ *first_cell; +}; + +} /* namespace test */ +} /* namespace hbase */ + +#endif /* HBASE_TESTS_TYPES_H_ */ diff --git a/hbase-native-client/src/test/native/perftest/flusher.cc b/hbase-native-client/src/test/native/perftest/flusher.cc new file mode 100644 index 000000000000..457a7adb934c --- /dev/null +++ b/hbase-native-client/src/test/native/perftest/flusher.cc @@ -0,0 +1,54 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#line 19 "flusher.cc" // ensures short filename in logs. + +#include +#include + +#include "flusher.h" + +#include "common_utils.h" + +namespace hbase { +namespace test { + +void* +Flusher::Run() { + HBASE_LOG_INFO("Starting Flush thread (0x%08x).", Id()); + uint64_t rpcsSentLast = 0; + while (Running()) { + usleep(20000); // sleep for 20 milliseconds + uint64_t rpcsSent = statKeeper_->GetBufferableOpsCount(); + if ((rpcsSent - rpcsSentLast) > flushBatchSize_) { + uint64_t startTime = currentTimeMicroSeconds(); + HBASE_LOG_DEBUG("Flushing after %" PRIu64 " rpcs.", rpcsSent); + flush_client_and_wait(client_); + uint64_t endTime = currentTimeMicroSeconds(); + rpcsSentLast = rpcsSent; + statKeeper_->UpdateStats(1, + (endTime - startTime), StatKeeper::OP_FLUSH, false); + } + } + HBASE_LOG_INFO("Stopping Flush thread (0x%08x) after %" PRIu64 " rpcs.", + Id(), statKeeper_->GetBufferableOpsCount()); + return NULL; +} + +} /* namespace test */ +} /* namespace hbase */ + diff --git a/hbase-native-client/src/test/native/perftest/flusher.h b/hbase-native-client/src/test/native/perftest/flusher.h new file mode 100644 index 000000000000..62227dd4032e --- /dev/null +++ b/hbase-native-client/src/test/native/perftest/flusher.h @@ -0,0 +1,52 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef HBASE_TESTS_FLUSH_OPS_H_ +#define HBASE_TESTS_FLUSH_OPS_H_ + +#include + +#include "stats_keeper.h" + +namespace hbase { +namespace test { + +class Flusher : public TaskRunner { +public: + Flusher( + hb_client_t client, + uint64_t flushBatchSize, + StatKeeper *statKeeper) : + client_(client), + flushBatchSize_(flushBatchSize), + statKeeper_(statKeeper) { + } + + void* Run(); + +private: + const hb_client_t client_; + + const uint64_t flushBatchSize_; + + StatKeeper *statKeeper_; +}; + +} /* namespace test */ +} /* namespace hbase */ + +#endif /* HBASE_TESTS_FLUSH_OPS_H_ */ diff --git a/hbase-native-client/src/test/native/perftest/ops_runner.cc b/hbase-native-client/src/test/native/perftest/ops_runner.cc new file mode 100644 index 000000000000..7e26a99d97b5 --- /dev/null +++ b/hbase-native-client/src/test/native/perftest/ops_runner.cc @@ -0,0 +1,233 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#line 19 "ops_runner.cc" // ensures short filename in logs. + +#include +#include +#include +#include +#include + +#include + +#include "common_utils.h" +#include "test_types.h" +#include "ops_runner.h" + +namespace hbase { +namespace test { + +void +OpsRunner::GetCallback( + int32_t err, + hb_client_t client, + hb_get_t get, + hb_result_t result, + void* extra) { + RowSpec *rowSpec = reinterpret_cast(extra); + OpsRunner *runner = dynamic_cast(rowSpec->runner); + + runner->EndRpc(err, rowSpec->key, StatKeeper::OP_GET); + + if (runner->checkRead_) { + size_t cellCount = 0; + if (result) { + hb_result_get_cell_count(result, &cellCount); + } + if (cellCount != 1) { + HBASE_LOG_ERROR("Number of cells for row \'%.*s\' = %d.", + rowSpec->key->length, rowSpec->key->buffer, cellCount); + } + } + + rowSpec->Destroy(); + hb_get_destroy(get); + if (result) { + hb_result_destroy(result); + } +} + +void +OpsRunner::PutCallback( + int32_t err, + hb_client_t client, + hb_mutation_t mutation, + hb_result_t result, + void* extra) { + RowSpec *rowSpec = reinterpret_cast(extra); + OpsRunner *runner = dynamic_cast(rowSpec->runner); + + runner->EndRpc(err, rowSpec->key, StatKeeper::OP_PUT); + + rowSpec->Destroy(); + hb_mutation_destroy(mutation); + if (result) { + hb_result_destroy(result); + } +} + +void +OpsRunner::BeginRpc() { + if (paused_) { + pthread_mutex_lock(&pauseMutex_); + while(paused_) { + pthread_cond_wait(&pauseCond_, &pauseMutex_); + } + pthread_mutex_unlock(&pauseMutex_); + } + semaphore_->Acquire(); +} + +void +OpsRunner::EndRpc( + int32_t err, + bytebuffer key, + StatKeeper::OpType type) { + semaphore_->Release(); + statKeeper_->RpcComplete(err, type); + const char *opName = StatKeeper::GetOpName(type); + if (err == 0) { + HBASE_LOG_TRACE("%s completed for row \'%.*s\'.", + opName, key->length, key->buffer); + Resume(); + } else { + if (err == ENOBUFS) { + Pause(); + } else { + HBASE_LOG_ERROR("%s failed for row \'%.*s\', result = %d.", + opName, key->length, key->buffer, err); + } + } +} + +void +OpsRunner::Pause() { + if (!paused_) { + pthread_mutex_lock(&pauseMutex_); + if (!paused_) { + HBASE_LOG_INFO("Pausing OpsRunner(0x%08x) operations.", Id()); + paused_ = true; + } + pthread_mutex_unlock(&pauseMutex_); + } +} + +void +OpsRunner::Resume() { + if (paused_ && semaphore_->NumAcquired() == 0) { + pthread_mutex_lock(&pauseMutex_); + if (paused_) { + HBASE_LOG_INFO("Resuming OpsRunner(0x%08x) operations.", Id()); + paused_ = false; + pthread_cond_broadcast(&pauseCond_); + } + pthread_mutex_unlock(&pauseMutex_); + } +} + +void +OpsRunner::WaitForCompletion() { + while(semaphore_->NumAcquired() > 0) { + usleep(20000); + } +} + +void +OpsRunner::SendPut(uint64_t row) { + hb_put_t put = NULL; + RowSpec *rowSpec = new RowSpec(); + rowSpec->runner = this; + rowSpec->key = generateRowKey(keyPrefix_, hashKeys_, row); + hb_put_create(rowSpec->key->buffer, rowSpec->key->length, &put); + hb_mutation_set_table(put, (const char *)table_->buffer, table_->length); + hb_mutation_set_bufferable(put, bufferPuts_); + hb_mutation_set_durability(put, (writeToWAL_ ? DURABILITY_USE_DEFAULT : DURABILITY_SKIP_WAL)); + + cell_data_t *cell_data = new_cell_data(); + rowSpec->first_cell = cell_data; + cell_data->value = bytebuffer_random(valueLen_); + + hb_cell_t *cell = (hb_cell_t*) calloc(1, sizeof(hb_cell_t)); + cell_data->hb_cell = cell; + + cell->row = rowSpec->key->buffer; + cell->row_len = rowSpec->key->length; + cell->family = family_->buffer; + cell->family_len = family_->length; + cell->qualifier = column_->buffer; + cell->qualifier_len = column_->length; + cell->value = cell_data->value->buffer; + cell->value_len = cell_data->value->length; + cell->ts = HBASE_LATEST_TIMESTAMP; + + hb_put_add_cell(put, cell); + + HBASE_LOG_TRACE("Sending row with row key : '%.*s'.", cell->row_len, cell->row); + uint64_t startTime = currentTimeMicroSeconds(); + hb_mutation_send(client_, put, OpsRunner::PutCallback, rowSpec); + uint64_t endTime = currentTimeMicroSeconds(); + statKeeper_->UpdateStats(1, endTime - startTime, StatKeeper::OP_PUT, true); +} + +void +OpsRunner::SendGet(uint64_t row) { + hb_get_t get = NULL; + RowSpec *rowSpec = new RowSpec(); + rowSpec->runner = this; + rowSpec->key = generateRowKey(keyPrefix_, hashKeys_, row); + + hb_get_create(rowSpec->key->buffer, rowSpec->key->length, &get); + hb_get_set_table(get, (const char *)table_->buffer, table_->length); + + HBASE_LOG_TRACE("Sending row with row key : '%.*s'.", + rowSpec->key->length, rowSpec->key->buffer); + uint64_t startTime = currentTimeMicroSeconds(); + hb_get_send(client_, get, GetCallback, rowSpec); + uint64_t endTime = currentTimeMicroSeconds(); + statKeeper_->UpdateStats(1, endTime - startTime, StatKeeper::OP_GET, false); +} + +void* +OpsRunner::Run() { + uint64_t endRow = startRow_ + numOps_; + HBASE_LOG_INFO("Starting OpsRunner(0x%08x) for start row %" + PRIu64 ", operation count %" PRIu64 ".", Id(), startRow_, numOps_); + + double rand_max = RAND_MAX; + for (uint64_t row = startRow_; row < endRow; ++row) { + BeginRpc(); // ensures that we have permit to send the rpc + double p = rand()/rand_max; + if (((p < putWeight_) && (putsSent_ < maxPuts_) && !paused_) + || (getsSent_ >= maxGets_)) { + putsSent_++; + SendPut(row); + } else { + getsSent_++; + SendGet(row); + } + } + + flush_client_and_wait(client_); + HBASE_LOG_INFO("OpsRunner(0x%08x) waiting for operations to complete.", Id()); + WaitForCompletion(); + HBASE_LOG_INFO("OpsRunner(0x%08x) complete.", Id()); + return NULL; +} + +} /* namespace test */ +} /* namespace hbase */ diff --git a/hbase-native-client/src/test/native/perftest/ops_runner.h b/hbase-native-client/src/test/native/perftest/ops_runner.h new file mode 100644 index 000000000000..6f5bfef6c207 --- /dev/null +++ b/hbase-native-client/src/test/native/perftest/ops_runner.h @@ -0,0 +1,131 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef HBASE_TESTS_OPS_RUNNER_H_ +#define HBASE_TESTS_OPS_RUNNER_H_ + +#include +#include + +#include "test_types.h" +#include "byte_buffer.h" +#include "stats_keeper.h" + +namespace hbase { +namespace test { + +class OpsRunner : public TaskRunner { +public: + OpsRunner( + const hb_client_t client, + const bytebuffer table, + const uint32_t putPercent, + const uint64_t startRow, + const uint64_t numOps, + const bytebuffer family, + const bytebuffer column, + const char *keyPrefix, + const int valueSize, + const bool hashKeys, + const bool bufferPuts, + const bool writeToWAL, + int32_t maxPendingRPCsPerThread, + const bool checkRead, + StatKeeper *statKeeper) : + client_(client), + table_ (table), + startRow_(startRow), + numOps_(numOps), + hashKeys_(hashKeys), + bufferPuts_(bufferPuts), + writeToWAL_(writeToWAL), + family_(family), + column_(column), + keyPrefix_(keyPrefix), + valueLen_(valueSize), + getsSent_(0), + maxGets_(numOps_*(1.0-(putPercent/100.0))), + putsSent_(0), + maxPuts_(numOps_-maxGets_), + putWeight_(putPercent/100.0), + checkRead_(checkRead), + paused_(false), + semaphore_(new Semaphore(maxPendingRPCsPerThread)), + statKeeper_(statKeeper) { + pthread_mutex_init(&pauseMutex_, 0); + pthread_cond_init(&pauseCond_, 0); + } + + ~OpsRunner() { + delete semaphore_; + } + +protected: + const hb_client_t client_; + const bytebuffer table_; + const uint64_t startRow_; + const uint64_t numOps_; + const bool hashKeys_; + const bool bufferPuts_; + const bool writeToWAL_; + const bytebuffer family_; + const bytebuffer column_; + const char *keyPrefix_; + const int valueLen_; + + uint64_t getsSent_; + const uint64_t maxGets_; + uint64_t putsSent_; + const uint64_t maxPuts_; + const double putWeight_; + const bool checkRead_; + + volatile bool paused_; + pthread_mutex_t pauseMutex_; + pthread_cond_t pauseCond_; + + Semaphore *const semaphore_; + + StatKeeper *statKeeper_; + + void *Run(); + + void SendPut(uint64_t row); + + void BeginRpc(); + + void EndRpc(int32_t err, bytebuffer key, StatKeeper::OpType type); + + void Pause(); + + void Resume(); + + void WaitForCompletion(); + + void SendGet(uint64_t row); + + static void PutCallback(int32_t err, hb_client_t client, + hb_mutation_t mutation, hb_result_t result, void *extra); + + static void GetCallback(int32_t err, hb_client_t client, + hb_get_t get, hb_result_t result, void *extra); +}; + +} /* namespace test */ +} /* namespace hbase */ + +#endif /* HBASE_TESTS_OPS_RUNNER_H_ */ diff --git a/hbase-native-client/src/test/native/perftest/perftest.cc b/hbase-native-client/src/test/native/perftest/perftest.cc new file mode 100644 index 000000000000..e3705fa73be5 --- /dev/null +++ b/hbase-native-client/src/test/native/perftest/perftest.cc @@ -0,0 +1,283 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#line 19 "perftest.cc" // ensures short filename in logs. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "admin_ops.h" +#include "byte_buffer.h" +#include "common_utils.h" +#include "flusher.h" +#include "ops_runner.h" +#include "stats_keeper.h" +#include "test_types.h" + +namespace hbase { +namespace test { + +static bool argCreateTable = false; +static bool argCheckRead = false; +static bool argHashKeys = true; +static bool argBufferPuts = true; +static bool argWriteToWAL = true; + +static char *argZkQuorum = (char*) "localhost:2181"; +static char *argZkRootNode = NULL; +static char *argTableName = (char*) "test_table"; +static char *argFamilyName = (char*) "f"; +static char *argLogFilePath = NULL; +static char *argKeyPrefix = (char*) "user"; + +static uint64_t argStartRow = 1; +static uint64_t argNumOps = 1000000; +static uint32_t argValueSize = 1024; +static uint32_t argFlushBatchSize = 0; +static uint32_t argMaxPendingRPCs = 100000; +static uint32_t argNumThreads = 1; +static uint32_t argPutPercent = 100; + +static +void usage() { + fprintf(stderr, "Usage: perftest [options]...\n" + "Available options: (default values in [])\n" + " -zkQuorum [localhost:2181]\n" + " -zkRootNode [/hbase]\n" + " -table [test_table]\n" + " -family [f]\n" + " -startRow [1]\n" + " -valueSize [1024]\n" + " -numOps [1000000]\n" + " -keyPrefix [user]\n" + " -hashKeys true|false [true]\n" + " -bufferPuts true|false [true]\n" + " -writeToWAL true|false [true]\n" + " -flushBatchSize [0(disabled)]\n" + " -maxPendingRPCs [100000]\n" + " -numThreads [1]\n" + " -putPercent [100]\n" + " -createTable true|false [false]\n" + " -logFilePath [stderr]\n"); + exit(1); +} + +static void +parseArgs(int argc, + char *argv[]) { + // skip program name + argc--; argv++; +#define ArgEQ(a) (argc > 1 && (strcmp(argv[0], a) == 0)) + while (argc >= 1) { + if (ArgEQ("-valueSize")) { + argValueSize = atoi(argv[1]); + } else if (ArgEQ("-numOps")) { + argNumOps = atol(argv[1]); + } else if (ArgEQ("-startRow")) { + argStartRow = atol(argv[1]); + } else if (ArgEQ("-table")) { + argTableName = argv[1]; + } else if (ArgEQ("-family")) { + argFamilyName = argv[1]; + } else if (ArgEQ("-keyPrefix")) { + argKeyPrefix = argv[1]; + } else if (ArgEQ("-createTable")) { + argCreateTable = !(strcmp(argv[1], "false") == 0); + } else if (ArgEQ("-checkRead")) { + argCheckRead = !(strcmp(argv[1], "false") == 0); + } else if (ArgEQ("-hashKeys")) { + argHashKeys = !(strcmp(argv[1], "false") == 0); + } else if (ArgEQ("-bufferPuts")) { + argBufferPuts = !(strcmp(argv[1], "false") == 0); + } else if (ArgEQ("-writeToWAL")) { + argWriteToWAL = !(strcmp(argv[1], "false") == 0); + } else if (ArgEQ("-zkQuorum")) { + argZkQuorum = argv[1]; + } else if (ArgEQ("-zkRootNode")) { + argZkRootNode = argv[1]; + } else if (ArgEQ("-logFilePath")) { + argLogFilePath = argv[1]; + } else if (ArgEQ("-flushBatchSize")) { + // if not set to 0, starts a thread to + // flush after every 'flushBatchSize' RPCs + argFlushBatchSize = atoi(argv[1]); + } else if (ArgEQ("-maxPendingRPCs")) { + argMaxPendingRPCs = atoi(argv[1]); + } else if (ArgEQ("-numThreads")) { + argNumThreads = atoi(argv[1]); + } else if (ArgEQ("-putPercent")) { + argPutPercent = atoi(argv[1]); + } else { + usage(); + } + argv += 2; argc -= 2; + } +#undef ArgEQ + + if (!argBufferPuts && argFlushBatchSize > 0) { + fprintf(stderr, "'-flushBatchSize' can not be specified if '-bufferPuts' is false"); + } else if (argPutPercent < 0 || argPutPercent > 100) { + fprintf(stderr, "'-putPercent' must be between 0 and 100."); + } else { + // everything okay + return; + } + exit(1); +} + +/** + * Program entry point + */ +extern "C" int +main(int argc, + char *argv[]) { + if (argc == 1) usage(); + + int32_t retCode = 0; + FILE *logFile = NULL; + hb_connection_t connection = NULL; + hb_client_t client = NULL; + bytebuffer table = NULL, column = NULL; + bytebuffer families[1]; + + parseArgs(argc, argv); + + uint64_t opsPerThread = (argNumOps/argNumThreads); + int32_t maxPendingRPCsPerThread = argMaxPendingRPCs/argNumThreads; + if (maxPendingRPCsPerThread > SEM_VALUE_MAX) { + fprintf(stderr, "Can not have more than %d pending RPCs per thread.", + SEM_VALUE_MAX); + exit(1); + } + + table = bytebuffer_strcpy(argTableName); + families[0] = bytebuffer_strcpy(argFamilyName); + column = bytebuffer_strcpy("a"); + + hb_log_set_level(HBASE_LOG_LEVEL_DEBUG); // defaults to INFO + if (argLogFilePath != NULL) { + logFile = fopen(argLogFilePath, "a"); + if (!logFile) { + retCode = errno; + fprintf(stderr, "Unable to open log file \"%s\"", argLogFilePath); + perror(NULL); + goto cleanup; + } + hb_log_set_stream(logFile); // defaults to stderr + } + + if ((retCode = hb_connection_create(argZkQuorum, argZkRootNode, &connection))) { + HBASE_LOG_ERROR("Could not create HBase connection : errorCode = %d.", retCode); + goto cleanup; + } + + if ((retCode = ensureTable(connection, + argCreateTable, argTableName, families, 1)) != 0) { + HBASE_LOG_ERROR("Failed to ensure table %s : errorCode = %d", + argTableName, retCode); + goto cleanup; + } + + HBASE_LOG_INFO("Connecting to HBase cluster using Zookeeper ensemble '%s'.", + argZkQuorum); + if ((retCode = hb_client_create(connection, &client)) != 0) { + HBASE_LOG_ERROR("Could not connect to HBase cluster : errorCode = %d.", retCode); + goto cleanup; + } + + // launch threads + { + StatKeeper *statKeeper = new StatKeeper; + Flusher *flushRunner = NULL; + OpsRunner *runner[argNumThreads]; + + srand(time(NULL)); + + for (size_t i = 0; i < argNumThreads; ++i) { + runner[i] = new OpsRunner(client, table, argPutPercent, + (argStartRow + (i*opsPerThread)), opsPerThread, + families[0], column, argKeyPrefix, argValueSize, + argHashKeys, argBufferPuts, argWriteToWAL, + maxPendingRPCsPerThread, argCheckRead, statKeeper); + runner[i]->Start(); + } + + statKeeper->Start(); + + if (argFlushBatchSize > 0) { + flushRunner = new Flusher(client, argFlushBatchSize, statKeeper); + flushRunner->Start(); + } + + for (size_t i = 0; i < argNumThreads; ++i) { + runner[i]->Stop(); + delete runner[i]; + } + + if (flushRunner != NULL) { + flushRunner->Stop(); + delete flushRunner; + } + + statKeeper->Stop(); + statKeeper->PrintSummary(); + delete statKeeper; + } + +cleanup: + if (client) { + disconnect_client_and_wait(client); + } + + if (connection) { + hb_connection_destroy(connection); + } + + if (column) { + bytebuffer_free(column); + } + + if (families[0]) { + bytebuffer_free(families[0]); + } + + if (table) { + bytebuffer_free(table); + } + + if (logFile) { + fclose(logFile); + } + + return retCode; +} + +} /* namespace test */ +} /* namespace hbase */ diff --git a/hbase-native-client/src/test/native/perftest/stats_keeper.cc b/hbase-native-client/src/test/native/perftest/stats_keeper.cc new file mode 100644 index 000000000000..244ae83028c4 --- /dev/null +++ b/hbase-native-client/src/test/native/perftest/stats_keeper.cc @@ -0,0 +1,205 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#line 19 "stats_keeper.cc" // ensures short filename in logs. + +#include +#include +#include +#include +#include + +#include "stats_keeper.h" + +namespace hbase { +namespace test { + +const char* StatKeeper::OP_TYPE_NAMES[] = { + (const char*)"PUT", + (const char*)"GET", + (const char*)"FLUSH" +}; + +StatKeeper::OperationType:: +OperationType(const char* name) +: name_(name){ + numOps_ = success_ = failure_ = 0; + cumLatencyOps_ = 0; + minLatencyOps_ = -1; + maxLatencyOps_ = 0; + opsStartTime_ = opsEndTime_ = 0; + pthread_mutex_init(&mutexes_, NULL); +} + +StatKeeper::OperationType:: +~OperationType() { + pthread_mutex_destroy(&mutexes_); +} + +StatKeeper::StatKeeper() { + bufferableOpsCount_ = 0; + op_ = new OperationType*[OP_LAST]; + for (int i = 0; i < OP_LAST; ++i) { + op_[i] = new OperationType(OP_TYPE_NAMES[i]); + } +} + +StatKeeper::~StatKeeper() { + if (op_ != NULL) { + for (int i = 0; i < OP_LAST; ++i) { + delete op_[i]; + } + } + + delete[] op_; +} + +void +StatKeeper::RpcComplete(int32_t err, OpType type) { + if (type >= OP_LAST) { + return; + } + op_[type]->opsEndTime_ = currentTimeMicroSeconds(); + if (err) { + ++(op_[type]->failure_); // susceptible to race + } else { + ++(op_[type]->success_); // susceptible to race + } +} + +void +StatKeeper::UpdateStats(uint32_t numOps, + uint32_t elapsed, OpType type, bool isBufferable) { + if (type >= OP_LAST) { + return; + } + + OperationType *opType = op_[type]; + pthread_mutex_lock(&opType->mutexes_); + { + int64_t minLatencyOps = opType->minLatencyOps_; + int64_t maxLatencyOps = opType->maxLatencyOps_; + + if (opType->opsStartTime_ == 0) { + // first operation + minLatencyOps = elapsed; + opType->opsStartTime_ = currentTimeMicroSeconds(); + } + + if (elapsed < minLatencyOps) { + minLatencyOps = elapsed; + } + if (maxLatencyOps < elapsed) { + maxLatencyOps = elapsed; + } + + opType->minLatencyOps_ = minLatencyOps; + opType->maxLatencyOps_ = maxLatencyOps; + opType->numOps_ += numOps; + opType->cumLatencyOps_ += elapsed; + if (isBufferable) { + bufferableOpsCount_ += numOps; + } + } + pthread_mutex_unlock(&opType->mutexes_); +} + +void* +StatKeeper::Run() { + uint64_t prevNumOps[OP_LAST] = {0}; + uint64_t currentNumOps[OP_LAST] = {0}; + uint64_t totalOps; + uint64_t totalOpsLastSec; + int32_t statsCount = 0, lastStatsCount = 0; + + int32_t nsec = 0; + while (Running()) { + sleep(1); + ++nsec; + time_t t; + time(&t); + struct tm *timeinfo = localtime(&t); + int hour = timeinfo->tm_hour; + int min = timeinfo->tm_min; + int secs = timeinfo->tm_sec; + + statsCount = totalOps = totalOpsLastSec = 0; + for (int i = 0; i < OP_LAST; ++i) { + uint64_t numOpsForOp = op_[i]->numOps_; + if (!numOpsForOp) continue; + statsCount++; + currentNumOps[i] = numOpsForOp - prevNumOps[i]; + totalOps += numOpsForOp; + totalOpsLastSec += currentNumOps[i]; + } + + if ((nsec % 10) == 1 || statsCount > lastStatsCount) { + lastStatsCount = statsCount; + fprintf(stdout, "%8s %5s %9s %6s", + "Time", "Secs", "TotalOps", "Ops/s"); + for (int i = 0; i < OP_LAST; ++i) { + uint64_t numOpsForOp = op_[i]->numOps_; + if (!numOpsForOp) continue; + fprintf(stdout, "|[%-6s#] %6s %8s %8s %8s", + OP_TYPE_NAMES[i], "Ops/s", + "avg(us)", "max(us)", "min(us)"); + } + fprintf(stdout, "|\n"); + fflush(stdout); + } + + fprintf(stdout, "%02d:%02d:%02d %5d %9" PRIu64 " %6" PRIu64 "", + hour, min, secs, nsec, totalOps, totalOpsLastSec); + for (int i = 0; i < OP_LAST; ++i) { + uint64_t numOpsForOp = op_[i]->numOps_; + if (!numOpsForOp) continue; + fprintf(stdout, "|%9" PRIu64 " %6" PRIu64 " %8" PRIu64 " %8" PRIu64 " %8" PRIu64 "", + numOpsForOp, currentNumOps[i], + (op_[i]->cumLatencyOps_ / (numOpsForOp ? numOpsForOp : 1)), + op_[i]->maxLatencyOps_, op_[i]->minLatencyOps_); + } + fprintf(stdout, "|\n"); + fflush(stdout); + for (int i = 0; i < OP_LAST; ++i) { + prevNumOps[i] = op_[i]->numOps_; + } + } + + return NULL; +} + +void +StatKeeper::PrintSummary() { + fprintf(stdout, "============================================================================\n"); + for (int i = 0; i < OP_LAST; ++i) { + uint64_t numOpsForOp = op_[i]->numOps_; + if (!numOpsForOp) continue; + uint64_t runTimeForOp = (op_[i]->opsEndTime_ - op_[i]->opsStartTime_)/1000000; + fprintf(stdout, "[%5s] %10" PRIu64 " Ops, %" PRIu64 " Secs, %" PRIu64 " ops/s. " + "Success: %" PRIu64 ", Failures: %" PRIu64 ". " + "Latency(us): avg %" PRIu64 ", max %" PRIu64 ", min %" PRIu64 ".\n", + op_[i]->name_, numOpsForOp, runTimeForOp, (numOpsForOp/runTimeForOp), + op_[i]->success_, op_[i]->failure_, + (op_[i]->cumLatencyOps_ / (numOpsForOp ? numOpsForOp : 1)), + op_[i]->maxLatencyOps_, op_[i]->minLatencyOps_); + } + fprintf(stdout, "============================================================================\n"); + fflush(stdout); +} + +} /* namespace test */ +} /* namespace hbase */ diff --git a/hbase-native-client/src/test/native/perftest/stats_keeper.h b/hbase-native-client/src/test/native/perftest/stats_keeper.h new file mode 100644 index 000000000000..33706411c099 --- /dev/null +++ b/hbase-native-client/src/test/native/perftest/stats_keeper.h @@ -0,0 +1,87 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef HBASE_TESTS_STATS_H_ +#define HBASE_TESTS_STATS_H_ + +#include +#include +#include + +#include "test_types.h" + +namespace hbase { +namespace test { + +class StatKeeper : public TaskRunner { + +public: + typedef enum { + OP_PUT = 0, + OP_GET, + OP_FLUSH, + OP_LAST + } OpType; + + struct OperationType { + OperationType(const char *name); + ~OperationType(); + const char *name_; + volatile uint64_t numOps_; + volatile uint64_t success_; + volatile uint64_t failure_; + volatile uint64_t opsStartTime_; + volatile uint64_t opsEndTime_; + volatile uint64_t cumLatencyOps_; + volatile int64_t minLatencyOps_; + volatile int64_t maxLatencyOps_; + pthread_mutex_t mutexes_; + }; + + StatKeeper(); + + ~StatKeeper(); + + void *Run(); + + void UpdateStats(uint32_t numOps, uint32_t elapsed, OpType opType, bool isBufferable); + + void RpcComplete(int32_t err, OpType opType); + + volatile uint64_t GetBufferableOpsCount() { return bufferableOpsCount_; } + + void PrintSummary(); + + static const char* GetOpName(OpType type) { + if (type < 0 || type >= OP_LAST) { + return NULL; + } + return OP_TYPE_NAMES[type]; + } + +protected: + volatile uint64_t bufferableOpsCount_; + + OperationType **op_; + + static const char *OP_TYPE_NAMES[]; +}; + +} /* namespace test */ +} /* namespace hbase */ + +#endif /* HBASE_TESTS_STATS_H_ */ diff --git a/hbase-native-client/src/test/native/unittests/libhbaseutil.cc b/hbase-native-client/src/test/native/unittests/libhbaseutil.cc new file mode 100644 index 000000000000..2492e6725c5c --- /dev/null +++ b/hbase-native-client/src/test/native/unittests/libhbaseutil.cc @@ -0,0 +1,969 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#line 19 "libhbaseutil.cc" // ensures short filename in logs. + +#include +#include + +#include +#include +#include +#include + +#include "common_utils.h" +#include "libhbaseutil.h" + +namespace hbase { +namespace test { + +static int32_t retCode_delete_row = 0; +static int32_t ret_get_row = 0; +static int32_t ret_put_row = 0; +static int32_t ret_client_flush = 0; +static int32_t ret_scan = 0; +static uint64_t scan_num_rows = 0; +static uint64_t scan_cell_count = 0; + +void client_disconnection_callback(int32_t err, hb_client_t client, void *extra); +void wait_client_disconnection(); +void waitForGetsToComplete(); +void waitForDeletesToComplete(); +void waitForScanToComplete(); + +void delete_callback(int32_t err, hb_client_t client, hb_mutation_t del, hb_result_t result, + void *extra); +void put_callback(int32_t retCode, hb_client_t client, hb_mutation_t mutation, hb_result_t result, + void *extra); +void get_callback(int32_t status, hb_client_t client, hb_get_t get, hb_result_t result, + void *extra); +void scan_callback(int32_t err, hb_scanner_t scanner, hb_result_t results[], size_t num_results, + void *extra); +void release_row_data(row_data_t *row_data); +void release_scan_data(scan_data_t *scan_data); +char HBASE_MSG_BUFF[HBASE_MSG_LEN] = ""; +volatile int32_t client_destroyed = false; +pthread_cond_t client_destroyed_cv; +pthread_mutex_t client_destroyed_mutex; + +static volatile int32_t get_done = false; +static pthread_cond_t get_cv = PTHREAD_COND_INITIALIZER; +static pthread_mutex_t get_mutex = PTHREAD_MUTEX_INITIALIZER; + +static volatile int32_t outstanding_puts_count; +static pthread_cond_t puts_cv = PTHREAD_COND_INITIALIZER; +static pthread_mutex_t puts_mutex = PTHREAD_MUTEX_INITIALIZER; + +static volatile int32_t delete_done = false; +static pthread_cond_t del_cv = PTHREAD_COND_INITIALIZER; +static pthread_mutex_t del_mutex = PTHREAD_MUTEX_INITIALIZER; + +static volatile bool flush_done = false; +static pthread_cond_t flush_cv = PTHREAD_COND_INITIALIZER; +static pthread_mutex_t flush_mutex = PTHREAD_MUTEX_INITIALIZER; + +static volatile bool scan_done = false; +static pthread_cond_t scan_cv = PTHREAD_COND_INITIALIZER; +static pthread_mutex_t scan_mutex = PTHREAD_MUTEX_INITIALIZER; + +hb_cell_t *cell[64] = { NULL }; +ut_cell_data_t *cell_data[64] = { NULL }; + +hb_connection_t connection = NULL; +hb_client_t client = NULL; +hb_admin_t admin = NULL; + +ut_cell_data_t* +new_ut_cell_data() { + ut_cell_data_t *cell_data = (ut_cell_data_t*) calloc(1, sizeof(ut_cell_data_t)); + cell_data->next_cell = NULL; + return cell_data; +} + +int32_t +connectionCreate( + const char* zk_quorum, + const char *zk_root_node) { + int retCode = 0; + HBASE_LOG_INFO("creating connection with zk ensemble :%s root znode:%s ", zk_quorum, + zk_root_node); + if ((retCode = hb_connection_create(zk_quorum, zk_root_node, &connection)) != 0) { + + HBASE_LOG_FATAL("Could not create HBase connection returncode:%ld", retCode); + return retCode; + } + + else + HBASE_LOG_INFO("connection crate is successful"); + return retCode; + +} + +int32_t +clientCreate() { + int retCode = 0; + if (!connection) { + HBASE_LOG_INFO("not a valid connection"); + return retCode; + } + HBASE_LOG_INFO("creating clinet"); + if ((retCode = hb_client_create(connection, &client)) != 0) { + + HBASE_LOG_INFO("could not create client return code:%ld", retCode); + return retCode; + } else + HBASE_LOG_INFO("client creation is successful"); + + return retCode; + +} + +int32_t +adminCreate() { + int retCode = 0; + if ((retCode = hb_admin_create(connection, &admin)) != 0) { + + HBASE_LOG_INFO("could not create admin return code:%ld", retCode); + } else + HBASE_LOG_INFO("admin crate is successful"); + return retCode; + +} + +int32_t +connectionDestroy() { + + return hb_connection_destroy(connection); +} + +int32_t +clientDestroy() { + HBASE_LOG_INFO("client destory called"); + if (client) { + hb_client_destroy(client, client_disconnection_callback, NULL); + wait_client_disconnection(); + return 0; + } else { + HBASE_LOG_INFO("no valid client object :"); + return 1; + } + +} + +int32_t +adminDestroy() { + if (admin) { + return hb_admin_destroy(admin, NULL, NULL); + } + return 1; +} + +void +client_disconnection_callback( + int32_t err, + hb_client_t client, void *extra) { + HBASE_LOG_INFO("Received client disconnection callback."); + pthread_mutex_lock(&client_destroyed_mutex); + client_destroyed = true; + pthread_cond_signal(&client_destroyed_cv); + pthread_mutex_unlock(&client_destroyed_mutex); +} + +void +wait_client_disconnection() { + pthread_mutex_lock(&client_destroyed_mutex); + while (!client_destroyed) { + pthread_cond_wait(&client_destroyed_cv, &client_destroyed_mutex); + } + pthread_mutex_unlock(&client_destroyed_mutex); +} + +static void +client_flush_callback( + int32_t err, + hb_client_t client, + void *extra) { + ret_client_flush = err; + HBASE_LOG_INFO("Received client flush callback.retcode:%ld", err); + pthread_mutex_lock(&flush_mutex); + flush_done = true; + pthread_cond_signal(&flush_cv); + pthread_mutex_unlock(&flush_mutex); +} + +static void +waitForFlush() { + HBASE_LOG_INFO("Waiting for flush to complete."); + pthread_mutex_lock(&flush_mutex); + while (!flush_done) { + pthread_cond_wait(&flush_cv, &flush_mutex); + } + pthread_mutex_unlock(&flush_mutex); + HBASE_LOG_INFO("Flush completed."); +} + +int32_t +clientFlush() { + int32_t retCode; + if ((retCode = hb_client_flush(client, client_flush_callback, NULL)) != 0) { + HBASE_LOG_INFO("hb_client_flush failed with retCode:%ld", retCode); + return retCode; + } + waitForFlush(); + flush_done = false; //reset + return ret_client_flush; +} + +int32_t +deleteTableIfExists(const char *table_name) { + int32_t retCode = 0; + if ((retCode = hb_admin_table_exists(admin, NULL, table_name)) == 0) { + + HBASE_LOG_INFO("table :%s already exists deleting the table", table_name); + if ((retCode = hb_admin_table_delete(admin, NULL, table_name)) != 0) { + HBASE_LOG_FATAL("Could not delete table: %s return code:", table_name, retCode); + return retCode; + } + HBASE_LOG_INFO(" existing table:%s deleted", table_name); + } else + HBASE_LOG_INFO("table already exists returncode : %ld", retCode); + if (retCode == 2) + return 0; + else + return retCode; +} + +int32_t +deleteTable(const char *table_name) { + int32_t retCode = 0; + + if ((retCode = hb_admin_table_delete(admin, NULL, table_name)) != 0) { + HBASE_LOG_FATAL("Could not delete table:%s return code:%ld ", table_name, retCode); + } + return retCode; +} + +void +setLogLevel(HBaseLogLevel level) { + hb_log_set_level(level); +} + +HBaseLogLevel +getLogLevel() { + return hb_log_get_level(); +} + +int32_t +disableTable(const char *table_name) { + int32_t retCode; + retCode = hb_admin_table_disable(admin, NULL, table_name); + HBASE_LOG_INFO("disable table: %s return code:%ld", table_name, retCode); + return retCode; +} + +int32_t +enableTable(const char *table_name) { + int32_t retCode = 0; + retCode = hb_admin_table_enable(admin, NULL, table_name); + HBASE_LOG_INFO("enable table: %s return code:%ld", table_name, retCode); + return retCode; +} + +int32_t +isTableEnabled(const char *table_name) { + int32_t retCode = 0; + retCode = hb_admin_table_enabled(admin, NULL, table_name); + HBASE_LOG_INFO("enabled table:%s return code:%ld ", table_name, retCode); + return retCode; +} + +int32_t +createTable( + const char *table_name, + std::vector columnFamilies, + int maxVersions, + int minVersions, + int32_t ttl) { + hb_columndesc HCD[100] = { NULL }; + int32_t retCode = 0; + + for (uint32_t t = 0; t < columnFamilies.size(); ++t) { + byte_t *buffer = (byte_t *) columnFamilies.at(t).c_str(); + HBASE_LOG_DEBUG("column Family:%s ", buffer); + + retCode = hb_coldesc_create(buffer, columnFamilies.at(t).size(), &HCD[t]); + if (retCode != 0) { + HBASE_LOG_FATAL("Could not create column descriptor: returncode: %ld", retCode); + return retCode; + } + hb_coldesc_set_maxversions(HCD[t], maxVersions); + hb_coldesc_set_minversions(HCD[t], minVersions); + hb_coldesc_set_ttl(HCD[t], ttl); + hb_coldesc_set_inmemory(HCD[t], 1); + } + + HBASE_LOG_INFO("Creating table :%s column size:%d", table_name, columnFamilies.size()); + retCode = hb_admin_table_create(admin, NULL, table_name, HCD, columnFamilies.size()); + if (retCode != 0) { + HBASE_LOG_FATAL("Could not create table:%s return code:%ld ", table_name, retCode); + + } else { + HBASE_LOG_INFO("table :%s created successfully ", table_name); + } + + for (int t = 0; t < (int) columnFamilies.size(); ++t) { + hb_coldesc_destroy(HCD[t]); + } + + return retCode; +} + +int32_t +putRow( + std::string table_name, + std::string row_key, + std::vector data, + uint64_t ts, + hb_durability_t durability) { + srand(time(NULL)); + hb_put_t put = NULL; + int32_t retCode = 0; + + row_data_t *row_data = (row_data_t *) calloc(1, sizeof(row_data_t)); + row_data->key_ = bytebuffer_printf("%s", row_key.c_str()); + + HBASE_LOG_DEBUG("row_data key:%s", row_data->key_); + hb_put_create(row_data->key_->buffer, row_data->key_->length, &put); + HBASE_LOG_DEBUG("table name for put:%s", table_name.c_str()); + hb_mutation_set_table(put, (char*) table_name.c_str(), table_name.size()); + hb_mutation_set_durability(put, durability); + + for (int t = 0; t < (int) data.size(); ++t) { + HBASE_LOG_DEBUG("current data:%s", data.at(t).c_str()); + std::vector data_qualifier = SplitString(data.at(t), ':'); + + cell_data[t] = new_ut_cell_data(); + if (t == 0) + row_data->first_cell = cell_data[t]; + else + cell_data[t - 1]->next_cell = cell_data[t]; + + cell_data[t]->columnFamily_ = bytebuffer_printf("%s", data_qualifier[0].c_str()); + cell_data[t]->columnName_ = bytebuffer_printf("%s", data_qualifier[1].c_str()); + cell_data[t]->value_ = bytebuffer_printf("%s", data_qualifier[2].c_str()); + cell[t] = (hb_cell_t*) calloc(1, sizeof(hb_cell_t)); + cell_data[t]->hb_cell = cell[t]; + + cell[t] = (hb_cell_t*) calloc(1, sizeof(hb_cell_t)); + + cell[t]->row = row_data->key_->buffer; + cell[t]->row_len = row_data->key_->length; + + cell[t]->family = cell_data[t]->columnFamily_->buffer; + cell[t]->family_len = cell_data[t]->columnFamily_->length; + HBASE_LOG_DEBUG("column family :%s length:%d ", cell[t]->family, cell[t]->family_len); + cell[t]->qualifier = cell_data[t]->columnName_->buffer; + cell[t]->qualifier_len = cell_data[t]->columnName_->length; + HBASE_LOG_DEBUG("cell qualifer :%s length:%ld", cell[t]->qualifier, cell[t]->qualifier_len); + cell[t]->value = cell_data[t]->value_->buffer; + cell[t]->value_len = cell_data[t]->value_->length; + + cell[t]->ts = ts; + retCode = hb_put_add_cell(put, cell[t]); + if (retCode != 0) { + + HBASE_LOG_FATAL("Could not add cel to put:%s return code :%ld ", table_name.c_str(), retCode); + return retCode; + } + } + outstanding_puts_count++; + retCode = hb_mutation_send(client, put, put_callback, row_data); + if (retCode) { + HBASE_LOG_FATAL("mutation send is failed for table:%s return code:%ld ", table_name.c_str(), + retCode); + return retCode; + } else + HBASE_LOG_DEBUG("hb_mutation_send for put is success"); + + return retCode; +} + +int32_t +putRowAndWait( + std::string table_name, + std::string row_key_, + std::vector data, + uint64_t ts) { + int32_t retCode = 0; + retCode = putRow(table_name, row_key_, data, ts); + if (retCode) { + return retCode; + } + + HBASE_LOG_INFO("Waiting for put operation to complete."); + waitForPutsToComplete(); + + return ret_put_row; +} + +void +put_callback( + int32_t retCode, + hb_client_t client, + hb_mutation_t mutation, + hb_result_t result, + void *extra) { + ret_put_row = retCode; + row_data_t* row_data = (row_data_t *) extra; + HBASE_LOG_DEBUG("Received callback for row key:%s retCode:%ld ", row_data->key_->buffer, + retCode); + if (retCode == EAGAIN || retCode == ENOBUFS) { + HBASE_LOG_FATAL("received again/nobufs error retrying to send the put again for row key:%s", + row_data->key_->buffer); + sleep(1); + hb_mutation_send(client, mutation, put_callback, extra); + return; + } + + if (retCode != 0) { + HBASE_LOG_FATAL("fail to put row:%s return code:%d ", row_data->key_->buffer, retCode); + } + + HBASE_LOG_DEBUG("Received callback for row key:%s return code:%d ", + row_data->key_->buffer, retCode); + release_row_data(row_data); + hb_mutation_destroy(mutation); + + pthread_mutex_lock(&puts_mutex); + outstanding_puts_count--; + if (outstanding_puts_count == 0) { + pthread_cond_signal(&puts_cv); + } + pthread_mutex_unlock(&puts_mutex); +} + +bool +waitForPutsToComplete() { + HBASE_LOG_INFO("in wait for puts:"); + pthread_mutex_lock(&puts_mutex); + while (outstanding_puts_count > 0) { + pthread_cond_wait(&puts_cv, &puts_mutex); + } + pthread_mutex_unlock(&puts_mutex); + HBASE_LOG_INFO(" wait for puts done"); + return true; +} + +void +release_row_data(row_data_t *row_data) { + if (row_data != NULL) { + ut_cell_data_t *cell = row_data->first_cell; + while (cell) { + if (cell->value_) + bytebuffer_free(cell->value_); + + if (cell->columnFamily_) + bytebuffer_free(cell->columnFamily_); + if (cell->columnName_) + bytebuffer_free(cell->columnName_); + free(cell->hb_cell); + ut_cell_data_t *cur_cell = cell; + cell = cell->next_cell; + free(cur_cell); + } + bytebuffer_free(row_data->key_); + free(row_data); + } +} + +int32_t +getVerifyRow( + std::string table_name, + std::string row_key, + std::vector data, + bool isEntireRow, + bool isEntireCF, + int versions, + uint64_t min_ts, + uint64_t max_ts) { + int32_t retCode; + row_data_t *row_data = (row_data_t *) calloc(1, sizeof(row_data_t)); + row_data->key_ = bytebuffer_printf("%s", row_key.c_str()); + + hb_get_t get = NULL; + hb_get_create(row_data->key_->buffer, row_data->key_->length, &get); + // time range is not yet supported + /*if(min_ts || max_ts) + { + HBASE_LOG_INFO("time range for get is specified min:",min_ts,"max:"< data_qualifier = SplitString(data.at(t), ':'); + + cell_data[t] = new_ut_cell_data(); + if (t == 0) { + row_data->first_cell = cell_data[t]; + } + else { + cell_data[t - 1]->next_cell = cell_data[t]; + } + + cell_data[t]->columnFamily_ = bytebuffer_printf("%s", data_qualifier[0].c_str()); + if (data_qualifier.size() > 1) { // column qualifer + cell_data[t]->columnName_ = bytebuffer_printf("%s", data_qualifier[1].c_str()); + } + + // even for getting entire CF need to fill cell_data with cols, + // so that in get_callback we can validate the cells + if (!isEntireRow) { + HBASE_LOG_INFO("adding columns"); + if (!isEntireCF) { + hb_get_add_column(get, cell_data[t]->columnFamily_->buffer, + cell_data[t]->columnFamily_->length, cell_data[t]->columnName_->buffer, + cell_data[t]->columnName_->length); + } else { + hb_get_add_column(get, cell_data[t]->columnFamily_->buffer, + cell_data[t]->columnFamily_->length, NULL, 0); + } + } + } + hb_get_set_table(get, (char*) table_name.c_str(), table_name.size()); + hb_get_set_num_versions(get, versions); + + ret_get_row = 0; //reset retCode_get_row + get_done = false; //reset flag + + if ((retCode = hb_get_send(client, get, get_callback, row_data)) != 0) { + HBASE_LOG_INFO("hb_get_send failed with return code:%d", retCode); + return retCode; + } + waitForGetsToComplete(); + + return ret_get_row; +} + +void +waitForGetsToComplete() { + HBASE_LOG_INFO("in wait for get"); + pthread_mutex_lock(&get_mutex); + while (!get_done) { + pthread_cond_wait(&get_cv, &get_mutex); + } + pthread_mutex_unlock(&get_mutex); + HBASE_LOG_INFO("wait for get done."); +} + +void +get_callback( + int32_t status, + hb_client_t client, + hb_get_t get, + hb_result_t result, + void *extra) { + const char *table_name; + size_t table_name_len; + size_t cell_count; + HBASE_LOG_INFO("get_callback return code:%ld", status); + ret_get_row = status; + row_data_t *row_data = (row_data_t *) extra; + ut_cell_data_t *cell = row_data->first_cell; + if (status == 0) { + hb_result_get_cell_count(result, &cell_count); + hb_result_get_table(result, &table_name, &table_name_len); + const hb_cell_t **cells; + hb_result_get_cells(result, &cells, &cell_count); + HBASE_LOG_INFO("cell count:%d", cell_count); + if (expectedNumberOfCellCount != 0 && cell_count != expectedNumberOfCellCount) { + HBASE_LOG_INFO("expected cell count:%ld actual result count:%ld", + expectedNumberOfCellCount, cell_count); + ret_get_row = MISMATCH_RECEIVED_CELL_COUNT; + } + + const hb_cell_t *mycell; + while (cell) { + HBASE_LOG_INFO("getting result for cf:%s", cell->columnFamily_->buffer); + if (hb_result_get_cell(result, cell->columnFamily_->buffer, cell->columnFamily_->length, + cell->columnName_->buffer, cell->columnName_->length, &mycell) == 0) { + HBASE_LOG_INFO("Cell found value :%s", mycell->value); + } else { + HBASE_LOG_INFO("Cell not found."); + // This error is specific to Testcode, for cell not found + ret_get_row = CELL_NOT_FOUND_ERR; + } + cell = cell->next_cell; + } + } + hb_get_destroy(get); + hb_result_destroy(result); + release_row_data(row_data); + pthread_mutex_lock(&get_mutex); + get_done = true; + pthread_cond_signal(&get_cv); + pthread_mutex_unlock(&get_mutex); +} + +int32_t +deleteRow( + std::string table_name, + std::string row_key, + std::vector data) { + return deleteRow(table_name, row_key, data, HBASE_LATEST_TIMESTAMP); +} + +// Input: data is in format "CF:Column" +// If there is only "CF", then delete all the columns of that CF +// If data is NULL, then delete the entire row +int32_t +deleteRow( + std::string table_name, + std::string row_key, + std::vector data, + uint64_t ts) { + int32_t retCode = 0; + + hb_delete_t del = NULL; + row_data_t *row_data = (row_data_t *) calloc(1, sizeof(row_data_t)); + row_data->key_ = bytebuffer_printf("%s", row_key.c_str()); + + HBASE_LOG_INFO("row_data key:%s", row_data->key_); + + hb_delete_create(row_data->key_->buffer, row_data->key_->length, &del); + + // If data is NULL, then delete the entire row + for (int t = 0; t < (int) data.size(); t++) { + std::vector data_qualifier = SplitString(data.at(t), ':'); + if (data_qualifier[0].size() == 0) { + HBASE_LOG_INFO("Deleting the entire row."); + break; + } + + if (data_qualifier.size() == 1) { + HBASE_LOG_INFO("Deleting all the columns of CF:%s", data_qualifier[0].c_str()); + hb_delete_add_column(del, (byte_t *) data_qualifier[0].c_str(), data_qualifier[0].size(), + NULL, 0, ts); + } else { + HBASE_LOG_INFO("Deleting cf:%s column:%s", data_qualifier[0].c_str(), + data_qualifier[1].c_str()); + hb_delete_add_column(del, (byte_t *) data_qualifier[0].c_str(), data_qualifier[0].size(), + (byte_t *) data_qualifier[1].c_str(), data_qualifier[1].size(), ts); + } + } + + hb_mutation_set_table(del, (char*) table_name.c_str(), table_name.size()); + retCode_delete_row = 0; //reset retCode_delete_row + delete_done = false; //reset delete_done flag + if ((retCode = hb_mutation_send(client, del, delete_callback, row_data)) != 0) { + HBASE_LOG_ERROR("hb_mutation_send for delete failed:%d", retCode); + return retCode; + } + + HBASE_LOG_INFO("hb_mutation_send for delete is success"); + HBASE_LOG_INFO("Waiting for delete operation to complete."); + waitForDeletesToComplete(); + HBASE_LOG_INFO("Delete operation completed."); + return retCode_delete_row; +} + +void +delete_callback( + int32_t retCode, + hb_client_t client, + hb_mutation_t del, + hb_result_t result, + void *extra) { + row_data_t* row_data = (row_data_t *) extra; + HBASE_LOG_INFO("Received delete_callback for row key_:%s retcode:%d ", + row_data->key_->buffer, retCode); + if (retCode != 0) { + HBASE_LOG_FATAL("fail to delete row:%s retcode:%d ", row_data->key_->buffer, retCode); + } + + retCode_delete_row = retCode; + hb_mutation_destroy(del); + pthread_mutex_lock(&del_mutex); + delete_done = true; + pthread_cond_signal(&del_cv); + pthread_mutex_unlock(&del_mutex); +} + +void +waitForDeletesToComplete() { + HBASE_LOG_INFO("in wait for delete"); + pthread_mutex_lock(&del_mutex); + while (!delete_done) { + pthread_cond_wait(&del_cv, &del_mutex); + } + pthread_mutex_unlock(&del_mutex); + HBASE_LOG_INFO("wait for delete done."); +} + +int32_t +scanTable( + std::string table_name, + int32_t num_versions, + uint64_t max_num_rows, + std::string start_row_key, + std::string end_row_key, + std::string name_space) { + hb_scanner_t scanner = NULL; + hb_scanner_create(client, &scanner); + int32_t retCode; + scan_num_rows = 0; + scan_cell_count = 0; + scan_done = false; + + scan_data_t *scan_data = (scan_data_t *) calloc(1, sizeof(scan_data_t)); + scan_data->table_name_ = bytebuffer_printf("%s", table_name.c_str()); + + if ((retCode = hb_scanner_set_table(scanner, (char *) scan_data->table_name_->buffer, + scan_data->table_name_->length)) != 0) { + HBASE_LOG_INFO("scanner set table failed with return code:%d", retCode); + return retCode; + } + + if (!start_row_key.empty()) { + scan_data->start_row_key_ = bytebuffer_printf("%s", start_row_key.c_str()); + hb_scanner_set_start_row(scanner, scan_data->start_row_key_->buffer, + scan_data->start_row_key_->length); + } + + if (!end_row_key.empty()) { + scan_data->end_row_key_ = bytebuffer_printf("%s", end_row_key.c_str()); + hb_scanner_set_end_row(scanner, scan_data->end_row_key_->buffer, + scan_data->end_row_key_->length); + } + + hb_scanner_set_num_versions(scanner, num_versions); + + if (max_num_rows != 0) { + HBASE_LOG_INFO("setting max num rows for scan :%ld", max_num_rows); + hb_scanner_set_num_max_rows(scanner, max_num_rows); + } + + retCode = hb_scanner_next(scanner, scan_callback, scan_data); + if (retCode == 0) { + waitForScanToComplete(); + return ret_scan; + } else { + HBASE_LOG_INFO(" scanner failed with retcode:%ld", retCode); + } + + return retCode; +} + +void +scan_callback( + int32_t err, + hb_scanner_t scanner, + hb_result_t results[], + size_t num_results, + void *extra) { + HBASE_LOG_INFO("scan_callback return code:%ld", err); + ret_scan = err; + scan_data_t* scan_data = (scan_data_t *) extra; + + if (num_results) { + if (maxNumberOfRows != 0 && maxNumberOfRows < num_results) { + HBASE_LOG_INFO("max number of rows:%ld results in scan:%ld", maxNumberOfRows, num_results); + err = MISMATCH_MAX_ROW_COUNT; + } + + scan_num_rows += num_results; + const char *table_name; + size_t table_name_len; + hb_result_get_table(results[0], &table_name, &table_name_len); + HBASE_LOG_INFO("Received scan_next callback for table:%s results:%ld", table_name, num_results); + + for (uint32_t i = 0; i < num_results; ++i) { + size_t cell_count = 0; + hb_result_get_cell_count(results[i], &cell_count); + const byte_t *key = NULL; + size_t key_len = 0; + hb_result_get_key(results[i], &key, &key_len); + HBASE_LOG_DEBUG("scanned key:%s", key); + + scan_cell_count += cell_count; + hb_result_destroy(results[i]); + } + hb_scanner_next(scanner, scan_callback, extra); + } else { + HBASE_LOG_INFO("scan completed"); + if (scan_num_rows != expectedNumberOfRowCount) { + HBASE_LOG_INFO("expected row count:%ld actual scan count:%ld", + expectedNumberOfRowCount, scan_num_rows); + ret_scan = MISMATCH_RECEIVED_ROW_COUNT; + } + + if (expectedNumberOfCellCount && scan_cell_count != expectedNumberOfCellCount) { + HBASE_LOG_INFO("expected cell count:%ld actual scan count:%ld", + expectedNumberOfCellCount, scan_cell_count); + ret_scan = MISMATCH_RECEIVED_CELL_COUNT; + } + + release_scan_data(scan_data); + hb_scanner_destroy(scanner, NULL, NULL); + pthread_mutex_lock(&scan_mutex); + scan_done = true; + pthread_cond_signal(&scan_cv); + pthread_mutex_unlock(&scan_mutex); + } +} + +void +release_scan_data(scan_data_t *scan_data) { + if (scan_data != NULL) { + if (scan_data->table_name_) + bytebuffer_free(scan_data->table_name_); + if (scan_data->start_row_key_) + bytebuffer_free(scan_data->start_row_key_); + if (scan_data->end_row_key_) + bytebuffer_free(scan_data->end_row_key_); + } +} + +void +waitForScanToComplete() { + HBASE_LOG_INFO("Waiting for scan to complete."); + pthread_mutex_lock(&scan_mutex); + while (!scan_done) { + pthread_cond_wait(&scan_cv, &scan_mutex); + } + pthread_mutex_unlock(&scan_mutex); + HBASE_LOG_INFO("Scan completed."); +} + +/** + * Other utility functions + */ +static std::map s_ConfigOptions; + +static const char *CONFIG_FILE_PATH = "src/test/resources/config.properties"; + +static int32_t +InitConfig() { + std::string line, eq, val; + std::ifstream myfile(CONFIG_FILE_PATH); + if (myfile.is_open()) { + while (getline(myfile, line)) { + if (line.size() == 0 || line[0] == '#') continue; // skip empty lines and comments + std::vector data = SplitString(line, '='); + if(data.size() < 2) { + fprintf(stdout, "Parse error for line '%s'.\n", line.c_str()); + continue; + } + const char *env = getenv(data[0].c_str()); + s_ConfigOptions[data[0]] = env ? env : data[1]; + } + return 0; + } else { + fprintf(stdout, "No config file : %s\n",CONFIG_FILE_PATH); + return 1; + } +} + +std::string +GetConfigParameter(std::string key) { + if (s_ConfigOptions.empty()) { + InitConfig(); + } + return s_ConfigOptions.find(key)->second; +} + +std::vector +SplitString(const std::string &strLine, char delim) { + std::string strTempString; + std::vector splitIndices; + std::vector splitLine; + int nCharIndex = 0; + int nLineSize = strLine.size(); + + // find indices + for(int i = 0; i < nLineSize; i++) { + if(strLine[i] == delim) + splitIndices.push_back(i); + } + splitIndices.push_back(nLineSize); // end index + + // fill split lines + for(int i = 0; i < (int)splitIndices.size(); i++) { + strTempString = strLine.substr(nCharIndex, (splitIndices[i] - nCharIndex)); + splitLine.push_back(strTempString); + nCharIndex = splitIndices[i] + 1; + } + return splitLine; +} + +static int32_t +EnsureParentDir(const char *filePath) { + if (!filePath) { + fprintf(stdout, "filePath is NULL.""\n"); + return EINVAL; + } + + char *dup_path = strdup(filePath); + if (dup_path) { + size_t path_len = strlen(dup_path); + for (size_t i = 1; i < path_len; ++i) { // skip first '/', if exists. + if (dup_path[i] == '/' || dup_path[i] == '\\') { + dup_path[i] = '\0'; + if (mkdir(dup_path, 0) && errno != EEXIST) { + fprintf(stdout, "Failed to create folder %s.""\n", dup_path); + perror(NULL); + free(dup_path); + return errno; + } + dup_path[i] = '/'; + } + } + free(dup_path); + } + return 0; +} + +static FILE *logFile = NULL; + +int32_t +InitLogger(std::string logFilePath) { + const char *log_file_path = logFilePath.c_str(); + if (EnsureParentDir(log_file_path)) { + return errno; + } + + fprintf(stdout, "Initializing HBase logger with file: %s\n", log_file_path); + logFile = fopen(log_file_path, "a"); + if (!logFile) { + fprintf(stdout, "Unable to open log file \"%s\"", log_file_path); + perror(NULL); + return errno; + } + hb_log_set_stream(logFile); // defaults to stderr + return 0; +} + +int32_t +CloseLogger() { + if (logFile) { + fclose(logFile); + } + return 0; +} + +} /* namespace test */ +} /* namespace hbase */ diff --git a/hbase-native-client/src/test/native/unittests/libhbaseutil.h b/hbase-native-client/src/test/native/unittests/libhbaseutil.h new file mode 100644 index 000000000000..1f08b2dc189a --- /dev/null +++ b/hbase-native-client/src/test/native/unittests/libhbaseutil.h @@ -0,0 +1,113 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HBASE_TEST_UTIL_H +#define HBASE_TEST_UTIL_H + +#include +#include + +#include +#include + +#include + +#include "byte_buffer.h" + +#define CELL_NOT_FOUND_ERR 0xFF12 +#define MISMATCH_RECEIVED_CELL_COUNT 0xFF13 +#define MISMATCH_RECEIVED_ROW_COUNT 0xFF14 +#define MISMATCH_MAX_ROW_COUNT 0xFF15 + +#define HBASE_MSG_LEN 1024 + +namespace hbase { +namespace test { + +int32_t +InitLogger(std::string); + +int32_t +CloseLogger(); + +std::string +GetConfigParameter(std::string); + +std::vector +SplitString(const std::string &strLine, char delim); + +typedef struct ut_cell_data_t_ { + bytebuffer value_; + bytebuffer columnFamily_; + bytebuffer columnName_; + bytebuffer ts_; + hb_cell_t *hb_cell; + struct ut_cell_data_t_ *next_cell; +} ut_cell_data_t; + +typedef struct row_data_t_ { + bytebuffer key_; + struct ut_cell_data_t_ *first_cell; +} row_data_t; + +typedef struct scan_data_t_ { + bytebuffer table_name_; + bytebuffer start_row_key_; + bytebuffer end_row_key_; + bytebuffer name_space; +} scan_data_t; + +extern hb_connection_t connection; +extern hb_client_t client; +extern hb_admin_t admin; +extern uint64_t expectedNumberOfCellCount; +extern uint64_t expectedNumberOfRowCount; +extern uint64_t maxNumberOfRows; + +int32_t connectionCreate(const char *zk_ensemble, const char *zk_root_znode); +int32_t clientCreate(); +int32_t adminCreate(); +int32_t connectionDestroy(); +int32_t adminDestroy(); +int32_t clientDestroy(); +int32_t deleteTableIfExists(const char *table_name); +int32_t createTable(const char *table_name, std::vector columnFamilies, + int maxVersions = 3, int minVersions = 3, int32_t ttl = 99999999/*some max value*/); +int32_t disableTable(const char *table_name); +int32_t enableTable(const char *table_name); +int32_t deleteTable(const char *table_name); +int32_t isTableEnabled(const char *table_name); +void setLogLevel(HBaseLogLevel level); +HBaseLogLevel getLogLevel(); +int32_t clientFlush(); +int32_t putRow(std::string table_name, std::string row_key, std::vector row_data, + uint64_t ts = HBASE_LATEST_TIMESTAMP, hb_durability_t durability = DURABILITY_USE_DEFAULT); +int32_t putRowAndWait(std::string table_name, std::string row_key, std::vector data, + uint64_t ts = HBASE_LATEST_TIMESTAMP); +int32_t getVerifyRow(std::string table_name, std::string row_key, std::vector row_data, +bool isEntireRow = false, bool isEntireCF = false, int versions = 3, uint64_t min_ts = 0, + uint64_t max_ts = 0); +int32_t deleteRow(std::string table_name, std::string row_key, std::vector row_data, + uint64_t ts = HBASE_LATEST_TIMESTAMP); +int32_t scanTable(std::string table_name, int32_t num_versions = 1, uint64_t max_num_rows = 0, + std::string start_row_key = "", std::string end_row_key = "", std::string name_space = ""); +bool waitForPutsToComplete(); + +} /* namespace test */ +} /* namespace hbase */ + +#endif /* HBASE_TEST_UTIL_H*/ diff --git a/hbase-native-client/src/test/native/unittests/test_async.cc b/hbase-native-client/src/test/native/unittests/test_async.cc new file mode 100644 index 000000000000..d8fed6cef628 --- /dev/null +++ b/hbase-native-client/src/test/native/unittests/test_async.cc @@ -0,0 +1,1062 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#line 19 "test_async.cc" // ensures short filename in logs. + +#include +#include +#include + +#include +#include + +#include "common_utils.h" +#include "libhbaseutil.h" + +namespace hbase { +namespace test { + +static const char *TABLE_CREATE_FILE = "src/test/resources/table_create.dat"; +static const char *PUT_ROWS_FILE = "src/test/resources/table_put.dat"; + +static std::string zk_quorum = ""; +static std::string zk_root_node = ""; +static std::string log_file = ""; + +uint64_t expectedNumberOfCellCount = 0; +uint64_t expectedNumberOfRowCount = 0; +uint64_t maxNumberOfRows = 0; + +class HBaseCAPI: public ::testing::Test { + // shared by all tests. +protected: + // Per-test-case set-up. + // Called before the first test in this test case. + static void SetUpTestCase() { + fprintf(stdout, "\n **** HBaseCAPI::SetUpTestCase **** \n"); + log_file = GetConfigParameter("LIBHBASE_LOG_FILE"); + InitLogger(log_file); + zk_quorum = GetConfigParameter("LIBHBASE_ZK_QUORUM"); + zk_root_node = GetConfigParameter("LIBHBASE_ZK_ROOT_NODE"); + + HBASE_LOG_INFO("Using Zookeeper quorum: '%s'", zk_quorum.c_str()); + HBASE_LOG_INFO("zk_root_node: '%s'", zk_root_node.c_str()); + if (zk_root_node.empty()) { + ASSERT_EQ(connectionCreate((const char*)zk_quorum.c_str(), NULL), 0); + } else { + ASSERT_EQ(connectionCreate((const char*)zk_quorum.c_str(), + (const char*) zk_root_node.c_str()), 0); + } + ASSERT_EQ(clientCreate(), 0); + ASSERT_EQ(adminCreate(), 0); + } + + // Per-test-case tear-down. + // Called after the last test in this test case. + static void TearDownTestCase() { + ASSERT_EQ(adminDestroy(), 0); + ASSERT_EQ(clientDestroy(), 0); + ASSERT_EQ(connectionDestroy(), 0); + ASSERT_EQ(CloseLogger(), 0); + fprintf(stdout, "\n **** HBaseCAPI::TearDownTestCase **** \n"); + } + + virtual void SetUp() { } + + virtual void TearDown() { } +}; + +TEST_F(HBaseCAPI, table_create) { + std::string line; + std::vector words; + std::string table_name = ""; + + HBASE_LOG_INFO("*** hbase table create API test ***"); + std::ifstream myfile(TABLE_CREATE_FILE); + if (myfile.is_open()) { + while (getline(myfile, line)) { + std::vector columnFamilies; + words = SplitString(line, ','); + for (int t = 0; t < (int) words.size(); ++t) { + HBASE_LOG_DEBUG("splitted word:%s", words.at(t).c_str()); + if (t == 0) { + table_name = words.at(t); + } else { + columnFamilies.push_back(words.at(t)); + } + } + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ(createTable((char*)table_name.c_str(), columnFamilies), 0); + } + myfile.close(); + } else { + HBASE_LOG_FATAL("failed to open file:%s", TABLE_CREATE_FILE); + ASSERT_FALSE(myfile == NULL); + } +} + +TEST_F(HBaseCAPI, table_delete_non_exsting) { + std::string line; + std::vector words; + std::string table_name = "non_existing_table"; + + HBASE_LOG_INFO("*** table delete test with non existing table ***"); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ(deleteTable((char*)table_name.c_str()), 2); +} + +TEST_F(HBaseCAPI, table_create_existing) { + std::string line; + std::vector words; + std::string table_name = "test_table"; + std::vector columnFamilies { "testcf1", "testcf2" }; + + HBASE_LOG_INFO("*** table create test with already existing table name***"); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ(createTable((char*)table_name.c_str(), columnFamilies), 0); + ASSERT_EQ(createTable((char*)table_name.c_str(), columnFamilies), 17); +} + +TEST_F(HBaseCAPI, disable_enableTable) { + std::string table_name = "test_table"; + std::vector columnFamilies { "testcf1", "testcf2" }; + + HBASE_LOG_INFO(" **** table disable enable API test ****"); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ(createTable((char*)table_name.c_str(), columnFamilies), 0); + ASSERT_EQ(disableTable((char*)table_name.c_str()), 0); + ASSERT_EQ(enableTable((char*)table_name.c_str()), 0); +} + +TEST_F(HBaseCAPI, disable_enableTable_multiple_times) { + std::string table_name = "test_table"; + std::vector columnFamilies { "testcf1", "testcf2" }; + + HBASE_LOG_INFO("**** table disable enable table multiple times ****"); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ(createTable((char*)table_name.c_str(), columnFamilies), 0); + EXPECT_EQ(disableTable((char*)table_name.c_str()), 0); + EXPECT_EQ(disableTable((char*)table_name.c_str()), 0); + EXPECT_EQ(enableTable((char*)table_name.c_str()), 0); + EXPECT_EQ(enableTable((char*)table_name.c_str()), 0); +} + +TEST_F(HBaseCAPI, disable_enable_non_existing_table) { + std::string table_name = "test_table"; + std::vector columnFamilies { "testcf1", "testcf2" }; + + HBASE_LOG_INFO("**** table disable enable with non existing table ****"); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ(enableTable((char*)table_name.c_str()), 2); +} + +TEST_F(HBaseCAPI, enabled_verification) { + std::string table_name = "test_table"; + std::vector columnFamilies { "testcf1", "testcf2" }; + + HBASE_LOG_INFO("******* table is enabled API test *****"); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ(isTableEnabled((char*)table_name.c_str()), 2); // non existing table test + ASSERT_EQ(createTable((char*)table_name.c_str(), columnFamilies), 0); + ASSERT_EQ(isTableEnabled((char*)table_name.c_str()), 0); + ASSERT_EQ(disableTable((char*)table_name.c_str()), 0); + ASSERT_EQ(isTableEnabled((char*)table_name.c_str()), HBASE_TABLE_DISABLED); +} + +TEST_F(HBaseCAPI, put_test) { + std::string line; + std::vector words; + bool table_created = false; + + HBASE_LOG_INFO("*** table put API test ***"); + HBASE_LOG_INFO("table put API test with input file:%s", PUT_ROWS_FILE); + + std::ifstream myfile(PUT_ROWS_FILE); + if (myfile.is_open()) { + std::string table_name = ""; + while (getline(myfile, line)) { + if (line.at(0) == '#') { + HBASE_LOG_DEBUG("this line is comment in file skipping .."); + continue; + } + std::vector columnFamilies; + std::vector rowColumns; + HBASE_LOG_DEBUG("current line:%s", line.c_str()); + words = SplitString(line, ','); + std::string row_key = ""; + for (int t = 0; t < (int) words.size(); ++t) { + HBASE_LOG_DEBUG("splitted word:%s ", words.at(t).c_str()); + if (!table_created) { + if (t == 0) { + table_name = words.at(t); + } else { + columnFamilies.push_back(words.at(t)); + } + } else { + if (t == 0) { + row_key = words.at(t); + } else { + rowColumns.push_back(words.at(t)); + } + } + } + if (!table_created) { + HBASE_LOG_INFO("creating table:%s ", words.at(0).c_str()); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ(createTable((char*)table_name.c_str(), columnFamilies), 0); + table_created = true; + } else { + HBASE_LOG_INFO("inserting row to table: %s with key: %s", + table_name.c_str(), row_key.c_str()); + ASSERT_EQ(putRow(table_name, row_key, rowColumns), 0); + } + } + HBASE_LOG_INFO("wait for puts.."); + waitForPutsToComplete(); + HBASE_LOG_INFO("wait for puts completed"); + + myfile.close(); + } else { + HBASE_LOG_FATAL("faild to open file:%s", PUT_ROWS_FILE); + ASSERT_FALSE(myfile == NULL); + } +} + +TEST_F (HBaseCAPI, put_non_existing_cf_async) { + std::string table_name = "put_table"; + std::string table_not_existing = "non_existing_table"; + + std::vector columnFamilies { "testcf1", "testcf2" }; + std::vector row1_data { + "testcf1:co1:4", "testcf1:col5:3", "testcf2:col1:6" }; + std::vector row2_data { + "testcf1:co1:4", "testcf1:col2:3", "testcf2:col1:6" }; + + HBASE_LOG_INFO("*** table put API test with non existing table and non existing CF ***"); + HBASE_LOG_INFO("creating table for put request:%s ", table_name.c_str()); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ(createTable((char*)table_name.c_str(), columnFamilies), 0); + + std::vector row1_cf_not_exist { "none:col6:3" }; + EXPECT_EQ(putRowAndWait(table_not_existing, "row1", row1_data), 2); + EXPECT_EQ(putRowAndWait(table_name, "row2", row1_cf_not_exist), 2); +} + +TEST_F(HBaseCAPI, get_test_async) { + std::string line; + std::vector words; + std::string table_name = "test_table1"; + + HBASE_LOG_INFO("*** hbase table get API test ***"); + std::vector columnFamilies { "testcf1", "testcf2" }; + std::vector row1_data { + "testcf1:co1:4", "testcf1:col5:3", "testcf2:col1:6" }; + std::vector row2_data { + "testcf1:co1:4", "testcf1:col2:3", "testcf2:col1:6" }; + + HBASE_LOG_INFO("creating table for get requrest:%s", table_name.c_str()); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ(createTable((char*)table_name.c_str(), columnFamilies), 0); + ASSERT_EQ(putRow(table_name, "row1", row1_data), 0); + ASSERT_EQ(putRow(table_name, "row2", row2_data), 0); + + HBASE_LOG_INFO("wait for puts.."); + ASSERT_TRUE(waitForPutsToComplete()); + HBASE_LOG_INFO("wait for puts completed"); + + std::vector row1_data1 { "testcf1:col6:3" }; + EXPECT_EQ(getVerifyRow(table_name, "row1", row1_data1), CELL_NOT_FOUND_ERR); + EXPECT_EQ(getVerifyRow(table_name, "row2", row2_data), 0); +} + +TEST_F (HBaseCAPI, get_entire_row_async) { + std::string table_name = "get_table_row"; + + HBASE_LOG_INFO("*** hbase table get entire row test ***"); + std::vector columnFamilies { "testcf1", "testcf2" }; + std::vector row_data { + "testcf1:co1:4", "testcf1:col5:3", "testcf2:col1:6", "testcf1:col:6" }; + + HBASE_LOG_INFO("creating table for get request:%s ", table_name.c_str()); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ(createTable((char*)table_name.c_str(), columnFamilies), 0); + EXPECT_EQ(0, putRow(table_name, "row1", row_data)); + HBASE_LOG_INFO("wait for puts.."); + ASSERT_TRUE(waitForPutsToComplete()); + + HBASE_LOG_INFO("wait for puts completed"); + EXPECT_EQ(0, getVerifyRow(table_name, "row1", row_data, true, false)); +} + +TEST_F (HBaseCAPI, verify_cf_ttl_async) { + std::string table_name = "test_ttl"; + + HBASE_LOG_INFO("*** hbase table put and get with ttl ***"); + std::vector columnFamilies { "testcf1", "testcf2" }; + std::vector row_data { "testcf1:co1:4", "testcf1:col5:3", + "testcf2:col1:6", "testcf1:col:6" }; + + HBASE_LOG_INFO("creating table for get request:%s ", table_name.c_str()); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ( + createTable((char*)table_name.c_str(), columnFamilies, 3, 0/*min versions*/, + 1/*set ttl to 1*/), 0); + EXPECT_EQ(0, putRow(table_name, "row1", row_data)); + HBASE_LOG_INFO("wait for puts.."); + ASSERT_TRUE(waitForPutsToComplete()); + HBASE_LOG_INFO("wait for puts completed"); + + // sleep for 2 seconds so that cell will be deleted + sleep(2); + std::vector row1_valid_single_cell { "testcf1:co1:4" }; + EXPECT_EQ(getVerifyRow(table_name, "row1", row1_valid_single_cell), CELL_NOT_FOUND_ERR); +} + +TEST_F (HBaseCAPI, verify_cf_ttl_with_min_versions_async) { + std::string table_name = "test_ttl"; + + HBASE_LOG_INFO("*** hbase table put and get with ttl and min versions ***"); + std::vector columnFamilies { "testcf1", "testcf2" }; + std::vector row_data { + "testcf1:co1:4", "testcf1:col5:3", "testcf2:col1:6", "testcf1:col:6" }; + + HBASE_LOG_INFO("creating table for get request:%s ", table_name.c_str()); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ( + createTable((char*)table_name.c_str(), columnFamilies, 3, 1/*min versions*/, + 1/*set ttl to 1*/), 0); + EXPECT_EQ(0, putRow(table_name, "row1", row_data)); + HBASE_LOG_INFO("wait for puts.."); + ASSERT_TRUE(waitForPutsToComplete()); + HBASE_LOG_INFO("wait for puts completed"); + + // sleep for 2 seconds so that ttl will be expired + // but cell should not remove as min versions is 1 + sleep(2); + std::vector row1_valid_single_cell { "testcf1:co1:4" }; + EXPECT_EQ(getVerifyRow(table_name, "row1", row1_valid_single_cell), 0); +} + +TEST_F (HBaseCAPI, set_get_log_level) { + HBASE_LOG_INFO("setting and getting different log levels trade level"); + HBaseLogLevel level = HBASE_LOG_LEVEL_INFO; + setLogLevel(level); + EXPECT_EQ(getLogLevel(), HBASE_LOG_LEVEL_INFO); + + level = HBASE_LOG_LEVEL_TRACE; + setLogLevel(level); + EXPECT_EQ(getLogLevel(), HBASE_LOG_LEVEL_TRACE); + + level = (HBaseLogLevel) 9999; //set to invalid loglevel and it should not change log level + + setLogLevel(level); + EXPECT_EQ(getLogLevel(), HBASE_LOG_LEVEL_TRACE); +} + +TEST_F (HBaseCAPI, put_row_with_durability_async) { + std::string table_name = "test_table"; + HBASE_LOG_INFO("*** hbase table put row with durablity test ***"); + std::vector columnFamilies { "testcf1", "testcf2" }; + std::vector row_data { "testcf1:co1:4", "testcf1:col5:3", + "testcf2:col1:6", "testcf1:col:6" }; + + HBASE_LOG_INFO("creating table for get request:%s", table_name.c_str()); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ(createTable((char*)table_name.c_str(), columnFamilies), 0); + EXPECT_EQ(0, putRow(table_name, "row1", row_data, HBASE_LATEST_TIMESTAMP, DURABILITY_ASYNC_WAL)); + EXPECT_EQ(0, putRow(table_name, "row2", row_data, HBASE_LATEST_TIMESTAMP, DURABILITY_SYNC_WAL)); + EXPECT_EQ(0, putRow(table_name, "row3", row_data, HBASE_LATEST_TIMESTAMP, DURABILITY_SKIP_WAL)); + EXPECT_EQ(0, putRow(table_name, "row4", row_data, HBASE_LATEST_TIMESTAMP, DURABILITY_FSYNC_WAL)); + HBASE_LOG_INFO("wait for puts.."); + ASSERT_TRUE(waitForPutsToComplete()); + HBASE_LOG_INFO("wait for puts completed"); + + EXPECT_EQ(0, getVerifyRow(table_name, "row1", row_data, true, false)); + EXPECT_EQ(0, getVerifyRow(table_name, "row2", row_data, true, false)); + EXPECT_EQ(0, getVerifyRow(table_name, "row3", row_data, true, false)); + EXPECT_EQ(0, getVerifyRow(table_name, "row4", row_data, true, false)); +} + +TEST_F (HBaseCAPI, get_entire_row_disabled_table_async) { + std::string table_name = "test_table"; + + HBASE_LOG_INFO("*** hbase table get entire row from a disabled table***"); + std::vector columnFamilies { "testcf1", "testcf2" }; + std::vector row_data { "testcf1:co1:4", "testcf1:col5:3", "testcf2:col1:6", + "testcf1:col:6" }; + + HBASE_LOG_INFO("creating table for get request:%s ", table_name.c_str()); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ(createTable((char*)table_name.c_str(), columnFamilies), 0); + EXPECT_EQ(0, putRow(table_name, "row1", row_data)); + HBASE_LOG_INFO("wait for puts.."); + ASSERT_TRUE(waitForPutsToComplete()); + HBASE_LOG_INFO("wait for puts completed"); + + // disable table now + ASSERT_EQ(disableTable((char*)table_name.c_str()), 0); + // FIXME: this one currently return HBASE_INTERNAL_ERR + // instead of HBASE_TABLE_DISABLED, require fix in region server + fprintf(stdout, "**** Attempting to fetch a row from a disabled table. This is going to take a while ****\n"); + fflush(stdout); + EXPECT_EQ(HBASE_INTERNAL_ERR, getVerifyRow(table_name, "row1", row_data, true, false)); +} + +TEST_F (HBaseCAPI, client_flush) { + std::string table_name = "flush_table"; + + HBASE_LOG_INFO("*** hbase table get entire row test ***"); + std::vector columnFamilies { "testcf1", "testcf2" }; + std::vector row_data { "testcf1:co1:4", "testcf1:col5:3", "testcf2:col1:6", + "testcf1:col:6" }; + + HBASE_LOG_INFO("creating table for get request:%s ", table_name.c_str()); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ(createTable((char*)table_name.c_str(), columnFamilies), 0); + EXPECT_EQ(0, putRow(table_name, "row1", row_data)); + EXPECT_EQ(0, putRow(table_name, "row2", row_data)); + EXPECT_EQ(0, putRow(table_name, "row3", row_data)); + HBASE_LOG_INFO("doing clientFlush"); + EXPECT_EQ(0, clientFlush()); + HBASE_LOG_INFO("flush Completed"); + HBASE_LOG_INFO("wait for puts.."); + ASSERT_TRUE(waitForPutsToComplete()); + HBASE_LOG_INFO("wait for puts completed"); + + EXPECT_EQ(0, getVerifyRow(table_name, "row1", row_data, true, false)); +} + +TEST_F (HBaseCAPI, get_entire_cf_async) { + std::string table_name = "test_table"; + + HBASE_LOG_INFO("*** hbase table get entire column family test ***"); + std::vector columnFamilies { "testcf1", "testcf2" }; + std::vector row_data { "testcf1:co1:4", "testcf1:col5:3", "testcf2:col1:6", + "testcf1:col:6" }; + + HBASE_LOG_INFO("creating table for get request:%s ", table_name.c_str()); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ(createTable((char*)table_name.c_str(), columnFamilies), 0); + EXPECT_EQ(0, putRow(table_name, "row1", row_data)); + + HBASE_LOG_INFO("wait for puts.."); + ASSERT_TRUE(waitForPutsToComplete()); + HBASE_LOG_INFO("wait for puts completed"); + + std::vector expected_data { "testcf1:co1:4", "testcf1:col5:3", "testcf1:col:6" }; + EXPECT_EQ(0, getVerifyRow(table_name, "row1", expected_data, false, true)); +} + +TEST_F (HBaseCAPI, get_test_with_invalid_cf_table_async) { + std::string table_name = "test_table"; + std::vector columnFamilies { "testcf1", "testcf2" }; + std::vector row1_data { + "testcf1:co1:4", "testcf1:col5:3", "testcf2:col1:6", "testcf1:col:6" }; + std::vector row2_data { "testcf1:co1:4", "testcf1:col2:3", "testcf2:col1:6" }; + + HBASE_LOG_INFO("*** hbase table get test with invalid cf and with invalid table name ***"); + HBASE_LOG_INFO("creating table for get request:%s ", table_name.c_str()); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ(createTable((char*)table_name.c_str(), columnFamilies), 0); + EXPECT_EQ(0, putRow(table_name, "row1", row1_data)); + EXPECT_EQ(0, putRow(table_name, "row2", row2_data)); + HBASE_LOG_INFO("wait for puts.."); + ASSERT_TRUE(waitForPutsToComplete()); + HBASE_LOG_INFO("wait for puts completed"); + + std::vector invalid_CF { "none" }; + std::vector valid_CF { "testcf1" }; + std::string table_name_invalid = "no_table_with_this_name"; + EXPECT_EQ(2, getVerifyRow(table_name, "row2", invalid_CF, false, true)); + EXPECT_EQ(2, getVerifyRow(table_name_invalid, "row1", valid_CF, true)); +} + +TEST_F(HBaseCAPI, get_test_with_versions) { + std::string table_name = "test_table"; + HBASE_LOG_INFO("*** table get test with specified number of versions ***"); + std::vector columnFamilies { "testcf1", "testcf2" }; + std::vector row1_data { + "testcf1:co1:4", "testcf1:col5:3", "testcf2:col1:6", "testcf1:col:6" }; + + HBASE_LOG_INFO("creating table for get request:%s ", table_name.c_str()); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + // create table with versions as 4 + ASSERT_EQ(createTable((char*)table_name.c_str(), columnFamilies, 4), 0); + + // perform putRow 4 times so that it creates the versions + EXPECT_EQ(0, putRowAndWait(table_name, "row1", row1_data)); + EXPECT_EQ(0, putRowAndWait(table_name, "row1", row1_data)); + EXPECT_EQ(0, putRowAndWait(table_name, "row1", row1_data)); + EXPECT_EQ(0, putRowAndWait(table_name, "row1", row1_data)); + expectedNumberOfCellCount = 16; // 4 versions for 4 columns so expected cell count :16 + EXPECT_EQ(0, getVerifyRow(table_name, "row1", row1_data, false, false, 4)); + expectedNumberOfCellCount = 0; +} + +TEST_F(HBaseCAPI, delete_singlecell_test_async) { + std::string line; + std::vector words; + std::string table_name = "test_table"; + + HBASE_LOG_INFO("*** hbase table delete single cell test ***"); + std::vector columnFamilies { "testcf1", "testcf2" }; + std::vector row1_data { "testcf1:col1:4", "testcf1:col5:3", "testcf2:col1:6" }; + std::vector row2_data { "testcf1:col1:4", "testcf1:col2:3", "testcf2:col1:6" }; + std::vector row3_data { "testcf1:col1:8", "testcf1:col2:9", "testcf1:col6:19", + "testcf2:col1:10", "testcf2:col2:9" }; + HBASE_LOG_INFO("creating table:%s", table_name.c_str()); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ(createTable((char*)table_name.c_str(), columnFamilies), 0); + ASSERT_EQ(putRow(table_name, "row1", row1_data), 0); + ASSERT_EQ(putRow(table_name, "row2", row2_data), 0); + ASSERT_EQ(putRow(table_name, "row3", row3_data), 0); + HBASE_LOG_INFO("wait for puts.."); + ASSERT_TRUE(waitForPutsToComplete()); + HBASE_LOG_INFO("wait for puts completed"); + + std::vector row1_valid_single_cell { "testcf1:col1" }; + std::vector row2_valid_single_cell { "testcf1:col2" }; + + EXPECT_EQ(getVerifyRow(table_name, "row1", row1_valid_single_cell), 0); + EXPECT_EQ(deleteRow(table_name, "row1", row1_valid_single_cell), 0); + EXPECT_EQ(getVerifyRow(table_name, "row1", row1_valid_single_cell), CELL_NOT_FOUND_ERR); + + EXPECT_EQ(getVerifyRow(table_name, "row2", row2_valid_single_cell), 0); + EXPECT_EQ(deleteRow(table_name, "row2", row2_valid_single_cell), 0); + EXPECT_EQ(getVerifyRow(table_name, "row2", row2_valid_single_cell), CELL_NOT_FOUND_ERR); +} + +TEST_F(HBaseCAPI, delete_multicell_test_async) { + std::string line; + std::vector words; + std::string table_name = "test_table"; + + HBASE_LOG_INFO("*** hbase table delete multiple cells test ***"); + std::vector columnFamilies { "testcf1", "testcf2" }; + std::vector row1_data { "testcf1:col1:4", "testcf1:col5:3", "testcf2:col1:6" }; + std::vector row2_data { "testcf1:col1:4", "testcf1:col2:3", "testcf2:col1:6" }; + std::vector row3_data { "testcf1:col1:8", "testcf1:col2:9", "testcf1:col6:19", + "testcf2:col1:10", "testcf2:col2:9" }; + HBASE_LOG_INFO("creating table:%s", table_name.c_str()); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ(createTable((char*)table_name.c_str(), columnFamilies), 0); + ASSERT_EQ(putRow(table_name, "row1", row1_data), 0); + ASSERT_EQ(putRow(table_name, "row2", row2_data), 0); + ASSERT_EQ(putRow(table_name, "row3", row3_data), 0); + HBASE_LOG_INFO("wait for puts.."); + ASSERT_TRUE(waitForPutsToComplete()); + HBASE_LOG_INFO("wait for puts completed"); + + std::vector row1_valid_multi_cell { "testcf1:col1", "testcf2:col1" }; + std::vector row1_valid_multi_cell_1 { "testcf1:col1" }; + std::vector row1_valid_multi_cell_2 { "testcf2:col1" }; + + EXPECT_EQ(getVerifyRow(table_name, "row1", row1_valid_multi_cell), 0); + EXPECT_EQ(deleteRow(table_name, "row1", row1_valid_multi_cell), 0); + EXPECT_EQ(getVerifyRow(table_name, "row1", row1_valid_multi_cell), CELL_NOT_FOUND_ERR); + EXPECT_EQ(getVerifyRow(table_name, "row1", row1_valid_multi_cell_1), CELL_NOT_FOUND_ERR); + EXPECT_EQ(getVerifyRow(table_name, "row1", row1_valid_multi_cell_2), CELL_NOT_FOUND_ERR); +} + +TEST_F(HBaseCAPI, delete_entire_cf_test_async) { + std::string table_name = "test_table"; + + HBASE_LOG_INFO("*** hbase table delete entire cf test ***"); + std::vector columnFamilies { "testcf1", "testcf2" }; + std::vector row1_data { "testcf1:col1:4", "testcf1:col5:3", "testcf2:col1:6" }; + std::vector row2_data { "testcf1:col1:4", "testcf1:col2:3", "testcf2:col1:6" }; + std::vector row3_data { "testcf1:col1:8", "testcf1:col2:9", "testcf1:col6:19", + "testcf2:col1:10", "testcf2:col2:9" }; + + HBASE_LOG_INFO("creating table:%s", table_name.c_str()); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ(createTable((char*)table_name.c_str(), columnFamilies), 0); + ASSERT_EQ(putRow(table_name, "row1", row1_data), 0); + ASSERT_EQ(putRow(table_name, "row2", row2_data), 0); + ASSERT_EQ(putRow(table_name, "row3", row3_data), 0); + HBASE_LOG_INFO("wait for puts.."); + ASSERT_TRUE(waitForPutsToComplete()); + HBASE_LOG_INFO("wait for puts completed"); + + std::vector row1_valid_CF { "testcf1" }; + std::vector row1_valid_CF_cells { "testcf1:col1:4", "testcf1:col5:3" }; + std::vector row1_valid_CF_cells_1 { "testcf1:col1:4" }; + std::vector row1_valid_CF_cells_2 { "testcf1:col5:3" }; + + EXPECT_EQ(getVerifyRow(table_name, "row1", row1_valid_CF_cells), 0); + EXPECT_EQ(deleteRow(table_name, "row1", row1_valid_CF), 0); + + // now verify the cells of the row of one column family which is deleted in previous operation + EXPECT_EQ(getVerifyRow(table_name, "row1", row1_valid_CF_cells), CELL_NOT_FOUND_ERR); +} + +TEST_F(HBaseCAPI, delete_entire_row_test_async) { + std::string table_name = "test_table"; + + HBASE_LOG_INFO("*** hbase table delete entire row test ***"); + std::vector columnFamilies { "testcf1", "testcf2" }; + std::vector row1_data { "testcf1:col1:4", "testcf1:col5:3", "testcf2:col1:6" }; + std::vector row2_data { "testcf1:col1:4", "testcf1:col2:3", "testcf2:col1:6" }; + std::vector row3_data { "testcf1:col1:8", "testcf1:col2:9", "testcf1:col6:19", + "testcf2:col1:10", "testcf2:col2:9" }; + HBASE_LOG_INFO("creating table:%s", table_name.c_str()); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ(createTable((char*)table_name.c_str(), columnFamilies), 0); + ASSERT_EQ(putRow(table_name, "row1", row1_data), 0); + ASSERT_EQ(putRow(table_name, "row2", row2_data), 0); + ASSERT_EQ(putRow(table_name, "row3", row3_data), 0); + HBASE_LOG_INFO("wait for puts.."); + ASSERT_TRUE(waitForPutsToComplete()); + HBASE_LOG_INFO("wait for puts completed"); + + std::vector delete_entire_row { "" }; + std::vector row1_valid_cells_1 { "testcf1:col1:4" }; + std::vector row1_valid_cells_2 { "testcf1:col5:3" }; + std::vector row1_valid_cells_3 { "testcf2:col1" }; + + // before deleting + EXPECT_EQ(getVerifyRow(table_name, "row1", row1_data), 0); + // delete entire row + EXPECT_EQ(deleteRow(table_name, "row1", delete_entire_row), 0); + // verifying all the columns of entire row + EXPECT_EQ(getVerifyRow(table_name, "row1", row1_valid_cells_1), CELL_NOT_FOUND_ERR); + EXPECT_EQ(getVerifyRow(table_name, "row1", row1_valid_cells_2), CELL_NOT_FOUND_ERR); + EXPECT_EQ(getVerifyRow(table_name, "row1", row1_valid_cells_3), CELL_NOT_FOUND_ERR); +} + +TEST_F(HBaseCAPI, delete_nonexisting_row_test_async) { + std::string table_name = "del_nerow_t1"; + + HBASE_LOG_INFO("*** hbase table delete non existing row test ***"); + std::vector columnFamilies { "testcf1", "testcf2" }; + std::vector row1_data { "testcf1:col1:4", "testcf1:col5:3", "testcf2:col1:6" }; + std::vector row2_data { "testcf1:col1:4", "testcf1:col2:3", "testcf2:col1:6" }; + std::vector row3_data { "testcf1:col1:8", "testcf1:col2:9", "testcf1:col6:19", + "testcf2:col1:10", "testcf2:col2:9" }; + HBASE_LOG_INFO("creating table:%s", table_name.c_str()); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ(createTable((char*)table_name.c_str(), columnFamilies), 0); + ASSERT_EQ(putRow(table_name, "row1", row1_data), 0); + ASSERT_EQ(putRow(table_name, "row2", row2_data), 0); + ASSERT_EQ(putRow(table_name, "row3", row3_data), 0); + HBASE_LOG_INFO("wait for puts.."); + ASSERT_TRUE(waitForPutsToComplete()); + HBASE_LOG_INFO("wait for puts completed"); + + // make sure row not exists + EXPECT_EQ(getVerifyRow(table_name, "nonexistingrow", row1_data), CELL_NOT_FOUND_ERR); + + // try deleting non existing row - hbase returns zero for non existing row + EXPECT_EQ(deleteRow(table_name, "nonexistingrow", row1_data), 0); +} + +TEST_F(HBaseCAPI, delete_get_non_existing_cf_test_async) { + std::string table_name = "test_table"; + + HBASE_LOG_INFO("*** hbase table delete and get for non existing cf test ***"); + std::vector columnFamilies { "testcf1", "testcf2" }; + std::vector row1_data { "testcf1:col1:4", "testcf1:col5:3", "testcf2:col1:6" }; + std::vector row2_data { "testcf1:col1:4", "testcf1:col2:3", "testcf2:col1:6" }; + std::vector row3_data { "testcf1:col1:8", "testcf1:col2:9", "testcf1:col6:19", + "testcf2:col1:10", "testcf2:col2:9" }; + HBASE_LOG_INFO("creating table:%s", table_name.c_str()); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ(createTable((char*)table_name.c_str(), columnFamilies), 0); + // putting the data + ASSERT_EQ(putRow(table_name, "row1", row1_data), 0); + ASSERT_EQ(putRow(table_name, "row2", row2_data), 0); + ASSERT_EQ(putRow(table_name, "row3", row3_data), 0); + HBASE_LOG_INFO("wait for puts.."); + ASSERT_TRUE(waitForPutsToComplete()); + HBASE_LOG_INFO("wait for puts completed"); + + std::vector row1_non_existing_cf { "none:col1" }; + + // non existing cf should give 2 error for both delete and get + + EXPECT_EQ(getVerifyRow(table_name, "row1", row1_non_existing_cf), 2); + EXPECT_EQ(deleteRow(table_name, "row1", row1_non_existing_cf), 2); +} + +TEST_F(HBaseCAPI, delete_test_ts_async) { + std::string table_name = "test_table"; + + HBASE_LOG_INFO("*** hbase table delete with time stamp test ***"); + std::vector columnFamilies { "testcf1", "testcf2" }; + std::vector row2_data_ts { "testcf1:col1:4000", + "testcf1:col2:3000", "testcf2:col1:6000" }; + std::vector row2_data { "testcf1:col1:4", "testcf1:col2:3", "testcf2:col1:6" }; + + HBASE_LOG_INFO("creating table:%s", table_name.c_str()); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ(createTable((char*)table_name.c_str(), columnFamilies), 0); + + // putting the row with ts ->1000 + ASSERT_EQ(putRowAndWait(table_name, "row2", row2_data_ts, 1000), 0); + + // putting the row with latest time stamp for same cells but different values + ASSERT_EQ(putRowAndWait(table_name, "row2", row2_data), 0); + + std::vector row1_data_cell1 { "testcf1:col6:3" }; + std::vector row1_data_cell2 { "testcf1:col1:3" }; + std::vector row2_data_cell3 { "testcf1:col1:4" }; + std::vector cf1 { "testcf1" }; + std::vector empty { "" }; + + // total number of cells 3 with two diffeent ts -> expected cell count 6 + expectedNumberOfCellCount = 6; + EXPECT_EQ(getVerifyRow(table_name, "row2", row2_data), 0); + + // delete the row with ts->2000 so that ts with 1000 will be deleted + EXPECT_EQ(deleteRow(table_name, "row2", row2_data, 2000), 0); + // MAPR-13104 + // still it should keep the values with latest time stamp, + expectedNumberOfCellCount = 3; + EXPECT_EQ(getVerifyRow(table_name, "row2", row2_data), 0); + expectedNumberOfCellCount = 0; +} + +TEST_F(HBaseCAPI, scan_table_async) { + std::string table_name = "scan_table"; + + HBASE_LOG_INFO("*** table scan ***"); + std::vector columnFamilies { "testcf1", "testcf2" }; + std::vector row_data { "testcf1:col1:4", "testcf1:col2:3", "testcf2:col1:6" }; + + HBASE_LOG_INFO("creating table:%s", table_name.c_str()); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ(createTable((char*)table_name.c_str(), columnFamilies), 0); + // put 1000 records + for (int i = 0; i < 1000; i++) { + char row_key[20] = ""; + sprintf((char*) row_key, "%s_%d", "user", i); + std::string rowKey(row_key); + ASSERT_EQ(putRow(table_name, rowKey, row_data), 0); + } + + HBASE_LOG_INFO("wait for puts.."); + waitForPutsToComplete(); + HBASE_LOG_INFO("wait for puts completed"); + + expectedNumberOfRowCount = 1000; + expectedNumberOfCellCount = 3000; + HBASE_LOG_INFO("scan table expected no of rows:%lu expected no of cells:%lu", + expectedNumberOfRowCount, expectedNumberOfCellCount); + EXPECT_EQ(scanTable(table_name), 0); + expectedNumberOfRowCount = 0; //reset + EXPECT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); +} + +TEST_F(HBaseCAPI, scan_table_with_non_existing_table) { + std::string table_name = "scan_table"; + + HBASE_LOG_INFO("*** table scan with non existing table***"); + std::vector columnFamilies { "testcf1", "testcf2" }; + + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + expectedNumberOfRowCount = 0; + expectedNumberOfCellCount = 0; + HBASE_LOG_INFO("scan table for non existing table with expected no of rows:", + expectedNumberOfRowCount, " expected no of cells", expectedNumberOfCellCount); + EXPECT_EQ(scanTable(table_name), 2); +} + +TEST_F(HBaseCAPI, scan_empty_table_async) { + std::string table_name = "scan_table"; + + HBASE_LOG_INFO("*** table scan for empty table ***"); + std::vector columnFamilies { "testcf1", "testcf2" }; + + HBASE_LOG_INFO("creating table:%s", table_name.c_str()); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ(createTable((char*)table_name.c_str(), columnFamilies), 0); + + expectedNumberOfRowCount = 0; + expectedNumberOfCellCount = 0; + HBASE_LOG_INFO("scan table for empty table with expected no of rows:%ld", + expectedNumberOfRowCount); + EXPECT_EQ(scanTable(table_name), 0); +} + +TEST_F(HBaseCAPI, scan_table_with_versions) { + std::string table_name = "scan_table_with_verions"; + + HBASE_LOG_INFO("*** table scan with versions **"); + std::vector columnFamilies { "testcf1", "testcf2" }; + std::vector row_data { "testcf1:col1:4", "testcf1:col2:3", "testcf2:col1:6" }; + + HBASE_LOG_INFO("creating table:%s", table_name.c_str()); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ(createTable((char*)table_name.c_str(), columnFamilies), 0); + // put 1000 records 3 times so that 3 versions will be created + for (int k = 0; k < 3; k++) { + for (int i = 0; i < 1000; i++) { + char row_key[20] = ""; + sprintf((char*) row_key, "%s_%d", "user", i); + std::string rowKey(row_key); + ASSERT_EQ(putRow(table_name, rowKey, row_data), 0); + } + } + HBASE_LOG_INFO("wait for puts.."); + waitForPutsToComplete(); + HBASE_LOG_INFO("wait for puts completed"); + + expectedNumberOfRowCount = 1000; + expectedNumberOfCellCount = 9000; + HBASE_LOG_INFO("scan table with verions:3 with expected no of rows:%lu" + "expected Number of Cells:%lu", expectedNumberOfRowCount, expectedNumberOfCellCount); + EXPECT_EQ(scanTable(table_name, 3/*versions*/), 0); + + expectedNumberOfRowCount = 1000; + expectedNumberOfCellCount = 6000; + HBASE_LOG_INFO("scan table with verions:2 with expected no of rows:%lu" + "expected Number of Cells:%lu", expectedNumberOfRowCount, expectedNumberOfCellCount); + + EXPECT_EQ(scanTable(table_name, 2/*versions*/), 0); + + expectedNumberOfRowCount = 1000; + expectedNumberOfCellCount = 3000; + HBASE_LOG_INFO("scan table with verions:1 with expected no of rows:%lu" + " expected Number of Cells:%lu", expectedNumberOfRowCount, expectedNumberOfCellCount); + + EXPECT_EQ(scanTable(table_name, 1/*versions*/), 0); + expectedNumberOfRowCount = 0; //reset + expectedNumberOfCellCount = 0; +} + +TEST_F(HBaseCAPI, scan_table_with_max_num_rows) { + std::string table_name = "scan_table_num_rows"; + + HBASE_LOG_INFO("*** table scan max number of rows **"); + std::vector columnFamilies { "testcf1", "testcf2" }; + std::vector row_data { "testcf1:col1:4", "testcf1:col2:3", "testcf2:col1:6" }; + + HBASE_LOG_INFO("creating table:%s", table_name.c_str()); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ(createTable((char*)table_name.c_str(), columnFamilies), 0); + for (int i = 0; i < 1000; i++) { + char row_key[20] = ""; + sprintf((char*) row_key, "%s_%d", "user", i); + std::string rowKey(row_key); + ASSERT_EQ(putRow(table_name, rowKey, row_data), 0); + } + HBASE_LOG_INFO("wait for puts.."); + waitForPutsToComplete(); + HBASE_LOG_INFO("wait for puts completed"); + + expectedNumberOfRowCount = 1000; + maxNumberOfRows = 1000; + HBASE_LOG_INFO("scan table with verions:3 maxnorows:%lu with expected no of row:%lu", + maxNumberOfRows, expectedNumberOfRowCount); + EXPECT_EQ(scanTable(table_name, 1/*versions*/, maxNumberOfRows), 0); + + expectedNumberOfRowCount = 1000; + maxNumberOfRows = 50; + HBASE_LOG_INFO("scan table with verions:3 maxnorows:%lu with expected no of row:%lu", + maxNumberOfRows, expectedNumberOfRowCount); + EXPECT_EQ(scanTable(table_name, 3/*versions*/, maxNumberOfRows), 0); + + expectedNumberOfRowCount = 1000; + maxNumberOfRows = 10000; + HBASE_LOG_INFO("scan table with verions:3 maxnorows:%lu with expected no of row:%lu", + maxNumberOfRows, expectedNumberOfRowCount); + EXPECT_EQ(scanTable(table_name, 3/*versions*/, maxNumberOfRows), 0); + + maxNumberOfRows = 0; //reset +} + +TEST_F(HBaseCAPI, scan_table_with_row_start_key) { + std::string table_name = "scan_table"; + std::string start_key = ""; + + HBASE_LOG_INFO("*** table scan with specified start row key ***"); + std::vector columnFamilies { "testcf1", "testcf2" }; + + std::vector row_data { "testcf1:col1:4", "testcf1:col2:3", "testcf2:col1:6" }; + + HBASE_LOG_INFO("creating table:%s", table_name.c_str()); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ(createTable((char*)table_name.c_str(), columnFamilies), 0); + // put 1000 records + for (int i = 0; i < 1000; i++) { + char row_key[20] = ""; + sprintf((char*) row_key, "%s_%d", "user", i); + std::string rowKey(row_key); + ASSERT_EQ(putRow(table_name, rowKey, row_data), 0); + } + HBASE_LOG_INFO("wait for puts.."); + waitForPutsToComplete(); + HBASE_LOG_INFO("wait for puts completed"); + + start_key = "user_499"; + expectedNumberOfRowCount = 556; + HBASE_LOG_INFO(" scan table with start key:%s expected rows:%lu", start_key.c_str(), + expectedNumberOfRowCount); + EXPECT_EQ(scanTable(table_name, 1, 10000, start_key), 0); + + start_key = "user_0"; + expectedNumberOfRowCount = 1000; + HBASE_LOG_INFO(" scan table with start key:%s expected rows:%lu", start_key.c_str(), + expectedNumberOfRowCount); + EXPECT_EQ(scanTable(table_name, 1, 10000, start_key), 0); + + start_key = "user_999"; + expectedNumberOfRowCount = 1; + HBASE_LOG_INFO(" scan table with start key:%s expected rows:%lu", start_key.c_str(), + expectedNumberOfRowCount); + EXPECT_EQ(scanTable(table_name, 1, 10000, start_key), 0); + + EXPECT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); +} + +TEST_F(HBaseCAPI, scan_table_with_invalid_start_key) { + std::string table_name = "scan_table"; + std::string start_key = ""; + + HBASE_LOG_INFO("*** table scan with invalid start row key ***"); + std::vector columnFamilies { "testcf1", "testcf2" }; + std::vector row_data { + "testcf1:col1:4", "testcf1:col2:3", "testcf2:col1:6" }; + + HBASE_LOG_INFO("creating table:%s", table_name.c_str()); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ(createTable((char*)table_name.c_str(), columnFamilies), 0); + // put 1000 records + for (int i = 0; i < 1000; i++) { + char row_key[20] = ""; + sprintf((char*) row_key, "%s_%d", "user", i); + std::string rowKey(row_key); + ASSERT_EQ(putRow(table_name, rowKey, row_data), 0); + } + HBASE_LOG_INFO("wait for puts.."); + waitForPutsToComplete(); + HBASE_LOG_INFO("wait for puts completed"); + + start_key = "user_99999"; + expectedNumberOfRowCount = 0; + HBASE_LOG_INFO(" scan table with start key:%s expected rows:%lu", + start_key.c_str(), expectedNumberOfRowCount); + EXPECT_EQ(scanTable(table_name, 1, 10000, start_key), 0); +} + +TEST_F(HBaseCAPI, scan_table_with_start_end_key) { + std::string table_name = "scan_table"; + std::string start_key = ""; + std::string end_key = ""; + + HBASE_LOG_INFO("*** table scan with start and end row key ***"); + std::vector columnFamilies { "testcf1", "testcf2" }; + std::vector row_data { + "testcf1:col1:4", "testcf1:col2:3", "testcf2:col1:6" }; + + HBASE_LOG_INFO("creating table:", table_name.c_str()); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ(createTable((char*)table_name.c_str(), columnFamilies), 0); + // put 1000 records + for (int i = 0; i < 1000; i++) { + char row_key[20] = ""; + sprintf((char*) row_key, "%s_%d", "user", i); + std::string rowKey(row_key); + ASSERT_EQ(putRow(table_name, rowKey, row_data), 0); + } + HBASE_LOG_INFO("wait for puts.."); + waitForPutsToComplete(); + HBASE_LOG_INFO("wait for puts completed"); + + expectedNumberOfRowCount = 999; + start_key = "user_0"; + end_key = "user_999"; //exclusive + HBASE_LOG_INFO(" scan table with start key:%s endkey:%s expected rows:%lu", + start_key.c_str(), end_key.c_str(), expectedNumberOfRowCount); + EXPECT_EQ(scanTable(table_name, 1, 10000, start_key, end_key), 0); + expectedNumberOfCellCount = 0; //reset + + expectedNumberOfRowCount = 552; + start_key = "user_500"; + end_key = "user_999"; + HBASE_LOG_INFO(" scan table with start key:%s endkey:%s expected rows:%lu", + start_key.c_str(), end_key.c_str(), expectedNumberOfRowCount); + EXPECT_EQ(scanTable(table_name, 1, 10000, start_key, end_key), 0); + + expectedNumberOfRowCount = 0; //reset + EXPECT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); +} + +TEST_F(HBaseCAPI, scan_table_with_invalid_start_end_key) { + std::string table_name = "scan_table"; + std::string start_key = ""; + std::string end_key = ""; + + HBASE_LOG_INFO("*** table scan with start and end row key ***"); + std::vector columnFamilies { "testcf1", "testcf2" }; + std::vector row_data { + "testcf1:col1:4", "testcf1:col2:3", "testcf2:col1:6" }; + + HBASE_LOG_INFO("creating table:", table_name.c_str()); + ASSERT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); + ASSERT_EQ(createTable((char*)table_name.c_str(), columnFamilies), 0); + // put 1000 records + for (int i = 0; i < 1000; i++) { + char row_key[20] = ""; + sprintf((char*) row_key, "%s_%d", "user", i); + std::string rowKey(row_key); + ASSERT_EQ(putRow(table_name, rowKey, row_data), 0); + } + HBASE_LOG_INFO("wait for puts.."); + waitForPutsToComplete(); + HBASE_LOG_INFO("wait for puts completed"); + + // end key is less than start key + expectedNumberOfRowCount = 0; + + start_key = "user_995"; + end_key = "user_0"; + HBASE_LOG_INFO(" scan table with start key:%s endkey:%s expected rows:%lu", + start_key.c_str(), end_key.c_str(), expectedNumberOfRowCount); + EXPECT_EQ(scanTable(table_name, 1, 10000, start_key, end_key), 0); + expectedNumberOfCellCount = 0; //reset + + // valid start key invalid end key + expectedNumberOfRowCount = 0; + start_key = "user_500"; + end_key = "user_1999"; + HBASE_LOG_INFO(" scan table with start key:%s endkey:%s expected rows:%lu", + start_key.c_str(), end_key.c_str(), expectedNumberOfRowCount); + EXPECT_EQ(scanTable(table_name, 1, 10000, start_key, end_key), 0); + + // with invalid start key valid end key + expectedNumberOfRowCount = 0; + start_key = "user_aaa"; + end_key = "user_999"; + HBASE_LOG_INFO(" scan table with start key:%s endkey:%s expected rows:%lu", + start_key.c_str(), end_key.c_str(), expectedNumberOfRowCount); + EXPECT_EQ(scanTable(table_name, 1, 10000, start_key, end_key), 0); + + EXPECT_EQ(deleteTableIfExists((char*)table_name.c_str()), 0); +} + +/** + * Test entry point. + */ +extern "C" int +main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + +} /* namespace test */ +} /* namespace hbase */ diff --git a/hbase-native-client/src/test/resources/config.properties b/hbase-native-client/src/test/resources/config.properties new file mode 100644 index 000000000000..eeba82e9ffbc --- /dev/null +++ b/hbase-native-client/src/test/resources/config.properties @@ -0,0 +1,21 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#################################################### +### zookeeper quorum and root nodes for libhbase ### +#################################################### +LIBHBASE_ZK_QUORUM=localhost:2181 +LIBHBASE_ZK_ROOT_NODE=/hbase +LIBHBASE_LOG_FILE=target/test-logs/unittests_native.log diff --git a/hbase-native-client/src/test/resources/table_create.dat b/hbase-native-client/src/test/resources/table_create.dat new file mode 100644 index 000000000000..86d8ab08b545 --- /dev/null +++ b/hbase-native-client/src/test/resources/table_create.dat @@ -0,0 +1,2 @@ +table_create_test_2_cfs,cf1,cf2 +table_create_test_10_cfs,cf1,cf2,cf3,cf4,cf5,cf6,cf7,cf8,cf9,cf10 diff --git a/hbase-native-client/src/test/resources/table_put.dat b/hbase-native-client/src/test/resources/table_put.dat new file mode 100644 index 000000000000..96b6e1adce5e --- /dev/null +++ b/hbase-native-client/src/test/resources/table_put.dat @@ -0,0 +1,7 @@ +#first row is for table name and cfs second row are inputs for one put operation. time stamp is optional for column +#all lines starts with '#' are comments - application skip those lines +test_table,cf1,cf2,cf3,cf4,cf5 +row1,cf1:col1:4,cf4:col4:5 +row1,cf5:col1:4,cf4:col4:5 +row3,cf1:col1:4,cf4:col4:5 +row4,cf1:col1:4,cf4:col4:5 diff --git a/pom.xml b/pom.xml index 6b7b65e0821e..c1f687561ea8 100644 --- a/pom.xml +++ b/pom.xml @@ -695,6 +695,7 @@ .svn/** **/.settings/** **/patchprocess/** + **/.gradle/** @@ -1467,6 +1468,15 @@ Mac_OS_X-${sun.arch.data.model} + + hbase-native-client + + false + + + hbase-native-client + + os.windows