diff --git a/hbase-native-client/core/BUCK b/hbase-native-client/core/BUCK index 76c836b..577d649 100644 --- a/hbase-native-client/core/BUCK +++ b/hbase-native-client/core/BUCK @@ -345,4 +345,8 @@ cxx_binary( srcs=[ "load-client.cc", ], - deps=[":core", "//connection:connection"],) + deps=[ + ":core", + "//connection:connection", + "//test-util:test-util", + ]) diff --git a/hbase-native-client/core/load-client.cc b/hbase-native-client/core/load-client.cc index 8cceeef..4cd98e3 100644 --- a/hbase-native-client/core/load-client.cc +++ b/hbase-native-client/core/load-client.cc @@ -31,6 +31,7 @@ #include "core/put.h" #include "core/table.h" #include "serde/table-name.h" +#include "test-util/monkey-runner.h" #include "utils/time-util.h" using hbase::Client; @@ -56,6 +57,7 @@ DEFINE_bool(gets, true, "perform gets"); DEFINE_bool(scans, true, "perform scans"); DEFINE_bool(puts, true, "perform put's"); DEFINE_bool(appends, true, "perform append's"); +DEFINE_string(monkey, "", "activate designated chaos monkey, such as slowDeterministic"); static constexpr const char *kNumColumn = "num"; static constexpr const char *incrPrefix = "i"; @@ -296,6 +298,16 @@ int main(int argc, char *argv[]) { conf = std::make_shared(loader.LoadDefaultResources().value()); } auto tn = std::make_shared(folly::to(FLAGS_table)); + hbase::MonkeyRunner runner; + if (!FLAGS_monkey.empty()) { + if (FLAGS_conf == "") { + LOG(ERROR) + << "Must provide conf directory where hbase-site.xml points to distributed cluster"; + return -1; + } + runner.Run(FLAGS_monkey, FLAGS_table, FLAGS_conf); + } + auto num_puts = FLAGS_num_rows; auto client = std::make_unique(*conf); diff --git a/hbase-native-client/test-util/BUCK b/hbase-native-client/test-util/BUCK index 7c92841..52a6c51 100644 --- a/hbase-native-client/test-util/BUCK +++ b/hbase-native-client/test-util/BUCK @@ -18,8 +18,8 @@ import os cxx_library( name="test-util", - exported_headers=["test-util.h", "mini-cluster.h"], - srcs=["test-util.cc", "mini-cluster.cc"], + exported_headers=["test-util.h", "mini-cluster.h", "monkey-runner.h"], + srcs=["test-util.cc", "mini-cluster.cc", "monkey-runner.cc"], deps=[ "//third-party:folly", "//core:core", diff --git a/hbase-native-client/test-util/mini-cluster.cc b/hbase-native-client/test-util/mini-cluster.cc index 9dd2f12..a55a5c6 100644 --- a/hbase-native-client/test-util/mini-cluster.cc +++ b/hbase-native-client/test-util/mini-cluster.cc @@ -65,9 +65,10 @@ JNIEnv *MiniCluster::CreateVM(JavaVM **jvm) { args.options = &jvm_options; args.ignoreUnrecognized = 0; int rv; - rv = JNI_CreateJavaVM(jvm, reinterpret_cast(&env_), &args); - CHECK(rv >= 0 && env_); - return env_; + JNIEnv *env; + rv = JNI_CreateJavaVM(jvm, reinterpret_cast(&env), &args); + CHECK(rv >= 0 && env); + return env; } MiniCluster::~MiniCluster() { @@ -189,13 +190,13 @@ JNIEnv *MiniCluster::env() { return env_; } // converts C char* to Java byte[] -jbyteArray MiniCluster::StrToByteChar(const std::string &str) { +jbyteArray MiniCluster::StrToByteChar(JNIEnv *env, const std::string &str) { if (str.length() == 0) { return nullptr; } int n = str.length(); - jbyteArray arr = env_->NewByteArray(n); - env_->SetByteArrayRegion(arr, 0, n, reinterpret_cast(str.c_str())); + jbyteArray arr = env->NewByteArray(n); + env->SetByteArrayRegion(arr, 0, n, reinterpret_cast(str.c_str())); return arr; } @@ -217,7 +218,7 @@ jobject MiniCluster::CreateTable(const std::string &table, jobjectArray family_array = env_->NewObjectArray(families.size(), array_element_type, nullptr); int i = 0; for (auto family : families) { - env_->SetObjectArrayElement(family_array, i++, StrToByteChar(family)); + env_->SetObjectArrayElement(family_array, i++, StrToByteChar(env_, family)); } jobject table_obj = env_->CallObjectMethod(htu_, create_table_families_mid_, table_name, family_array); @@ -241,14 +242,14 @@ jobject MiniCluster::CreateTable(const std::string &table, const std::vectorNewObjectArray(families.size(), array_element_type, nullptr); for (auto family : families) { - env_->SetObjectArrayElement(family_array, i++, StrToByteChar(family)); + env_->SetObjectArrayElement(family_array, i++, StrToByteChar(env_, family)); } jobjectArray key_array = env_->NewObjectArray(keys.size(), array_element_type, nullptr); i = 0; for (auto key : keys) { - env_->SetObjectArrayElement(key_array, i++, StrToByteChar(key)); + env_->SetObjectArrayElement(key_array, i++, StrToByteChar(env_, key)); } jobject tbl = env_->CallObjectMethod(htu_, create_table_with_split_mid_, table_name, family_array, @@ -277,7 +278,8 @@ jobject MiniCluster::admin() { // moves region to server void MiniCluster::MoveRegion(const std::string ®ion, const std::string &server) { jobject admin_ = admin(); - env_->CallObjectMethod(admin_, move_mid_, StrToByteChar(region), StrToByteChar(server)); + env_->CallObjectMethod(admin_, move_mid_, StrToByteChar(env_, region), + StrToByteChar(env_, server)); } jobject MiniCluster::StartCluster(int num_region_servers) { diff --git a/hbase-native-client/test-util/mini-cluster.h b/hbase-native-client/test-util/mini-cluster.h index 6b4547c..d9ebd1d 100644 --- a/hbase-native-client/test-util/mini-cluster.h +++ b/hbase-native-client/test-util/mini-cluster.h @@ -43,6 +43,8 @@ class MiniCluster { jobject GetConf(); // returns the value for config key retrieved from cluster const std::string GetConfValue(const std::string &key); + static JNIEnv *CreateVM(JavaVM **jvm); + static jbyteArray StrToByteChar(JNIEnv *env, const std::string &str); private: JNIEnv *env_; @@ -71,11 +73,9 @@ class MiniCluster { jobject cluster_; pthread_mutex_t count_mutex_; JavaVM *jvm_; - JNIEnv *CreateVM(JavaVM **jvm); void Setup(); jobject htu(); JNIEnv *env(); - jbyteArray StrToByteChar(const std::string &str); jobject admin(); }; } /*namespace hbase*/ diff --git a/hbase-native-client/test-util/monkey-runner.h b/hbase-native-client/test-util/monkey-runner.h new file mode 100644 index 0000000..c66d1c4 --- /dev/null +++ b/hbase-native-client/test-util/monkey-runner.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. + * + */ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "test-util/mini-cluster.h" + +namespace hbase { + +class MonkeyRunner { + public: + MonkeyRunner(); + ~MonkeyRunner(); + void Run(std::string monkey, std::string tablename, std::string confdir); + void Stop(); + + private: + JNIEnv *env_; + JavaVM *jvm_; + jclass runner_class_; + std::thread monkey_runner_; + jmethodID stop_method_; +}; +} /*namespace hbase*/ diff --git a/hbase-native-client/test-util/monkey-runner.cc b/hbase-native-client/test-util/monkey-runner.cc new file mode 100644 index 0000000..fa5023c --- /dev/null +++ b/hbase-native-client/test-util/monkey-runner.cc @@ -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. + * + */ + +#include "test-util/monkey-runner.h" +#include +#include +#include +#include +#include + +using hbase::MonkeyRunner; + +MonkeyRunner::MonkeyRunner() {} + +void MonkeyRunner::Run(std::string monkey, std::string tablename, std::string confdir) { + monkey_runner_ = std::thread([&] { + env_ = MiniCluster::CreateVM(&jvm_); + runner_class_ = env_->FindClass("org/apache/hadoop/hbase/chaos/util/ChaosMonkeyRunner"); + if (runner_class_ == NULL) { + LOG(ERROR) << "Couldn't find class ChaosMonkeyRunner"; + exit(-1); + } + jmethodID runner_method = + env_->GetStaticMethodID(runner_class_, "main", "([Ljava/lang/String;)V"); + if (runner_method == NULL) { + LOG(ERROR) << "Couldn't find main for ChaosMonkeyRunner"; + exit(-1); + } + stop_method_ = env_->GetStaticMethodID(runner_class_, "stopRunner", "()V"); + + jclass str_class = env_->FindClass("java/lang/String"); + jobjectArray args = env_->NewObjectArray(6, str_class, nullptr); + env_->SetObjectArrayElement(args, 0, env_->NewStringUTF("-c")); + env_->SetObjectArrayElement(args, 1, env_->NewStringUTF((confdir + "/hbase-site.xml").c_str())); + env_->SetObjectArrayElement(args, 2, env_->NewStringUTF("-m")); + env_->SetObjectArrayElement(args, 3, env_->NewStringUTF(monkey.c_str())); + env_->SetObjectArrayElement(args, 4, env_->NewStringUTF("--tableName")); + env_->SetObjectArrayElement(args, 5, env_->NewStringUTF(tablename.c_str())); + + env_->CallStaticObjectMethod(runner_class_, runner_method, args); + }); +} + +void MonkeyRunner::Stop() { + if (stop_method_ != NULL) { + env_->CallStaticObjectMethod(runner_class_, stop_method_); + } +} +MonkeyRunner::~MonkeyRunner() { +}