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..7f449eb 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,11 @@ 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()) { + runner.Run(FLAGS_monkey, FLAGS_table); + } + auto num_puts = FLAGS_num_rows; auto client = std::make_unique(*conf); @@ -386,5 +393,6 @@ int main(int argc, char *argv[]) { } client->Close(); + runner.Stop(); return succeeded.load() ? 0 : -1; } 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 56461e1..ab56929 100644 --- a/hbase-native-client/test-util/mini-cluster.cc +++ b/hbase-native-client/test-util/mini-cluster.cc @@ -65,13 +65,14 @@ JNIEnv *MiniCluster::CreateVM(JavaVM **jvm) { args.options = &jvm_options; args.ignoreUnrecognized = 0; int rv; - rv = JNI_CreateJavaVM(jvm, reinterpret_cast(&env_), &args); - if (rv < 0 || !env_) { + JNIEnv *env; + rv = JNI_CreateJavaVM(jvm, reinterpret_cast(&env), &args); + if (rv < 0 || !env) { LOG(INFO) << "Unable to Launch JVM " << rv; } else { LOG(INFO) << "Launched JVM! " << options; } - return env_; + return env; } void MiniCluster::Setup() { @@ -185,14 +186,14 @@ 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.size() == 0) { return nullptr; } char *p = const_cast(str.c_str()); 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; } @@ -214,7 +215,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); @@ -238,14 +239,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, @@ -274,7 +275,7 @@ 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 b8ac391..cfafa81 100644 --- a/hbase-native-client/test-util/mini-cluster.h +++ b/hbase-native-client/test-util/mini-cluster.h @@ -42,6 +42,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_; @@ -70,11 +72,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..c7cdf9e --- /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); + void Stop(); + + private: + JNIEnv *env_; + JavaVM *jvm_; + jclass runner_class_; + std::vector monkey_runners_; + 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..736fd02 --- /dev/null +++ b/hbase-native-client/test-util/monkey-runner.cc @@ -0,0 +1,65 @@ +/* + * 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() { env_ = MiniCluster::CreateVM(&jvm_); } + +void MonkeyRunner::Run(std::string monkey, std::string tablename) { + 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(4, str_class, nullptr); + env_->SetObjectArrayElement(args, 0, MiniCluster::StrToByteChar(env_, "-m")); + env_->SetObjectArrayElement(args, 1, MiniCluster::StrToByteChar(env_, monkey)); + env_->SetObjectArrayElement(args, 2, MiniCluster::StrToByteChar(env_, "--tableName")); + env_->SetObjectArrayElement(args, 3, MiniCluster::StrToByteChar(env_, tablename)); + + monkey_runners_.push_back( + std::thread([&] { env_->CallStaticObjectMethod(runner_class_, runner_method, args); })); +} + +void MonkeyRunner::Stop() { + if (stop_method_ != NULL) { + env_->CallStaticObjectMethod(runner_class_, stop_method_); + } +} +MonkeyRunner::~MonkeyRunner() { + if (jvm_ != NULL) { + jvm_->DestroyJavaVM(); + jvm_ = NULL; + } +}