diff --git hbase-native-client/core/BUCK hbase-native-client/core/BUCK index 95fb8b5..e40236f 100644 --- hbase-native-client/core/BUCK +++ hbase-native-client/core/BUCK @@ -21,7 +21,7 @@ cxx_library( exported_headers=[ "client.h", "cell.h", - "hbase_macros.h", + "hbase-macros.h", "filter.h", "query.h", "keyvalue-codec.h", @@ -32,13 +32,13 @@ cxx_library( # Once meta lookup works "meta-utils.h", "get.h", - "time_range.h", + "time-range.h", "configuration.h", - "hbase_configuration_loader.h", + "hbase-configuration-loader.h", "scan.h", "result.h", - "request_converter.h", - "response_converter.h", + "request-converter.h", + "response-converter.h", "table.h", "async-rpc-retrying-caller-factory.h", "async-rpc-retrying-caller.h", @@ -51,13 +51,13 @@ cxx_library( "location-cache.cc", "meta-utils.cc", "get.cc", - "time_range.cc", + "time-range.cc", "configuration.cc", - "hbase_configuration_loader.cc", + "hbase-configuration-loader.cc", "scan.cc", "result.cc", - "request_converter.cc", - "response_converter.cc", + "request-converter.cc", + "response-converter.cc", "table.cc", ], deps=[ @@ -120,8 +120,8 @@ cxx_test( ], run_test_separately=True,) cxx_test( - name="time_range-test", - srcs=["time_range-test.cc",], + name="time-range-test", + srcs=["time-range-test.cc",], deps=[":core",], run_test_separately=True,) cxx_test( @@ -130,8 +130,8 @@ cxx_test( deps=[":core",], run_test_separately=True,) cxx_test( - name="hbase_configuration-test", - srcs=["hbase_configuration-test.cc",], + name="hbase-configuration-test", + srcs=["hbase-configuration-test.cc",], deps=[":core",], run_test_separately=True,) cxx_test( @@ -145,8 +145,8 @@ cxx_test( deps=[":core",], run_test_separately=True,) cxx_test( - name="request_converter-test", - srcs=["request_converter-test.cc",], + name="request-converter-test", + srcs=["request-converter-test.cc",], deps=[ ":core", "//connection:connection", diff --git hbase-native-client/core/async-rpc-retrying-test.cc hbase-native-client/core/async-rpc-retrying-test.cc index d2435b9..f2a79a1 100644 --- hbase-native-client/core/async-rpc-retrying-test.cc +++ hbase-native-client/core/async-rpc-retrying-test.cc @@ -36,8 +36,8 @@ #include "core/hbase-rpc-controller.h" #include "core/keyvalue-codec.h" #include "core/region-location.h" -#include "core/request_converter.h" -#include "core/response_converter.h" +#include "core/request-converter.h" +#include "core/response-converter.h" #include "core/result.h" #include "exceptions/exception.h" #include "if/Client.pb.h" diff --git hbase-native-client/core/client-test.cc hbase-native-client/core/client-test.cc index afca847..6f74e9c 100644 --- hbase-native-client/core/client-test.cc +++ hbase-native-client/core/client-test.cc @@ -21,7 +21,7 @@ #include #include "core/configuration.h" #include "core/get.h" -#include "core/hbase_configuration_loader.h" +#include "core/hbase-configuration-loader.h" #include "core/result.h" #include "core/table.h" #include "serde/table-name.h" diff --git hbase-native-client/core/client.h hbase-native-client/core/client.h index e73ab70..6e3c889 100644 --- hbase-native-client/core/client.h +++ hbase-native-client/core/client.h @@ -30,7 +30,7 @@ #include "connection/rpc-client.h" #include "core/configuration.h" #include "core/connection-configuration.h" -#include "core/hbase_configuration_loader.h" +#include "core/hbase-configuration-loader.h" #include "core/keyvalue-codec.h" #include "core/location-cache.h" #include "core/table.h" diff --git hbase-native-client/core/get.h hbase-native-client/core/get.h index 92d1fee..5492f21 100644 --- hbase-native-client/core/get.h +++ hbase-native-client/core/get.h @@ -25,7 +25,7 @@ #include #include #include "core/query.h" -#include "core/time_range.h" +#include "core/time-range.h" #include "if/Client.pb.h" namespace hbase { diff --git hbase-native-client/core/hbase-configuration-loader.cc hbase-native-client/core/hbase-configuration-loader.cc new file mode 100644 index 0000000..4d6a3e9 --- /dev/null +++ hbase-native-client/core/hbase-configuration-loader.cc @@ -0,0 +1,208 @@ +/* + * 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/hbase-configuration-loader.h" + +#include +#include +#include +#include + +namespace hbase { + +bool is_valid_bool(const std::string &raw) { + if (raw.empty()) { + return false; + } + + if (!strcasecmp(raw.c_str(), "true")) { + return true; + } + if (!strcasecmp(raw.c_str(), "false")) { + return true; + } + return false; +} + +bool str_to_bool(const std::string &raw) { + if (!strcasecmp(raw.c_str(), "true")) { + return true; + } + return false; +} + +HBaseConfigurationLoader::HBaseConfigurationLoader() {} + +HBaseConfigurationLoader::~HBaseConfigurationLoader() {} + +void HBaseConfigurationLoader::SetDefaultSearchPath() { + /* + * Try (in order, taking the first valid one): + * $HBASE_CONF_DIR + * /etc/hbase/conf + * + */ + const char *hadoop_conf_dir_env = getenv("HBASE_CONF"); + if (hadoop_conf_dir_env) { + AddToSearchPath(hadoop_conf_dir_env); + } else { + AddToSearchPath(kHBaseDefauktConfPath); + } +} + +void HBaseConfigurationLoader::ClearSearchPath() { search_paths_.clear(); } + +void HBaseConfigurationLoader::SetSearchPath(const std::string &search_path) { + search_paths_.clear(); + + std::vector paths; + std::string::size_type start = 0; + std::string::size_type end = search_path.find(kSearchPathSeparator); + + while (end != std::string::npos) { + paths.push_back(search_path.substr(start, end - start)); + start = ++end; + end = search_path.find(kSearchPathSeparator, start); + } + paths.push_back(search_path.substr(start, search_path.length())); + + for (auto path : paths) { + AddToSearchPath(path); + } +} + +void HBaseConfigurationLoader::AddToSearchPath(const std::string &search_path) { + if (search_path.empty()) return; + + std::string path_to_add(search_path); + if (search_path.back() != kFileSeparator) { + path_to_add += kFileSeparator; + } + if (std::find(search_paths_.begin(), search_paths_.end(), path_to_add) == search_paths_.end()) + search_paths_.push_back(path_to_add); +} + +void HBaseConfigurationLoader::AddDefaultResources() { + resources_.push_back(kHBaseDefaultXml); + resources_.push_back(kHBaseSiteXml); +} + +void HBaseConfigurationLoader::AddResources(const std::string &filename) { + if (std::find(resources_.begin(), resources_.end(), filename) == resources_.end()) + resources_.push_back(filename); +} + +optional HBaseConfigurationLoader::LoadDefaultResources() { + SetDefaultSearchPath(); + AddDefaultResources(); + ConfigMap conf_property; + bool success = false; + for (auto dir : search_paths_) { + for (auto file : resources_) { + std::string config_file = dir + file; + std::ifstream stream(config_file); + if (stream.is_open()) { + success |= LoadProperties(config_file, conf_property); + } else { + DLOG(WARNING) << "Unable to open file[" << config_file << "]"; + } + } + } + if (success) { + return std::experimental::make_optional(Configuration(conf_property)); + } else { + return optional(); + } +} + +optional HBaseConfigurationLoader::LoadResources( + const std::string &search_path, const std::vector &resources) { + SetSearchPath(search_path); + for (const auto &resource : resources) AddResources(resource); + ConfigMap conf_property; + bool success = false; + for (auto dir : search_paths_) { + for (auto file : resources_) { + std::string config_file = dir + file; + std::ifstream stream(config_file); + if (stream.is_open()) { + success |= LoadProperties(config_file, conf_property); + } else { + DLOG(WARNING) << "Unable to open file[" << config_file << "]"; + } + } + } + if (success) { + return std::experimental::make_optional(Configuration(conf_property)); + } else { + return optional(); + } +} + +bool HBaseConfigurationLoader::LoadProperties(const std::string &file, ConfigMap &property_map) { + // Create empty property tree object + using boost::property_tree::ptree; + ptree pt; + try { + // Load XML file and put contents in a property tree. + // If read fails, throw exception. + read_xml(file, pt); + + // If configuration key is not found exception is thrown + std::string configuration = pt.get("configuration"); + + // Iterate over configuration section. + // Store all found properties in ConfigMap + BOOST_FOREACH (ptree::value_type &v, pt.get_child("configuration")) { + if ("property" == v.first) { + std::string name_node = v.second.get("name"); + std::string value_node = v.second.get("value"); + if ((name_node.size() > 0) && (value_node.size() > 0)) { + boost::optional final_node = v.second.get_optional("final"); + UpdateMapWithValue(property_map, name_node, value_node, final_node); + } + } + } + } catch (std::exception &ex) { + DLOG(WARNING) << "Exception in parsing file [" << file << "]:[" << ex.what() << "]"; + return false; + } + return true; +} + +bool HBaseConfigurationLoader::UpdateMapWithValue(ConfigMap &map, const std::string &key, + const std::string &value, + boost::optional final_text) { + auto map_value = map.find(key); + if (map_value != map.end() && map_value->second.final) { + return false; + } + + bool final_value = false; + if (nullptr != final_text.get_ptr()) { + if (is_valid_bool(final_text.get())) { + final_value = str_to_bool(final_text.get()); + } + } + + map[key].value = value; + map[key].final = final_value; + return true; +} +} /* namespace hbase */ diff --git hbase-native-client/core/hbase-configuration-loader.h hbase-native-client/core/hbase-configuration-loader.h new file mode 100644 index 0000000..a1c1d3f --- /dev/null +++ hbase-native-client/core/hbase-configuration-loader.h @@ -0,0 +1,143 @@ +/* + * 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 "core/configuration.h" + +namespace hbase { + +template +using optional = std::experimental::optional; + +class HBaseConfigurationLoader { + public: + HBaseConfigurationLoader(); + ~HBaseConfigurationLoader(); + + /** + * @brief Creates a Configuration object based on default resources loaded + * from default search paths. Default search path will be either $HBASE_CONF + * is set or /etc/hbase/conf. Default resources are hbase-default.xml and + * hbase-site.xml.SetDefaultSearchPath() and AddDefaultResources() are used + * for the same. + * Values are loaded in from hbase-default.xml first and then from + * hbase-site.xml. + * Properties in hbase-site.xml will override the ones in hbase-default.xml + * unless marked as final + */ + optional LoadDefaultResources(); + + /* + * @brief Creates a Configuration object based on resources loaded from search + * paths. Search paths are defined in search_path. Values are loaded from + * resources and will be overridden unless marked as final + * @param search_path - ':' search paths to load resources. + * @param resources - list of resources used to load configuration properties. + */ + optional LoadResources(const std::string &search_path, + const std::vector &resources); + + private: + using ConfigMap = Configuration::ConfigMap; + const std::string kHBaseDefaultXml = "hbase-default.xml"; + const std::string kHBaseSiteXml = "hbase-site.xml"; + const std::string kHBaseDefauktConfPath = "/etc/hbase/conf"; + + // Adds FILE_SEPARATOR to the search path + const char kFileSeparator = '/'; + + // Separator using which multiple search paths can be defined. + const char kSearchPathSeparator = ':'; + + /** + * List of paths which will be looked up for loading properties. + */ + std::vector search_paths_; + + /** + * List of files which will be looked up in search_paths_ to load properties. + */ + std::vector resources_; + + /** + * @brief This method sets the search path to the default search path (i.e. + * "$HBASE_CONF" or "/etc/hbase/conf" if HBASE_CONF is absent) + */ + void SetDefaultSearchPath(); + + /** + * @brief Clears out the set search path(s) + */ + void ClearSearchPath(); + + /** + * @brief Sets the search path to ":"-delimited paths, clearing already + * defined values + * @param search_path Single path or ":"-delimited separated paths + */ + void SetSearchPath(const std::string &search_path); + + /** + * @brief Adds an element to the search path if not already present. + * @param search_path Path that will be added to load config values + */ + void AddToSearchPath(const std::string &search_path); + + /** + * @brief This method will add default resources i.e. hbase-default.xml and + * hbase-site.xml to the default search path. + */ + void AddDefaultResources(); + + /** + * @brief Adds resources to list for loading config values. + * @param filename to be added to resources. + */ + void AddResources(const std::string &filename); + + /** + * @brief Loads properties in file identified by file in a map identified by + * property_map + * @param file XML file which defines HBase configuration properties. + * @param property_map Property map representing HBase configuration as key + * value pairs. + * @throws Boost ptree exception if some parsing issue occurs. + */ + bool LoadProperties(const std::string &file, ConfigMap &property_map); + + /** + * @brief This method will create a map of the name and properties. + * @param map Property map to hold configuration properties. + * @param key value of name node. + * @param value value of value node. + * @param final_text value of final node true or false if present + */ + bool UpdateMapWithValue(ConfigMap &map, const std::string &key, const std::string &value, + boost::optional final_text); +}; + +} /* namespace hbase */ diff --git hbase-native-client/core/hbase-configuration-test.cc hbase-native-client/core/hbase-configuration-test.cc new file mode 100644 index 0000000..ebf0817 --- /dev/null +++ hbase-native-client/core/hbase-configuration-test.cc @@ -0,0 +1,374 @@ +/* + * 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 +#include "core/configuration.h" +#include "core/hbase-configuration-loader.h" + +using namespace hbase; + +const std::string kDefHBaseConfPath("./build/test-data/hbase-configuration-test/conf/"); +const std::string kHBaseConfPath("./build/test-data/hbase-configuration-test/custom-conf/"); + +const std::string kHBaseDefaultXml("hbase-default.xml"); +const std::string kHBaseSiteXml("hbase-site.xml"); + +const std::string kHBaseDefaultXmlData( + "\n\n\n\n\n\nhbase.rootdir\n/root/hbase-docker/apps/hbase/data\ntrue\n\n\n\nhbase.zookeeper.property.datadir\nThis value will be " + "overwritten\nfalse\n\n\n\ndefault-prop\ndefault-value\n\n\n"); +const std::string kHBaseSiteXmlData( + "\n\n\n\n\n\nhbase.rootdir\nThis value will not be be " + "overwritten\n\n\n\nhbase.zookeeper.property.datadir\n/root/hbase-docker/zookeeper\n\n\n\nhbase-client.user.name\n${user.name}\n\n\n\nhbase-client.user.dir\n${user.dir}\n\n\n\nhbase-client.user.home\n${user.home}\n\n\n\nselfRef\n${selfRef}\n\n\n\nfoo.substs\n${bar},${bar},${bar},${bar},${bar},${bar},${bar},${bar},${" + "bar},${bar},\n\n\n\nfoo.substs.exception\n${bar},${bar},${bar},${bar},${bar},${bar},${bar},${bar},${" + "bar},${bar},${bar},${bar},${bar},${bar},${bar},${bar},${bar},${bar},${bar}" + ",${bar},${bar}\n\n\n\nbar\nbar-value\n\n\n\ncustom-prop\ncustom-value\n\n\n\nint\n16000\n\n\n\nint.largevalue\n2147483646\n\n\n\nint.exception\n2147483648\n\n\n\nlong\n2147483850\n\n\n\nlong.largevalue\n9223372036854775807\n\n\n\nlong.exception\n9223372036854775810\n\n\n\ndouble\n17.9769e+100\n\n\n\ndouble.largevalue\n170.769e+200\n\n\n\ndouble.exception\n1.79769e+310\n\n\n\nbool.true\ntrue\n\n\n\nbool.false\nfalse\n\n\n\nbool.exception\nunknown " + "bool\n\n\n"); + +void WriteDataToFile(const std::string &file, const std::string &xml_data) { + std::ofstream hbase_conf; + hbase_conf.open(file.c_str()); + hbase_conf << xml_data; + hbase_conf.close(); +} + +void CreateHBaseConf(const std::string &dir, const std::string &file, const std::string xml_data) { + // Directory will be created if not present + if (!boost::filesystem::exists(dir)) { + boost::filesystem::create_directories(dir); + } + // Remove temp file always + boost::filesystem::remove((dir + file).c_str()); + WriteDataToFile((dir + file), xml_data); +} + +void CreateHBaseConfWithEnv() { + CreateHBaseConf(kDefHBaseConfPath, kHBaseDefaultXml, kHBaseDefaultXmlData); + CreateHBaseConf(kDefHBaseConfPath, kHBaseSiteXml, kHBaseSiteXmlData); + setenv("HBASE_CONF", kDefHBaseConfPath.c_str(), 1); +} + +/* + * Config will be loaded from $HBASE_CONF. We set it @ kDefHBaseConfPath + * Config values will be loaded from hbase-default.xml and hbase-site.xml + * present in the above path. + */ +TEST(Configuration, LoadConfFromDefaultLocation) { + // Remove already configured env if present. + unsetenv("HBASE_CONF"); + CreateHBaseConf(kDefHBaseConfPath, kHBaseDefaultXml, kHBaseDefaultXmlData); + CreateHBaseConf(kDefHBaseConfPath, kHBaseSiteXml, kHBaseSiteXmlData); + setenv("HBASE_CONF", kDefHBaseConfPath.c_str(), 0); + + HBaseConfigurationLoader loader; + hbase::optional conf = loader.LoadDefaultResources(); + ASSERT_TRUE(conf) << "No configuration object present."; + EXPECT_STREQ((*conf).Get("custom-prop", "Set this value").c_str(), "custom-value"); + EXPECT_STREQ((*conf).Get("default-prop", "Set this value").c_str(), "default-value"); +} + +/* + * Config will be loaded from hbase-site.xml defined at + * kHBaseConfPath + */ +TEST(Configuration, LoadConfFromCustomLocation) { + // Remove already configured env if present. + unsetenv("HBASE_CONF"); + CreateHBaseConf(kHBaseConfPath, kHBaseSiteXml, kHBaseSiteXmlData); + + HBaseConfigurationLoader loader; + std::vector resources{kHBaseSiteXml}; + hbase::optional conf = loader.LoadResources(kHBaseConfPath, resources); + ASSERT_TRUE(conf) << "No configuration object present."; + EXPECT_STREQ((*conf).Get("custom-prop", "").c_str(), "custom-value"); + EXPECT_STRNE((*conf).Get("custom-prop", "").c_str(), "some-value"); +} + +/* + * Config will be loaded from hbase-defualt.xml and hbase-site.xml @ + * kDefHBaseConfPath and kHBaseConfPath respectively. + */ +TEST(Configuration, LoadConfFromMultipleLocatons) { + // Remove already configured env if present. + unsetenv("HBASE_CONF"); + CreateHBaseConf(kDefHBaseConfPath, kHBaseDefaultXml, kHBaseDefaultXmlData); + CreateHBaseConf(kDefHBaseConfPath, kHBaseSiteXml, kHBaseSiteXmlData); + CreateHBaseConf(kHBaseConfPath, kHBaseDefaultXml, kHBaseDefaultXmlData); + CreateHBaseConf(kHBaseConfPath, kHBaseSiteXml, kHBaseSiteXmlData); + + HBaseConfigurationLoader loader; + std::string conf_paths = kDefHBaseConfPath + ":" + kHBaseConfPath; + std::vector resources{kHBaseDefaultXml, kHBaseSiteXml}; + hbase::optional conf = loader.LoadResources(conf_paths, resources); + ASSERT_TRUE(conf) << "No configuration object present."; + EXPECT_STREQ((*conf).Get("default-prop", "From hbase-default.xml").c_str(), "default-value"); + EXPECT_STREQ((*conf).Get("custom-prop", "").c_str(), "custom-value"); + EXPECT_STRNE((*conf).Get("custom-prop", "").c_str(), "some-value"); +} + +/* + * Config will be loaded from hbase-defualt.xml and hbase-site.xml @ + * $HBASE_CONF. + * We set HBASE_CONF to kDefHBaseConfPath + * Below tests load the conf files in the same way unless specified. + */ +TEST(Configuration, DefaultValues) { + // Remove already configured env if present. + unsetenv("HBASE_CONF"); + CreateHBaseConfWithEnv(); + + HBaseConfigurationLoader loader; + hbase::optional conf = loader.LoadDefaultResources(); + ASSERT_TRUE(conf) << "No configuration object present."; + EXPECT_STREQ((*conf).Get("default-prop", "Set this value.").c_str(), "default-value"); + EXPECT_STREQ((*conf).Get("custom-prop", "Set this value.").c_str(), "custom-value"); +} + +TEST(Configuration, FinalValues) { + // Remove already configured env if present. + unsetenv("HBASE_CONF"); + CreateHBaseConfWithEnv(); + + HBaseConfigurationLoader loader; + hbase::optional conf = loader.LoadDefaultResources(); + ASSERT_TRUE(conf) << "No configuration object present."; + EXPECT_STREQ((*conf).Get("hbase.rootdir", "").c_str(), "/root/hbase-docker/apps/hbase/data"); + EXPECT_STREQ((*conf).Get("hbase.zookeeper.property.datadir", "").c_str(), + "/root/hbase-docker/zookeeper"); + EXPECT_STRNE((*conf).Get("hbase.rootdir", "").c_str(), "This value will not be be overwritten"); + EXPECT_STRNE((*conf).Get("hbase.zookeeper.property.datadir", "").c_str(), + "This value will be overwritten"); +} + +/* + * Config will be loaded from HBASE_CONF which we set in + * CreateHBaseConfWithEnv(). + * Config values will be loaded from hbase-default.xml and hbase-site.xml in the + * above path. + */ +TEST(Configuration, EnvVars) { + // Remove already configured env if present. + unsetenv("HBASE_CONF"); + CreateHBaseConfWithEnv(); + + HBaseConfigurationLoader loader; + hbase::optional conf = loader.LoadDefaultResources(); + ASSERT_TRUE(conf) << "No configuration object present."; + EXPECT_STREQ((*conf).Get("hbase-client.user.name", "").c_str(), "${user.name}"); + EXPECT_STRNE((*conf).Get("hbase-client.user.name", "root").c_str(), "test-user"); +} + +TEST(Configuration, SelfRef) { + // Remove already configured env if present. + unsetenv("HBASE_CONF"); + CreateHBaseConfWithEnv(); + + HBaseConfigurationLoader loader; + hbase::optional conf = loader.LoadDefaultResources(); + ASSERT_TRUE(conf) << "No configuration object present."; + EXPECT_STREQ((*conf).Get("selfRef", "${selfRef}").c_str(), "${selfRef}"); +} + +TEST(Configuration, VarExpansion) { + // Remove already configured env if present. + unsetenv("HBASE_CONF"); + CreateHBaseConfWithEnv(); + + HBaseConfigurationLoader loader; + hbase::optional conf = loader.LoadDefaultResources(); + ASSERT_TRUE(conf) << "No configuration object present."; + EXPECT_STREQ((*conf).Get("foo.substs", "foo-value").c_str(), + "bar-value,bar-value,bar-value,bar-value,bar-value,bar-value," + "bar-value,bar-value,bar-value,bar-value,"); + EXPECT_STRNE((*conf).Get("foo.substs", "foo-value").c_str(), "bar-value"); +} + +TEST(Configuration, VarExpansionException) { + // Remove already configured env if present. + unsetenv("HBASE_CONF"); + CreateHBaseConfWithEnv(); + + HBaseConfigurationLoader loader; + hbase::optional conf = loader.LoadDefaultResources(); + ASSERT_TRUE(conf) << "No configuration object present."; + ASSERT_THROW((*conf).Get("foo.substs.exception", "foo-value").c_str(), std::runtime_error); +} + +TEST(Configuration, GetInt) { + // Remove already configured env if present. + unsetenv("HBASE_CONF"); + CreateHBaseConfWithEnv(); + + HBaseConfigurationLoader loader; + hbase::optional conf = loader.LoadDefaultResources(); + ASSERT_TRUE(conf) << "No configuration object present."; + EXPECT_EQ(16000, (*conf).GetInt("int", 0)); + EXPECT_EQ(2147483646, (*conf).GetInt("int.largevalue", 0)); +} + +TEST(Configuration, GetLong) { + // Remove already configured env if present. + unsetenv("HBASE_CONF"); + CreateHBaseConfWithEnv(); + + HBaseConfigurationLoader loader; + hbase::optional conf = loader.LoadDefaultResources(); + ASSERT_TRUE(conf) << "No configuration object present."; + EXPECT_EQ(2147483850, (*conf).GetLong("long", 0)); + EXPECT_EQ(9223372036854775807, (*conf).GetLong("long.largevalue", 0)); +} + +TEST(Configuration, GetDouble) { + // Remove already configured env if present. + unsetenv("HBASE_CONF"); + CreateHBaseConfWithEnv(); + + HBaseConfigurationLoader loader; + hbase::optional conf = loader.LoadDefaultResources(); + ASSERT_TRUE(conf) << "No configuration object present."; + EXPECT_DOUBLE_EQ(17.9769e+100, (*conf).GetDouble("double", 0.0)); + EXPECT_DOUBLE_EQ(170.769e+200, (*conf).GetDouble("double.largevalue", 0.0)); +} + +TEST(Configuration, GetBool) { + // Remove already configured env if present. + unsetenv("HBASE_CONF"); + CreateHBaseConfWithEnv(); + + HBaseConfigurationLoader loader; + hbase::optional conf = loader.LoadDefaultResources(); + ASSERT_TRUE(conf) << "No configuration object present."; + EXPECT_EQ(true, (*conf).GetBool("bool.true", true)); + EXPECT_EQ(false, (*conf).GetBool("bool.false", false)); +} + +TEST(Configuration, GetIntException) { + // Remove already configured env if present. + unsetenv("HBASE_CONF"); + CreateHBaseConfWithEnv(); + + HBaseConfigurationLoader loader; + hbase::optional conf = loader.LoadDefaultResources(); + ASSERT_TRUE(conf) << "No configuration object present."; + ASSERT_THROW((*conf).GetInt("int.exception", 0), std::runtime_error); +} + +TEST(Configuration, GetLongException) { + // Remove already configured env if present. + unsetenv("HBASE_CONF"); + CreateHBaseConfWithEnv(); + + HBaseConfigurationLoader loader; + hbase::optional conf = loader.LoadDefaultResources(); + ASSERT_TRUE(conf) << "No configuration object present."; + ASSERT_THROW((*conf).GetLong("long.exception", 0), std::runtime_error); +} + +TEST(Configuration, GetDoubleException) { + // Remove already configured env if present. + unsetenv("HBASE_CONF"); + CreateHBaseConfWithEnv(); + + HBaseConfigurationLoader loader; + hbase::optional conf = loader.LoadDefaultResources(); + ASSERT_TRUE(conf) << "No configuration object present."; + ASSERT_THROW((*conf).GetDouble("double.exception", 0), std::runtime_error); +} + +TEST(Configuration, GetBoolException) { + // Remove already configured env if present. + unsetenv("HBASE_CONF"); + CreateHBaseConfWithEnv(); + + HBaseConfigurationLoader loader; + hbase::optional conf = loader.LoadDefaultResources(); + ASSERT_TRUE(conf) << "No configuration object present."; + ASSERT_THROW((*conf).GetBool("bool.exception", false), std::runtime_error); +} diff --git hbase-native-client/core/hbase-macros.h hbase-native-client/core/hbase-macros.h new file mode 100644 index 0000000..d70c247 --- /dev/null +++ hbase-native-client/core/hbase-macros.h @@ -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. + * + */ + +#pragma once + +#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 diff --git hbase-native-client/core/hbase_configuration-test.cc hbase-native-client/core/hbase_configuration-test.cc deleted file mode 100644 index 07a6358..0000000 --- hbase-native-client/core/hbase_configuration-test.cc +++ /dev/null @@ -1,374 +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 - -#include -#include -#include -#include "core/configuration.h" -#include "core/hbase_configuration_loader.h" - -using namespace hbase; - -const std::string kDefHBaseConfPath("./build/test-data/hbase-configuration-test/conf/"); -const std::string kHBaseConfPath("./build/test-data/hbase-configuration-test/custom-conf/"); - -const std::string kHBaseDefaultXml("hbase-default.xml"); -const std::string kHBaseSiteXml("hbase-site.xml"); - -const std::string kHBaseDefaultXmlData( - "\n\n\n\n\n\nhbase.rootdir\n/root/hbase-docker/apps/hbase/data\ntrue\n\n\n\nhbase.zookeeper.property.datadir\nThis value will be " - "overwritten\nfalse\n\n\n\ndefault-prop\ndefault-value\n\n\n"); -const std::string kHBaseSiteXmlData( - "\n\n\n\n\n\nhbase.rootdir\nThis value will not be be " - "overwritten\n\n\n\nhbase.zookeeper.property.datadir\n/root/hbase-docker/zookeeper\n\n\n\nhbase-client.user.name\n${user.name}\n\n\n\nhbase-client.user.dir\n${user.dir}\n\n\n\nhbase-client.user.home\n${user.home}\n\n\n\nselfRef\n${selfRef}\n\n\n\nfoo.substs\n${bar},${bar},${bar},${bar},${bar},${bar},${bar},${bar},${" - "bar},${bar},\n\n\n\nfoo.substs.exception\n${bar},${bar},${bar},${bar},${bar},${bar},${bar},${bar},${" - "bar},${bar},${bar},${bar},${bar},${bar},${bar},${bar},${bar},${bar},${bar}" - ",${bar},${bar}\n\n\n\nbar\nbar-value\n\n\n\ncustom-prop\ncustom-value\n\n\n\nint\n16000\n\n\n\nint.largevalue\n2147483646\n\n\n\nint.exception\n2147483648\n\n\n\nlong\n2147483850\n\n\n\nlong.largevalue\n9223372036854775807\n\n\n\nlong.exception\n9223372036854775810\n\n\n\ndouble\n17.9769e+100\n\n\n\ndouble.largevalue\n170.769e+200\n\n\n\ndouble.exception\n1.79769e+310\n\n\n\nbool.true\ntrue\n\n\n\nbool.false\nfalse\n\n\n\nbool.exception\nunknown " - "bool\n\n\n"); - -void WriteDataToFile(const std::string &file, const std::string &xml_data) { - std::ofstream hbase_conf; - hbase_conf.open(file.c_str()); - hbase_conf << xml_data; - hbase_conf.close(); -} - -void CreateHBaseConf(const std::string &dir, const std::string &file, const std::string xml_data) { - // Directory will be created if not present - if (!boost::filesystem::exists(dir)) { - boost::filesystem::create_directories(dir); - } - // Remove temp file always - boost::filesystem::remove((dir + file).c_str()); - WriteDataToFile((dir + file), xml_data); -} - -void CreateHBaseConfWithEnv() { - CreateHBaseConf(kDefHBaseConfPath, kHBaseDefaultXml, kHBaseDefaultXmlData); - CreateHBaseConf(kDefHBaseConfPath, kHBaseSiteXml, kHBaseSiteXmlData); - setenv("HBASE_CONF", kDefHBaseConfPath.c_str(), 1); -} - -/* - * Config will be loaded from $HBASE_CONF. We set it @ kDefHBaseConfPath - * Config values will be loaded from hbase-default.xml and hbase-site.xml - * present in the above path. - */ -TEST(Configuration, LoadConfFromDefaultLocation) { - // Remove already configured env if present. - unsetenv("HBASE_CONF"); - CreateHBaseConf(kDefHBaseConfPath, kHBaseDefaultXml, kHBaseDefaultXmlData); - CreateHBaseConf(kDefHBaseConfPath, kHBaseSiteXml, kHBaseSiteXmlData); - setenv("HBASE_CONF", kDefHBaseConfPath.c_str(), 0); - - HBaseConfigurationLoader loader; - hbase::optional conf = loader.LoadDefaultResources(); - ASSERT_TRUE(conf) << "No configuration object present."; - EXPECT_STREQ((*conf).Get("custom-prop", "Set this value").c_str(), "custom-value"); - EXPECT_STREQ((*conf).Get("default-prop", "Set this value").c_str(), "default-value"); -} - -/* - * Config will be loaded from hbase-site.xml defined at - * kHBaseConfPath - */ -TEST(Configuration, LoadConfFromCustomLocation) { - // Remove already configured env if present. - unsetenv("HBASE_CONF"); - CreateHBaseConf(kHBaseConfPath, kHBaseSiteXml, kHBaseSiteXmlData); - - HBaseConfigurationLoader loader; - std::vector resources{kHBaseSiteXml}; - hbase::optional conf = loader.LoadResources(kHBaseConfPath, resources); - ASSERT_TRUE(conf) << "No configuration object present."; - EXPECT_STREQ((*conf).Get("custom-prop", "").c_str(), "custom-value"); - EXPECT_STRNE((*conf).Get("custom-prop", "").c_str(), "some-value"); -} - -/* - * Config will be loaded from hbase-defualt.xml and hbase-site.xml @ - * kDefHBaseConfPath and kHBaseConfPath respectively. - */ -TEST(Configuration, LoadConfFromMultipleLocatons) { - // Remove already configured env if present. - unsetenv("HBASE_CONF"); - CreateHBaseConf(kDefHBaseConfPath, kHBaseDefaultXml, kHBaseDefaultXmlData); - CreateHBaseConf(kDefHBaseConfPath, kHBaseSiteXml, kHBaseSiteXmlData); - CreateHBaseConf(kHBaseConfPath, kHBaseDefaultXml, kHBaseDefaultXmlData); - CreateHBaseConf(kHBaseConfPath, kHBaseSiteXml, kHBaseSiteXmlData); - - HBaseConfigurationLoader loader; - std::string conf_paths = kDefHBaseConfPath + ":" + kHBaseConfPath; - std::vector resources{kHBaseDefaultXml, kHBaseSiteXml}; - hbase::optional conf = loader.LoadResources(conf_paths, resources); - ASSERT_TRUE(conf) << "No configuration object present."; - EXPECT_STREQ((*conf).Get("default-prop", "From hbase-default.xml").c_str(), "default-value"); - EXPECT_STREQ((*conf).Get("custom-prop", "").c_str(), "custom-value"); - EXPECT_STRNE((*conf).Get("custom-prop", "").c_str(), "some-value"); -} - -/* - * Config will be loaded from hbase-defualt.xml and hbase-site.xml @ - * $HBASE_CONF. - * We set HBASE_CONF to kDefHBaseConfPath - * Below tests load the conf files in the same way unless specified. - */ -TEST(Configuration, DefaultValues) { - // Remove already configured env if present. - unsetenv("HBASE_CONF"); - CreateHBaseConfWithEnv(); - - HBaseConfigurationLoader loader; - hbase::optional conf = loader.LoadDefaultResources(); - ASSERT_TRUE(conf) << "No configuration object present."; - EXPECT_STREQ((*conf).Get("default-prop", "Set this value.").c_str(), "default-value"); - EXPECT_STREQ((*conf).Get("custom-prop", "Set this value.").c_str(), "custom-value"); -} - -TEST(Configuration, FinalValues) { - // Remove already configured env if present. - unsetenv("HBASE_CONF"); - CreateHBaseConfWithEnv(); - - HBaseConfigurationLoader loader; - hbase::optional conf = loader.LoadDefaultResources(); - ASSERT_TRUE(conf) << "No configuration object present."; - EXPECT_STREQ((*conf).Get("hbase.rootdir", "").c_str(), "/root/hbase-docker/apps/hbase/data"); - EXPECT_STREQ((*conf).Get("hbase.zookeeper.property.datadir", "").c_str(), - "/root/hbase-docker/zookeeper"); - EXPECT_STRNE((*conf).Get("hbase.rootdir", "").c_str(), "This value will not be be overwritten"); - EXPECT_STRNE((*conf).Get("hbase.zookeeper.property.datadir", "").c_str(), - "This value will be overwritten"); -} - -/* - * Config will be loaded from HBASE_CONF which we set in - * CreateHBaseConfWithEnv(). - * Config values will be loaded from hbase-default.xml and hbase-site.xml in the - * above path. - */ -TEST(Configuration, EnvVars) { - // Remove already configured env if present. - unsetenv("HBASE_CONF"); - CreateHBaseConfWithEnv(); - - HBaseConfigurationLoader loader; - hbase::optional conf = loader.LoadDefaultResources(); - ASSERT_TRUE(conf) << "No configuration object present."; - EXPECT_STREQ((*conf).Get("hbase-client.user.name", "").c_str(), "${user.name}"); - EXPECT_STRNE((*conf).Get("hbase-client.user.name", "root").c_str(), "test-user"); -} - -TEST(Configuration, SelfRef) { - // Remove already configured env if present. - unsetenv("HBASE_CONF"); - CreateHBaseConfWithEnv(); - - HBaseConfigurationLoader loader; - hbase::optional conf = loader.LoadDefaultResources(); - ASSERT_TRUE(conf) << "No configuration object present."; - EXPECT_STREQ((*conf).Get("selfRef", "${selfRef}").c_str(), "${selfRef}"); -} - -TEST(Configuration, VarExpansion) { - // Remove already configured env if present. - unsetenv("HBASE_CONF"); - CreateHBaseConfWithEnv(); - - HBaseConfigurationLoader loader; - hbase::optional conf = loader.LoadDefaultResources(); - ASSERT_TRUE(conf) << "No configuration object present."; - EXPECT_STREQ((*conf).Get("foo.substs", "foo-value").c_str(), - "bar-value,bar-value,bar-value,bar-value,bar-value,bar-value," - "bar-value,bar-value,bar-value,bar-value,"); - EXPECT_STRNE((*conf).Get("foo.substs", "foo-value").c_str(), "bar-value"); -} - -TEST(Configuration, VarExpansionException) { - // Remove already configured env if present. - unsetenv("HBASE_CONF"); - CreateHBaseConfWithEnv(); - - HBaseConfigurationLoader loader; - hbase::optional conf = loader.LoadDefaultResources(); - ASSERT_TRUE(conf) << "No configuration object present."; - ASSERT_THROW((*conf).Get("foo.substs.exception", "foo-value").c_str(), std::runtime_error); -} - -TEST(Configuration, GetInt) { - // Remove already configured env if present. - unsetenv("HBASE_CONF"); - CreateHBaseConfWithEnv(); - - HBaseConfigurationLoader loader; - hbase::optional conf = loader.LoadDefaultResources(); - ASSERT_TRUE(conf) << "No configuration object present."; - EXPECT_EQ(16000, (*conf).GetInt("int", 0)); - EXPECT_EQ(2147483646, (*conf).GetInt("int.largevalue", 0)); -} - -TEST(Configuration, GetLong) { - // Remove already configured env if present. - unsetenv("HBASE_CONF"); - CreateHBaseConfWithEnv(); - - HBaseConfigurationLoader loader; - hbase::optional conf = loader.LoadDefaultResources(); - ASSERT_TRUE(conf) << "No configuration object present."; - EXPECT_EQ(2147483850, (*conf).GetLong("long", 0)); - EXPECT_EQ(9223372036854775807, (*conf).GetLong("long.largevalue", 0)); -} - -TEST(Configuration, GetDouble) { - // Remove already configured env if present. - unsetenv("HBASE_CONF"); - CreateHBaseConfWithEnv(); - - HBaseConfigurationLoader loader; - hbase::optional conf = loader.LoadDefaultResources(); - ASSERT_TRUE(conf) << "No configuration object present."; - EXPECT_DOUBLE_EQ(17.9769e+100, (*conf).GetDouble("double", 0.0)); - EXPECT_DOUBLE_EQ(170.769e+200, (*conf).GetDouble("double.largevalue", 0.0)); -} - -TEST(Configuration, GetBool) { - // Remove already configured env if present. - unsetenv("HBASE_CONF"); - CreateHBaseConfWithEnv(); - - HBaseConfigurationLoader loader; - hbase::optional conf = loader.LoadDefaultResources(); - ASSERT_TRUE(conf) << "No configuration object present."; - EXPECT_EQ(true, (*conf).GetBool("bool.true", true)); - EXPECT_EQ(false, (*conf).GetBool("bool.false", false)); -} - -TEST(Configuration, GetIntException) { - // Remove already configured env if present. - unsetenv("HBASE_CONF"); - CreateHBaseConfWithEnv(); - - HBaseConfigurationLoader loader; - hbase::optional conf = loader.LoadDefaultResources(); - ASSERT_TRUE(conf) << "No configuration object present."; - ASSERT_THROW((*conf).GetInt("int.exception", 0), std::runtime_error); -} - -TEST(Configuration, GetLongException) { - // Remove already configured env if present. - unsetenv("HBASE_CONF"); - CreateHBaseConfWithEnv(); - - HBaseConfigurationLoader loader; - hbase::optional conf = loader.LoadDefaultResources(); - ASSERT_TRUE(conf) << "No configuration object present."; - ASSERT_THROW((*conf).GetLong("long.exception", 0), std::runtime_error); -} - -TEST(Configuration, GetDoubleException) { - // Remove already configured env if present. - unsetenv("HBASE_CONF"); - CreateHBaseConfWithEnv(); - - HBaseConfigurationLoader loader; - hbase::optional conf = loader.LoadDefaultResources(); - ASSERT_TRUE(conf) << "No configuration object present."; - ASSERT_THROW((*conf).GetDouble("double.exception", 0), std::runtime_error); -} - -TEST(Configuration, GetBoolException) { - // Remove already configured env if present. - unsetenv("HBASE_CONF"); - CreateHBaseConfWithEnv(); - - HBaseConfigurationLoader loader; - hbase::optional conf = loader.LoadDefaultResources(); - ASSERT_TRUE(conf) << "No configuration object present."; - ASSERT_THROW((*conf).GetBool("bool.exception", false), std::runtime_error); -} diff --git hbase-native-client/core/hbase_configuration_loader.cc hbase-native-client/core/hbase_configuration_loader.cc deleted file mode 100644 index 38a617b..0000000 --- hbase-native-client/core/hbase_configuration_loader.cc +++ /dev/null @@ -1,208 +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/hbase_configuration_loader.h" - -#include -#include -#include -#include - -namespace hbase { - -bool is_valid_bool(const std::string &raw) { - if (raw.empty()) { - return false; - } - - if (!strcasecmp(raw.c_str(), "true")) { - return true; - } - if (!strcasecmp(raw.c_str(), "false")) { - return true; - } - return false; -} - -bool str_to_bool(const std::string &raw) { - if (!strcasecmp(raw.c_str(), "true")) { - return true; - } - return false; -} - -HBaseConfigurationLoader::HBaseConfigurationLoader() {} - -HBaseConfigurationLoader::~HBaseConfigurationLoader() {} - -void HBaseConfigurationLoader::SetDefaultSearchPath() { - /* - * Try (in order, taking the first valid one): - * $HBASE_CONF_DIR - * /etc/hbase/conf - * - */ - const char *hadoop_conf_dir_env = getenv("HBASE_CONF"); - if (hadoop_conf_dir_env) { - AddToSearchPath(hadoop_conf_dir_env); - } else { - AddToSearchPath(kHBaseDefauktConfPath); - } -} - -void HBaseConfigurationLoader::ClearSearchPath() { search_paths_.clear(); } - -void HBaseConfigurationLoader::SetSearchPath(const std::string &search_path) { - search_paths_.clear(); - - std::vector paths; - std::string::size_type start = 0; - std::string::size_type end = search_path.find(kSearchPathSeparator); - - while (end != std::string::npos) { - paths.push_back(search_path.substr(start, end - start)); - start = ++end; - end = search_path.find(kSearchPathSeparator, start); - } - paths.push_back(search_path.substr(start, search_path.length())); - - for (auto path : paths) { - AddToSearchPath(path); - } -} - -void HBaseConfigurationLoader::AddToSearchPath(const std::string &search_path) { - if (search_path.empty()) return; - - std::string path_to_add(search_path); - if (search_path.back() != kFileSeparator) { - path_to_add += kFileSeparator; - } - if (std::find(search_paths_.begin(), search_paths_.end(), path_to_add) == search_paths_.end()) - search_paths_.push_back(path_to_add); -} - -void HBaseConfigurationLoader::AddDefaultResources() { - resources_.push_back(kHBaseDefaultXml); - resources_.push_back(kHBaseSiteXml); -} - -void HBaseConfigurationLoader::AddResources(const std::string &filename) { - if (std::find(resources_.begin(), resources_.end(), filename) == resources_.end()) - resources_.push_back(filename); -} - -optional HBaseConfigurationLoader::LoadDefaultResources() { - SetDefaultSearchPath(); - AddDefaultResources(); - ConfigMap conf_property; - bool success = false; - for (auto dir : search_paths_) { - for (auto file : resources_) { - std::string config_file = dir + file; - std::ifstream stream(config_file); - if (stream.is_open()) { - success |= LoadProperties(config_file, conf_property); - } else { - DLOG(WARNING) << "Unable to open file[" << config_file << "]"; - } - } - } - if (success) { - return std::experimental::make_optional(Configuration(conf_property)); - } else { - return optional(); - } -} - -optional HBaseConfigurationLoader::LoadResources( - const std::string &search_path, const std::vector &resources) { - SetSearchPath(search_path); - for (const auto &resource : resources) AddResources(resource); - ConfigMap conf_property; - bool success = false; - for (auto dir : search_paths_) { - for (auto file : resources_) { - std::string config_file = dir + file; - std::ifstream stream(config_file); - if (stream.is_open()) { - success |= LoadProperties(config_file, conf_property); - } else { - DLOG(WARNING) << "Unable to open file[" << config_file << "]"; - } - } - } - if (success) { - return std::experimental::make_optional(Configuration(conf_property)); - } else { - return optional(); - } -} - -bool HBaseConfigurationLoader::LoadProperties(const std::string &file, ConfigMap &property_map) { - // Create empty property tree object - using boost::property_tree::ptree; - ptree pt; - try { - // Load XML file and put contents in a property tree. - // If read fails, throw exception. - read_xml(file, pt); - - // If configuration key is not found exception is thrown - std::string configuration = pt.get("configuration"); - - // Iterate over configuration section. - // Store all found properties in ConfigMap - BOOST_FOREACH (ptree::value_type &v, pt.get_child("configuration")) { - if ("property" == v.first) { - std::string name_node = v.second.get("name"); - std::string value_node = v.second.get("value"); - if ((name_node.size() > 0) && (value_node.size() > 0)) { - boost::optional final_node = v.second.get_optional("final"); - UpdateMapWithValue(property_map, name_node, value_node, final_node); - } - } - } - } catch (std::exception &ex) { - DLOG(WARNING) << "Exception in parsing file [" << file << "]:[" << ex.what() << "]"; - return false; - } - return true; -} - -bool HBaseConfigurationLoader::UpdateMapWithValue(ConfigMap &map, const std::string &key, - const std::string &value, - boost::optional final_text) { - auto map_value = map.find(key); - if (map_value != map.end() && map_value->second.final) { - return false; - } - - bool final_value = false; - if (nullptr != final_text.get_ptr()) { - if (is_valid_bool(final_text.get())) { - final_value = str_to_bool(final_text.get()); - } - } - - map[key].value = value; - map[key].final = final_value; - return true; -} -} /* namespace hbase */ diff --git hbase-native-client/core/hbase_configuration_loader.h hbase-native-client/core/hbase_configuration_loader.h deleted file mode 100644 index a1c1d3f..0000000 --- hbase-native-client/core/hbase_configuration_loader.h +++ /dev/null @@ -1,143 +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. - * - */ - -#pragma once - -#include -#include -#include - -#include -#include - -#include "core/configuration.h" - -namespace hbase { - -template -using optional = std::experimental::optional; - -class HBaseConfigurationLoader { - public: - HBaseConfigurationLoader(); - ~HBaseConfigurationLoader(); - - /** - * @brief Creates a Configuration object based on default resources loaded - * from default search paths. Default search path will be either $HBASE_CONF - * is set or /etc/hbase/conf. Default resources are hbase-default.xml and - * hbase-site.xml.SetDefaultSearchPath() and AddDefaultResources() are used - * for the same. - * Values are loaded in from hbase-default.xml first and then from - * hbase-site.xml. - * Properties in hbase-site.xml will override the ones in hbase-default.xml - * unless marked as final - */ - optional LoadDefaultResources(); - - /* - * @brief Creates a Configuration object based on resources loaded from search - * paths. Search paths are defined in search_path. Values are loaded from - * resources and will be overridden unless marked as final - * @param search_path - ':' search paths to load resources. - * @param resources - list of resources used to load configuration properties. - */ - optional LoadResources(const std::string &search_path, - const std::vector &resources); - - private: - using ConfigMap = Configuration::ConfigMap; - const std::string kHBaseDefaultXml = "hbase-default.xml"; - const std::string kHBaseSiteXml = "hbase-site.xml"; - const std::string kHBaseDefauktConfPath = "/etc/hbase/conf"; - - // Adds FILE_SEPARATOR to the search path - const char kFileSeparator = '/'; - - // Separator using which multiple search paths can be defined. - const char kSearchPathSeparator = ':'; - - /** - * List of paths which will be looked up for loading properties. - */ - std::vector search_paths_; - - /** - * List of files which will be looked up in search_paths_ to load properties. - */ - std::vector resources_; - - /** - * @brief This method sets the search path to the default search path (i.e. - * "$HBASE_CONF" or "/etc/hbase/conf" if HBASE_CONF is absent) - */ - void SetDefaultSearchPath(); - - /** - * @brief Clears out the set search path(s) - */ - void ClearSearchPath(); - - /** - * @brief Sets the search path to ":"-delimited paths, clearing already - * defined values - * @param search_path Single path or ":"-delimited separated paths - */ - void SetSearchPath(const std::string &search_path); - - /** - * @brief Adds an element to the search path if not already present. - * @param search_path Path that will be added to load config values - */ - void AddToSearchPath(const std::string &search_path); - - /** - * @brief This method will add default resources i.e. hbase-default.xml and - * hbase-site.xml to the default search path. - */ - void AddDefaultResources(); - - /** - * @brief Adds resources to list for loading config values. - * @param filename to be added to resources. - */ - void AddResources(const std::string &filename); - - /** - * @brief Loads properties in file identified by file in a map identified by - * property_map - * @param file XML file which defines HBase configuration properties. - * @param property_map Property map representing HBase configuration as key - * value pairs. - * @throws Boost ptree exception if some parsing issue occurs. - */ - bool LoadProperties(const std::string &file, ConfigMap &property_map); - - /** - * @brief This method will create a map of the name and properties. - * @param map Property map to hold configuration properties. - * @param key value of name node. - * @param value value of value node. - * @param final_text value of final node true or false if present - */ - bool UpdateMapWithValue(ConfigMap &map, const std::string &key, const std::string &value, - boost::optional final_text); -}; - -} /* namespace hbase */ diff --git hbase-native-client/core/hbase_macros.h hbase-native-client/core/hbase_macros.h deleted file mode 100644 index d70c247..0000000 --- hbase-native-client/core/hbase_macros.h +++ /dev/null @@ -1,56 +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. - * - */ - -#pragma once - -#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 diff --git hbase-native-client/core/meta-utils.cc hbase-native-client/core/meta-utils.cc index bd26607..24a0360 100644 --- hbase-native-client/core/meta-utils.cc +++ hbase-native-client/core/meta-utils.cc @@ -24,7 +24,7 @@ #include "connection/request.h" #include "connection/response.h" -#include "core/response_converter.h" +#include "core/response-converter.h" #include "if/Client.pb.h" #include "serde/region-info.h" #include "serde/server-name.h" diff --git hbase-native-client/core/request-converter-test.cc hbase-native-client/core/request-converter-test.cc new file mode 100644 index 0000000..c01f16c --- /dev/null +++ hbase-native-client/core/request-converter-test.cc @@ -0,0 +1,127 @@ +/* + * 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/request-converter.h" + +#include +#include +#include "connection/request.h" +#include "core/get.h" +#include "core/scan.h" + +using hbase::Get; +using hbase::Scan; + +using hbase::pb::GetRequest; +using hbase::pb::RegionSpecifier; +using hbase::pb::RegionSpecifier_RegionSpecifierType; +using hbase::pb::ScanRequest; + +TEST(RequestConverter, ToGet) { + std::string row_str = "row-test"; + Get get(row_str); + get.AddFamily("family-1"); + get.AddFamily("family-2"); + get.AddFamily("family-3"); + get.AddColumn("family-2", "qualifier-1"); + get.AddColumn("family-2", "qualifier-2"); + get.AddColumn("family-2", "qualifier-3"); + get.SetCacheBlocks(false); + get.SetConsistency(hbase::pb::Consistency::TIMELINE); + get.SetMaxVersions(2); + get.SetTimeRange(10000, 20000); + std::string region_name("RegionName"); + + auto req = hbase::RequestConverter::ToGetRequest(get, region_name); + auto msg = std::static_pointer_cast(req->req_msg()); + + // Tests whether the PB object is properly set or not. + ASSERT_TRUE(msg->has_region()); + ASSERT_TRUE(msg->region().has_value()); + EXPECT_EQ(msg->region().value(), region_name); + + ASSERT_TRUE(msg->has_get()); + EXPECT_EQ(msg->get().row(), row_str); + EXPECT_FALSE(msg->get().cache_blocks()); + EXPECT_EQ(msg->get().consistency(), hbase::pb::Consistency::TIMELINE); + EXPECT_EQ(msg->get().max_versions(), 2); + EXPECT_EQ(msg->get().column_size(), 3); + for (int i = 0; i < msg->get().column_size(); ++i) { + EXPECT_EQ(msg->get().column(i).family(), "family-" + std::to_string(i + 1)); + for (int j = 0; j < msg->get().column(i).qualifier_size(); ++j) { + EXPECT_EQ(msg->get().column(i).qualifier(j), "qualifier-" + std::to_string(j + 1)); + } + } +} + +TEST(RequestConverter, ToScan) { + std::string start_row("start-row"); + std::string stop_row("stop-row"); + hbase::Scan scan; + scan.AddFamily("family-1"); + scan.AddFamily("family-2"); + scan.AddFamily("family-3"); + scan.AddColumn("family-2", "qualifier-1"); + scan.AddColumn("family-2", "qualifier-2"); + scan.AddColumn("family-2", "qualifier-3"); + scan.SetReversed(true); + scan.SetStartRow(start_row); + scan.SetStopRow(stop_row); + scan.SetSmall(true); + scan.SetCaching(3); + scan.SetConsistency(hbase::pb::Consistency::TIMELINE); + scan.SetCacheBlocks(true); + scan.SetAllowPartialResults(true); + scan.SetLoadColumnFamiliesOnDemand(true); + scan.SetMaxVersions(5); + scan.SetTimeRange(10000, 20000); + std::string region_name("RegionName"); + + auto req = hbase::RequestConverter::ToScanRequest(scan, region_name); + auto msg = std::static_pointer_cast(req->req_msg()); + + // Tests whether the PB object is properly set or not. + ASSERT_TRUE(msg->has_region()); + ASSERT_TRUE(msg->region().has_value()); + EXPECT_EQ(msg->region().value(), region_name); + + ASSERT_TRUE(msg->has_scan()); + EXPECT_TRUE(msg->scan().reversed()); + EXPECT_EQ(msg->scan().start_row(), start_row); + EXPECT_EQ(msg->scan().stop_row(), stop_row); + EXPECT_TRUE(msg->scan().small()); + EXPECT_EQ(msg->scan().caching(), 3); + EXPECT_EQ(msg->scan().consistency(), hbase::pb::Consistency::TIMELINE); + EXPECT_TRUE(msg->scan().cache_blocks()); + EXPECT_TRUE(msg->scan().allow_partial_results()); + EXPECT_TRUE(msg->scan().load_column_families_on_demand()); + EXPECT_EQ(msg->scan().max_versions(), 5); + EXPECT_EQ(msg->scan().max_result_size(), std::numeric_limits::max()); + + EXPECT_EQ(msg->scan().column_size(), 3); + for (int i = 0; i < msg->scan().column_size(); ++i) { + EXPECT_EQ(msg->scan().column(i).family(), "family-" + std::to_string(i + 1)); + for (int j = 0; j < msg->scan().column(i).qualifier_size(); ++j) { + EXPECT_EQ(msg->scan().column(i).qualifier(j), "qualifier-" + std::to_string(j + 1)); + } + } + ASSERT_FALSE(msg->client_handles_partials()); + ASSERT_FALSE(msg->client_handles_heartbeats()); + ASSERT_FALSE(msg->track_scan_metrics()); +} diff --git hbase-native-client/core/request-converter.cc hbase-native-client/core/request-converter.cc new file mode 100644 index 0000000..227e04a --- /dev/null +++ hbase-native-client/core/request-converter.cc @@ -0,0 +1,126 @@ +/* + * 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/request-converter.h" +#include +#include "if/Client.pb.h" + +using hbase::Request; +using hbase::pb::GetRequest; +using hbase::pb::RegionSpecifier; +using hbase::pb::RegionSpecifier_RegionSpecifierType; +using hbase::pb::ScanRequest; + +namespace hbase { + +RequestConverter::~RequestConverter() {} + +RequestConverter::RequestConverter() {} + +void RequestConverter::SetRegion(const std::string ®ion_name, + RegionSpecifier *region_specifier) { + region_specifier->set_type( + RegionSpecifier_RegionSpecifierType::RegionSpecifier_RegionSpecifierType_REGION_NAME); + region_specifier->set_value(region_name); +} + +std::unique_ptr RequestConverter::ToGetRequest(const Get &get, + const std::string ®ion_name) { + auto pb_req = Request::get(); + + auto pb_msg = std::static_pointer_cast(pb_req->req_msg()); + RequestConverter::SetRegion(region_name, pb_msg->mutable_region()); + + auto pb_get = pb_msg->mutable_get(); + pb_get->set_max_versions(get.MaxVersions()); + pb_get->set_cache_blocks(get.CacheBlocks()); + pb_get->set_consistency(get.Consistency()); + + if (!get.Timerange().IsAllTime()) { + hbase::pb::TimeRange *pb_time_range = pb_get->mutable_time_range(); + pb_time_range->set_from(get.Timerange().MinTimeStamp()); + pb_time_range->set_to(get.Timerange().MaxTimeStamp()); + } + pb_get->set_row(get.Row()); + if (get.HasFamilies()) { + for (const auto &family : get.Family()) { + auto column = pb_get->add_column(); + column->set_family(family.first); + for (const auto &qualifier : family.second) { + column->add_qualifier(qualifier); + } + } + } + + if (get.filter() != nullptr) { + pb_get->set_allocated_filter(Filter::ToProto(*(get.filter())).release()); + } + + return pb_req; +} + +std::unique_ptr RequestConverter::ToScanRequest(const Scan &scan, + const std::string ®ion_name) { + auto pb_req = Request::scan(); + + auto pb_msg = std::static_pointer_cast(pb_req->req_msg()); + + RequestConverter::SetRegion(region_name, pb_msg->mutable_region()); + + auto pb_scan = pb_msg->mutable_scan(); + pb_scan->set_max_versions(scan.MaxVersions()); + pb_scan->set_cache_blocks(scan.CacheBlocks()); + pb_scan->set_reversed(scan.IsReversed()); + pb_scan->set_small(scan.IsSmall()); + pb_scan->set_caching(scan.Caching()); + pb_scan->set_start_row(scan.StartRow()); + pb_scan->set_stop_row(scan.StopRow()); + pb_scan->set_consistency(scan.Consistency()); + pb_scan->set_max_result_size(scan.MaxResultSize()); + pb_scan->set_allow_partial_results(scan.AllowPartialResults()); + pb_scan->set_load_column_families_on_demand(scan.LoadColumnFamiliesOnDemand()); + + if (!scan.Timerange().IsAllTime()) { + hbase::pb::TimeRange *pb_time_range = pb_scan->mutable_time_range(); + pb_time_range->set_from(scan.Timerange().MinTimeStamp()); + pb_time_range->set_to(scan.Timerange().MaxTimeStamp()); + } + + if (scan.HasFamilies()) { + for (const auto &family : scan.Family()) { + auto column = pb_scan->add_column(); + column->set_family(family.first); + for (const auto &qualifier : family.second) { + column->add_qualifier(qualifier); + } + } + } + + if (scan.filter() != nullptr) { + pb_scan->set_allocated_filter(Filter::ToProto(*(scan.filter())).release()); + } + + // TODO We will change this later. + pb_msg->set_client_handles_partials(false); + pb_msg->set_client_handles_heartbeats(false); + pb_msg->set_track_scan_metrics(false); + + return pb_req; +} +} /* namespace hbase */ diff --git hbase-native-client/core/request-converter.h hbase-native-client/core/request-converter.h new file mode 100644 index 0000000..57f08cc --- /dev/null +++ hbase-native-client/core/request-converter.h @@ -0,0 +1,69 @@ +/* + * 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 "connection/request.h" +#include "core/get.h" +#include "core/scan.h" +#include "if/HBase.pb.h" + +using hbase::pb::RegionSpecifier; +namespace hbase { + +/** + * RequestConverter class + * This class converts a Client side Get, Scan, Mutate operation to corresponding PB message. + */ +class RequestConverter { + public: + ~RequestConverter(); + + /** + * @brief Returns a Request object comprising of PB GetRequest created using + * passed 'get' + * @param get - Get object used for creating GetRequest + * @param region_name - table region + */ + static std::unique_ptr ToGetRequest(const Get &get, const std::string ®ion_name); + + /** + * @brief Returns a Request object comprising of PB ScanRequest created using + * passed 'scan' + * @param scan - Scan object used for creating ScanRequest + * @param region_name - table region + */ + static std::unique_ptr ToScanRequest(const Scan &scan, const std::string ®ion_name); + + private: + // Constructor not required. We have all static methods to create PB requests. + RequestConverter(); + + /** + * @brief fills region_specifier with region values. + * @param region_name - table region + * @param region_specifier - RegionSpecifier to be filled and passed in PB + * Request. + */ + static void SetRegion(const std::string ®ion_name, RegionSpecifier *region_specifier); +}; + +} /* namespace hbase */ diff --git hbase-native-client/core/request_converter-test.cc hbase-native-client/core/request_converter-test.cc deleted file mode 100644 index 84d5e8b..0000000 --- hbase-native-client/core/request_converter-test.cc +++ /dev/null @@ -1,127 +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/request_converter.h" - -#include -#include -#include "connection/request.h" -#include "core/get.h" -#include "core/scan.h" - -using hbase::Get; -using hbase::Scan; - -using hbase::pb::GetRequest; -using hbase::pb::RegionSpecifier; -using hbase::pb::RegionSpecifier_RegionSpecifierType; -using hbase::pb::ScanRequest; - -TEST(RequestConverter, ToGet) { - std::string row_str = "row-test"; - Get get(row_str); - get.AddFamily("family-1"); - get.AddFamily("family-2"); - get.AddFamily("family-3"); - get.AddColumn("family-2", "qualifier-1"); - get.AddColumn("family-2", "qualifier-2"); - get.AddColumn("family-2", "qualifier-3"); - get.SetCacheBlocks(false); - get.SetConsistency(hbase::pb::Consistency::TIMELINE); - get.SetMaxVersions(2); - get.SetTimeRange(10000, 20000); - std::string region_name("RegionName"); - - auto req = hbase::RequestConverter::ToGetRequest(get, region_name); - auto msg = std::static_pointer_cast(req->req_msg()); - - // Tests whether the PB object is properly set or not. - ASSERT_TRUE(msg->has_region()); - ASSERT_TRUE(msg->region().has_value()); - EXPECT_EQ(msg->region().value(), region_name); - - ASSERT_TRUE(msg->has_get()); - EXPECT_EQ(msg->get().row(), row_str); - EXPECT_FALSE(msg->get().cache_blocks()); - EXPECT_EQ(msg->get().consistency(), hbase::pb::Consistency::TIMELINE); - EXPECT_EQ(msg->get().max_versions(), 2); - EXPECT_EQ(msg->get().column_size(), 3); - for (int i = 0; i < msg->get().column_size(); ++i) { - EXPECT_EQ(msg->get().column(i).family(), "family-" + std::to_string(i + 1)); - for (int j = 0; j < msg->get().column(i).qualifier_size(); ++j) { - EXPECT_EQ(msg->get().column(i).qualifier(j), "qualifier-" + std::to_string(j + 1)); - } - } -} - -TEST(RequestConverter, ToScan) { - std::string start_row("start-row"); - std::string stop_row("stop-row"); - hbase::Scan scan; - scan.AddFamily("family-1"); - scan.AddFamily("family-2"); - scan.AddFamily("family-3"); - scan.AddColumn("family-2", "qualifier-1"); - scan.AddColumn("family-2", "qualifier-2"); - scan.AddColumn("family-2", "qualifier-3"); - scan.SetReversed(true); - scan.SetStartRow(start_row); - scan.SetStopRow(stop_row); - scan.SetSmall(true); - scan.SetCaching(3); - scan.SetConsistency(hbase::pb::Consistency::TIMELINE); - scan.SetCacheBlocks(true); - scan.SetAllowPartialResults(true); - scan.SetLoadColumnFamiliesOnDemand(true); - scan.SetMaxVersions(5); - scan.SetTimeRange(10000, 20000); - std::string region_name("RegionName"); - - auto req = hbase::RequestConverter::ToScanRequest(scan, region_name); - auto msg = std::static_pointer_cast(req->req_msg()); - - // Tests whether the PB object is properly set or not. - ASSERT_TRUE(msg->has_region()); - ASSERT_TRUE(msg->region().has_value()); - EXPECT_EQ(msg->region().value(), region_name); - - ASSERT_TRUE(msg->has_scan()); - EXPECT_TRUE(msg->scan().reversed()); - EXPECT_EQ(msg->scan().start_row(), start_row); - EXPECT_EQ(msg->scan().stop_row(), stop_row); - EXPECT_TRUE(msg->scan().small()); - EXPECT_EQ(msg->scan().caching(), 3); - EXPECT_EQ(msg->scan().consistency(), hbase::pb::Consistency::TIMELINE); - EXPECT_TRUE(msg->scan().cache_blocks()); - EXPECT_TRUE(msg->scan().allow_partial_results()); - EXPECT_TRUE(msg->scan().load_column_families_on_demand()); - EXPECT_EQ(msg->scan().max_versions(), 5); - EXPECT_EQ(msg->scan().max_result_size(), std::numeric_limits::max()); - - EXPECT_EQ(msg->scan().column_size(), 3); - for (int i = 0; i < msg->scan().column_size(); ++i) { - EXPECT_EQ(msg->scan().column(i).family(), "family-" + std::to_string(i + 1)); - for (int j = 0; j < msg->scan().column(i).qualifier_size(); ++j) { - EXPECT_EQ(msg->scan().column(i).qualifier(j), "qualifier-" + std::to_string(j + 1)); - } - } - ASSERT_FALSE(msg->client_handles_partials()); - ASSERT_FALSE(msg->client_handles_heartbeats()); - ASSERT_FALSE(msg->track_scan_metrics()); -} diff --git hbase-native-client/core/request_converter.cc hbase-native-client/core/request_converter.cc deleted file mode 100644 index 149202e..0000000 --- hbase-native-client/core/request_converter.cc +++ /dev/null @@ -1,126 +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/request_converter.h" -#include -#include "if/Client.pb.h" - -using hbase::Request; -using hbase::pb::GetRequest; -using hbase::pb::RegionSpecifier; -using hbase::pb::RegionSpecifier_RegionSpecifierType; -using hbase::pb::ScanRequest; - -namespace hbase { - -RequestConverter::~RequestConverter() {} - -RequestConverter::RequestConverter() {} - -void RequestConverter::SetRegion(const std::string ®ion_name, - RegionSpecifier *region_specifier) { - region_specifier->set_type( - RegionSpecifier_RegionSpecifierType::RegionSpecifier_RegionSpecifierType_REGION_NAME); - region_specifier->set_value(region_name); -} - -std::unique_ptr RequestConverter::ToGetRequest(const Get &get, - const std::string ®ion_name) { - auto pb_req = Request::get(); - - auto pb_msg = std::static_pointer_cast(pb_req->req_msg()); - RequestConverter::SetRegion(region_name, pb_msg->mutable_region()); - - auto pb_get = pb_msg->mutable_get(); - pb_get->set_max_versions(get.MaxVersions()); - pb_get->set_cache_blocks(get.CacheBlocks()); - pb_get->set_consistency(get.Consistency()); - - if (!get.Timerange().IsAllTime()) { - hbase::pb::TimeRange *pb_time_range = pb_get->mutable_time_range(); - pb_time_range->set_from(get.Timerange().MinTimeStamp()); - pb_time_range->set_to(get.Timerange().MaxTimeStamp()); - } - pb_get->set_row(get.Row()); - if (get.HasFamilies()) { - for (const auto &family : get.Family()) { - auto column = pb_get->add_column(); - column->set_family(family.first); - for (const auto &qualifier : family.second) { - column->add_qualifier(qualifier); - } - } - } - - if (get.filter() != nullptr) { - pb_get->set_allocated_filter(Filter::ToProto(*(get.filter())).release()); - } - - return pb_req; -} - -std::unique_ptr RequestConverter::ToScanRequest(const Scan &scan, - const std::string ®ion_name) { - auto pb_req = Request::scan(); - - auto pb_msg = std::static_pointer_cast(pb_req->req_msg()); - - RequestConverter::SetRegion(region_name, pb_msg->mutable_region()); - - auto pb_scan = pb_msg->mutable_scan(); - pb_scan->set_max_versions(scan.MaxVersions()); - pb_scan->set_cache_blocks(scan.CacheBlocks()); - pb_scan->set_reversed(scan.IsReversed()); - pb_scan->set_small(scan.IsSmall()); - pb_scan->set_caching(scan.Caching()); - pb_scan->set_start_row(scan.StartRow()); - pb_scan->set_stop_row(scan.StopRow()); - pb_scan->set_consistency(scan.Consistency()); - pb_scan->set_max_result_size(scan.MaxResultSize()); - pb_scan->set_allow_partial_results(scan.AllowPartialResults()); - pb_scan->set_load_column_families_on_demand(scan.LoadColumnFamiliesOnDemand()); - - if (!scan.Timerange().IsAllTime()) { - hbase::pb::TimeRange *pb_time_range = pb_scan->mutable_time_range(); - pb_time_range->set_from(scan.Timerange().MinTimeStamp()); - pb_time_range->set_to(scan.Timerange().MaxTimeStamp()); - } - - if (scan.HasFamilies()) { - for (const auto &family : scan.Family()) { - auto column = pb_scan->add_column(); - column->set_family(family.first); - for (const auto &qualifier : family.second) { - column->add_qualifier(qualifier); - } - } - } - - if (scan.filter() != nullptr) { - pb_scan->set_allocated_filter(Filter::ToProto(*(scan.filter())).release()); - } - - // TODO We will change this later. - pb_msg->set_client_handles_partials(false); - pb_msg->set_client_handles_heartbeats(false); - pb_msg->set_track_scan_metrics(false); - - return pb_req; -} -} /* namespace hbase */ diff --git hbase-native-client/core/request_converter.h hbase-native-client/core/request_converter.h deleted file mode 100644 index 57f08cc..0000000 --- hbase-native-client/core/request_converter.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. - * - */ - -#pragma once - -#include -#include -#include "connection/request.h" -#include "core/get.h" -#include "core/scan.h" -#include "if/HBase.pb.h" - -using hbase::pb::RegionSpecifier; -namespace hbase { - -/** - * RequestConverter class - * This class converts a Client side Get, Scan, Mutate operation to corresponding PB message. - */ -class RequestConverter { - public: - ~RequestConverter(); - - /** - * @brief Returns a Request object comprising of PB GetRequest created using - * passed 'get' - * @param get - Get object used for creating GetRequest - * @param region_name - table region - */ - static std::unique_ptr ToGetRequest(const Get &get, const std::string ®ion_name); - - /** - * @brief Returns a Request object comprising of PB ScanRequest created using - * passed 'scan' - * @param scan - Scan object used for creating ScanRequest - * @param region_name - table region - */ - static std::unique_ptr ToScanRequest(const Scan &scan, const std::string ®ion_name); - - private: - // Constructor not required. We have all static methods to create PB requests. - RequestConverter(); - - /** - * @brief fills region_specifier with region values. - * @param region_name - table region - * @param region_specifier - RegionSpecifier to be filled and passed in PB - * Request. - */ - static void SetRegion(const std::string ®ion_name, RegionSpecifier *region_specifier); -}; - -} /* namespace hbase */ diff --git hbase-native-client/core/response-converter.cc hbase-native-client/core/response-converter.cc new file mode 100644 index 0000000..7bb5e5d --- /dev/null +++ hbase-native-client/core/response-converter.cc @@ -0,0 +1,97 @@ +/* + * 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/response-converter.h" + +#include +#include + +#include "core/cell.h" + +using hbase::pb::GetResponse; +using hbase::pb::ScanResponse; + +namespace hbase { + +ResponseConverter::ResponseConverter() {} + +ResponseConverter::~ResponseConverter() {} + +std::unique_ptr ResponseConverter::FromGetResponse(const Response& resp) { + auto get_resp = std::static_pointer_cast(resp.resp_msg()); + + return ToResult(get_resp->result(), resp.cell_scanner()); +} + +std::unique_ptr ResponseConverter::ToResult( + const hbase::pb::Result& result, const std::unique_ptr& cell_scanner) { + std::vector> vcells; + for (auto cell : result.cell()) { + std::shared_ptr pcell = + std::make_shared(cell.row(), cell.family(), cell.qualifier(), cell.timestamp(), + cell.value(), static_cast(cell.cell_type())); + vcells.push_back(pcell); + } + + // iterate over the cells coming from rpc codec + if (cell_scanner != nullptr) { + while (cell_scanner->Advance()) { + vcells.push_back(cell_scanner->Current()); + } + // TODO: check associated cell count? + } + return std::make_unique(vcells, result.exists(), result.stale(), result.partial()); +} + +std::vector> ResponseConverter::FromScanResponse(const Response& resp) { + auto scan_resp = std::static_pointer_cast(resp.resp_msg()); + VLOG(3) << "FromScanResponse:" << scan_resp->ShortDebugString(); + int num_results = resp.cell_scanner() != nullptr ? scan_resp->cells_per_result_size() + : scan_resp->results_size(); + + std::vector> results{static_cast(num_results)}; + for (int i = 0; i < num_results; i++) { + if (resp.cell_scanner() != nullptr) { + // Cells are out in cellblocks. Group them up again as Results. How many to read at a + // time will be found in getCellsLength -- length here is how many Cells in the i'th Result + int num_cells = scan_resp->cells_per_result(i); + + std::vector> vcells; + while (resp.cell_scanner()->Advance()) { + vcells.push_back(resp.cell_scanner()->Current()); + } + // TODO: check associated cell count? + + if (vcells.size() != num_cells) { + std::string msg = "Results sent from server=" + std::to_string(num_results) + + ". But only got " + std::to_string(i) + + " results completely at client. Resetting the scanner to scan again."; + LOG(ERROR) << msg; + throw std::runtime_error(msg); + } + // TODO: handle partial results per Result by checking partial_flag_per_result + results[i] = std::make_unique(vcells, false, scan_resp->stale(), false); + } else { + results[i] = ToResult(scan_resp->results(i), resp.cell_scanner()); + } + } + + return results; +} +} /* namespace hbase */ diff --git hbase-native-client/core/response-converter.h hbase-native-client/core/response-converter.h new file mode 100644 index 0000000..759b1ce --- /dev/null +++ hbase-native-client/core/response-converter.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. + * + */ + +#pragma once + +#include +#include +#include "connection/response.h" +#include "core/result.h" +#include "if/Client.pb.h" +#include "serde/cell-scanner.h" + +namespace hbase { + +/** + * ResponseConverter class + * This class converts a PB Response to corresponding Result or other objects. + */ +class ResponseConverter { + public: + ~ResponseConverter(); + + static std::unique_ptr ToResult(const hbase::pb::Result& result, + const std::unique_ptr& cell_scanner); + + /** + * @brief Returns a Result object created by PB Message in passed Response object. + * @param resp - Response object having the PB message. + */ + static std::unique_ptr FromGetResponse(const Response& resp); + + static std::vector> FromScanResponse(const Response& resp); + + private: + // Constructor not required. We have all static methods to extract response from PB messages. + ResponseConverter(); +}; + +} /* namespace hbase */ diff --git hbase-native-client/core/response_converter.cc hbase-native-client/core/response_converter.cc deleted file mode 100644 index 2497306..0000000 --- hbase-native-client/core/response_converter.cc +++ /dev/null @@ -1,97 +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/response_converter.h" - -#include -#include - -#include "core/cell.h" - -using hbase::pb::GetResponse; -using hbase::pb::ScanResponse; - -namespace hbase { - -ResponseConverter::ResponseConverter() {} - -ResponseConverter::~ResponseConverter() {} - -std::unique_ptr ResponseConverter::FromGetResponse(const Response& resp) { - auto get_resp = std::static_pointer_cast(resp.resp_msg()); - - return ToResult(get_resp->result(), resp.cell_scanner()); -} - -std::unique_ptr ResponseConverter::ToResult( - const hbase::pb::Result& result, const std::unique_ptr& cell_scanner) { - std::vector> vcells; - for (auto cell : result.cell()) { - std::shared_ptr pcell = - std::make_shared(cell.row(), cell.family(), cell.qualifier(), cell.timestamp(), - cell.value(), static_cast(cell.cell_type())); - vcells.push_back(pcell); - } - - // iterate over the cells coming from rpc codec - if (cell_scanner != nullptr) { - while (cell_scanner->Advance()) { - vcells.push_back(cell_scanner->Current()); - } - // TODO: check associated cell count? - } - return std::make_unique(vcells, result.exists(), result.stale(), result.partial()); -} - -std::vector> ResponseConverter::FromScanResponse(const Response& resp) { - auto scan_resp = std::static_pointer_cast(resp.resp_msg()); - VLOG(3) << "FromScanResponse:" << scan_resp->ShortDebugString(); - int num_results = resp.cell_scanner() != nullptr ? scan_resp->cells_per_result_size() - : scan_resp->results_size(); - - std::vector> results{static_cast(num_results)}; - for (int i = 0; i < num_results; i++) { - if (resp.cell_scanner() != nullptr) { - // Cells are out in cellblocks. Group them up again as Results. How many to read at a - // time will be found in getCellsLength -- length here is how many Cells in the i'th Result - int num_cells = scan_resp->cells_per_result(i); - - std::vector> vcells; - while (resp.cell_scanner()->Advance()) { - vcells.push_back(resp.cell_scanner()->Current()); - } - // TODO: check associated cell count? - - if (vcells.size() != num_cells) { - std::string msg = "Results sent from server=" + std::to_string(num_results) + - ". But only got " + std::to_string(i) + - " results completely at client. Resetting the scanner to scan again."; - LOG(ERROR) << msg; - throw std::runtime_error(msg); - } - // TODO: handle partial results per Result by checking partial_flag_per_result - results[i] = std::make_unique(vcells, false, scan_resp->stale(), false); - } else { - results[i] = ToResult(scan_resp->results(i), resp.cell_scanner()); - } - } - - return results; -} -} /* namespace hbase */ diff --git hbase-native-client/core/response_converter.h hbase-native-client/core/response_converter.h deleted file mode 100644 index 759b1ce..0000000 --- hbase-native-client/core/response_converter.h +++ /dev/null @@ -1,55 +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. - * - */ - -#pragma once - -#include -#include -#include "connection/response.h" -#include "core/result.h" -#include "if/Client.pb.h" -#include "serde/cell-scanner.h" - -namespace hbase { - -/** - * ResponseConverter class - * This class converts a PB Response to corresponding Result or other objects. - */ -class ResponseConverter { - public: - ~ResponseConverter(); - - static std::unique_ptr ToResult(const hbase::pb::Result& result, - const std::unique_ptr& cell_scanner); - - /** - * @brief Returns a Result object created by PB Message in passed Response object. - * @param resp - Response object having the PB message. - */ - static std::unique_ptr FromGetResponse(const Response& resp); - - static std::vector> FromScanResponse(const Response& resp); - - private: - // Constructor not required. We have all static methods to extract response from PB messages. - ResponseConverter(); -}; - -} /* namespace hbase */ diff --git hbase-native-client/core/scan.h hbase-native-client/core/scan.h index 7e8c7bd..cedbe0a 100644 --- hbase-native-client/core/scan.h +++ hbase-native-client/core/scan.h @@ -25,7 +25,7 @@ #include #include #include "core/get.h" -#include "core/time_range.h" +#include "core/time-range.h" #include "if/Client.pb.h" namespace hbase { diff --git hbase-native-client/core/table.cc hbase-native-client/core/table.cc index ba4dc29..2ce8fcd 100644 --- hbase-native-client/core/table.cc +++ hbase-native-client/core/table.cc @@ -25,8 +25,8 @@ #include #include -#include "core/request_converter.h" -#include "core/response_converter.h" +#include "core/request-converter.h" +#include "core/response-converter.h" #include "if/Client.pb.h" #include "security/user.h" #include "serde/server-name.h" diff --git hbase-native-client/core/time-range-test.cc hbase-native-client/core/time-range-test.cc new file mode 100644 index 0000000..136ab54 --- /dev/null +++ hbase-native-client/core/time-range-test.cc @@ -0,0 +1,48 @@ +/* + * 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/time-range.h" + +#include +#include + +using namespace hbase; + +TEST(TimeRange, DefaultObject) { + TimeRange *timerange_def = nullptr; + ASSERT_NO_THROW(timerange_def = new TimeRange()); + + EXPECT_EQ(0, timerange_def->MinTimeStamp()); + EXPECT_EQ(std::numeric_limits::max(), timerange_def->MaxTimeStamp()); + EXPECT_NE(1000, timerange_def->MinTimeStamp()); + EXPECT_NE(2000, timerange_def->MaxTimeStamp()); + delete timerange_def; + timerange_def = nullptr; +} + +TEST(TimeRange, Exception) { + // Negative Min TS + ASSERT_THROW(TimeRange(-1000, 2000), std::runtime_error); + + // Negative Max TS + ASSERT_THROW(TimeRange(1000, -2000), std::runtime_error); + + // Min TS > Max TS + ASSERT_THROW(TimeRange(10000, 2000), std::runtime_error); +} diff --git hbase-native-client/core/time-range.cc hbase-native-client/core/time-range.cc new file mode 100644 index 0000000..e6b789b --- /dev/null +++ hbase-native-client/core/time-range.cc @@ -0,0 +1,73 @@ +/* + * 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/time-range.h" +#include +#include +#include + +namespace hbase { + +TimeRange::TimeRange() + : min_timestamp_(0L), max_timestamp_(std::numeric_limits::max()), all_time_(true) {} + +TimeRange::TimeRange(const TimeRange &tr) { + this->all_time_ = tr.all_time_; + this->max_timestamp_ = tr.max_timestamp_; + this->min_timestamp_ = tr.min_timestamp_; +} + +TimeRange &TimeRange::operator=(const TimeRange &tr) { + this->all_time_ = tr.all_time_; + this->max_timestamp_ = tr.max_timestamp_; + this->min_timestamp_ = tr.min_timestamp_; + return *this; +} + +TimeRange::~TimeRange() {} + +TimeRange::TimeRange(int64_t min_timestamp) { + this->min_timestamp_ = min_timestamp; + this->max_timestamp_ = std::numeric_limits::max(); + this->all_time_ = false; +} + +TimeRange::TimeRange(int64_t min_timestamp, int64_t max_timestamp) { + if (min_timestamp < 0 || max_timestamp < 0) { + throw std::runtime_error("Timestamp cannot be negative. min_timestamp: " + + std::to_string(min_timestamp) + ", max_timestamp:" + + std::to_string(max_timestamp)); + } + if (max_timestamp < min_timestamp) { + throw std::runtime_error("max_timestamp [" + std::to_string(max_timestamp) + + "] should be greater than min_timestamp [" + + std::to_string(min_timestamp) + "]"); + } + + this->min_timestamp_ = min_timestamp; + this->max_timestamp_ = max_timestamp; + this->all_time_ = false; +} + +int64_t TimeRange::MinTimeStamp() const { return this->min_timestamp_; } + +int64_t TimeRange::MaxTimeStamp() const { return this->max_timestamp_; } + +bool TimeRange::IsAllTime() const { return this->all_time_; } +} // namespace hbase diff --git hbase-native-client/core/time-range.h hbase-native-client/core/time-range.h new file mode 100644 index 0000000..d645ecd --- /dev/null +++ hbase-native-client/core/time-range.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. + * + */ + +#pragma once + +#include + +namespace hbase { +class TimeRange { + public: + /** + * @brief Default constructor. Represents interval [0, + * std::numeric_limits::max()) + * (allTime) + */ + TimeRange(); + TimeRange(const TimeRange &tr); + TimeRange &operator=(const TimeRange &tr); + /** + * @brief Represents interval [minStamp, std::numeric_limits::max()) + * @param minStamp the minimum timestamp value, inclusive + */ + explicit TimeRange(int64_t min_timestamp); + /** + * @brief Represents interval [minStamp, maxStamp) + * @param minStamp the minimum timestamp, inclusive + * @param maxStamp the maximum timestamp, exclusive + * @throws std::runtime_error if min_timestamp < 0 or max_timestamp < 0 or + * max_timestamp < min_timestamp + */ + TimeRange(int64_t min_timestamp, int64_t max_timestamp); + int64_t MinTimeStamp() const; + int64_t MaxTimeStamp() const; + bool IsAllTime() const; + ~TimeRange(); + + private: + int64_t min_timestamp_; + int64_t max_timestamp_; + bool all_time_; +}; +} // namespace hbase diff --git hbase-native-client/core/time_range-test.cc hbase-native-client/core/time_range-test.cc deleted file mode 100644 index 49cb359..0000000 --- hbase-native-client/core/time_range-test.cc +++ /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. - * - */ - -#include "core/time_range.h" - -#include -#include - -using namespace hbase; - -TEST(TimeRange, DefaultObject) { - TimeRange *timerange_def = nullptr; - ASSERT_NO_THROW(timerange_def = new TimeRange()); - - EXPECT_EQ(0, timerange_def->MinTimeStamp()); - EXPECT_EQ(std::numeric_limits::max(), timerange_def->MaxTimeStamp()); - EXPECT_NE(1000, timerange_def->MinTimeStamp()); - EXPECT_NE(2000, timerange_def->MaxTimeStamp()); - delete timerange_def; - timerange_def = nullptr; -} - -TEST(TimeRange, Exception) { - // Negative Min TS - ASSERT_THROW(TimeRange(-1000, 2000), std::runtime_error); - - // Negative Max TS - ASSERT_THROW(TimeRange(1000, -2000), std::runtime_error); - - // Min TS > Max TS - ASSERT_THROW(TimeRange(10000, 2000), std::runtime_error); -} diff --git hbase-native-client/core/time_range.cc hbase-native-client/core/time_range.cc deleted file mode 100644 index 04b70ec..0000000 --- hbase-native-client/core/time_range.cc +++ /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. - * - */ - -#include "core/time_range.h" -#include -#include -#include - -namespace hbase { - -TimeRange::TimeRange() - : min_timestamp_(0L), max_timestamp_(std::numeric_limits::max()), all_time_(true) {} - -TimeRange::TimeRange(const TimeRange &tr) { - this->all_time_ = tr.all_time_; - this->max_timestamp_ = tr.max_timestamp_; - this->min_timestamp_ = tr.min_timestamp_; -} - -TimeRange &TimeRange::operator=(const TimeRange &tr) { - this->all_time_ = tr.all_time_; - this->max_timestamp_ = tr.max_timestamp_; - this->min_timestamp_ = tr.min_timestamp_; - return *this; -} - -TimeRange::~TimeRange() {} - -TimeRange::TimeRange(int64_t min_timestamp) { - this->min_timestamp_ = min_timestamp; - this->max_timestamp_ = std::numeric_limits::max(); - this->all_time_ = false; -} - -TimeRange::TimeRange(int64_t min_timestamp, int64_t max_timestamp) { - if (min_timestamp < 0 || max_timestamp < 0) { - throw std::runtime_error("Timestamp cannot be negative. min_timestamp: " + - std::to_string(min_timestamp) + ", max_timestamp:" + - std::to_string(max_timestamp)); - } - if (max_timestamp < min_timestamp) { - throw std::runtime_error("max_timestamp [" + std::to_string(max_timestamp) + - "] should be greater than min_timestamp [" + - std::to_string(min_timestamp) + "]"); - } - - this->min_timestamp_ = min_timestamp; - this->max_timestamp_ = max_timestamp; - this->all_time_ = false; -} - -int64_t TimeRange::MinTimeStamp() const { return this->min_timestamp_; } - -int64_t TimeRange::MaxTimeStamp() const { return this->max_timestamp_; } - -bool TimeRange::IsAllTime() const { return this->all_time_; } -} // namespace hbase diff --git hbase-native-client/core/time_range.h hbase-native-client/core/time_range.h deleted file mode 100644 index d645ecd..0000000 --- hbase-native-client/core/time_range.h +++ /dev/null @@ -1,58 +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. - * - */ - -#pragma once - -#include - -namespace hbase { -class TimeRange { - public: - /** - * @brief Default constructor. Represents interval [0, - * std::numeric_limits::max()) - * (allTime) - */ - TimeRange(); - TimeRange(const TimeRange &tr); - TimeRange &operator=(const TimeRange &tr); - /** - * @brief Represents interval [minStamp, std::numeric_limits::max()) - * @param minStamp the minimum timestamp value, inclusive - */ - explicit TimeRange(int64_t min_timestamp); - /** - * @brief Represents interval [minStamp, maxStamp) - * @param minStamp the minimum timestamp, inclusive - * @param maxStamp the maximum timestamp, exclusive - * @throws std::runtime_error if min_timestamp < 0 or max_timestamp < 0 or - * max_timestamp < min_timestamp - */ - TimeRange(int64_t min_timestamp, int64_t max_timestamp); - int64_t MinTimeStamp() const; - int64_t MaxTimeStamp() const; - bool IsAllTime() const; - ~TimeRange(); - - private: - int64_t min_timestamp_; - int64_t max_timestamp_; - bool all_time_; -}; -} // namespace hbase diff --git hbase-native-client/test-util/mini-cluster.cc hbase-native-client/test-util/mini-cluster.cc index b40b689..88a091c 100644 --- hbase-native-client/test-util/mini-cluster.cc +++ hbase-native-client/test-util/mini-cluster.cc @@ -19,17 +19,11 @@ #include "test-util/mini-cluster.h" #include -#include +#include #include #include #include -#include "core/client.h" -#include "core/configuration.h" -#include "core/get.h" -#include "core/hbase_configuration_loader.h" -#include "core/result.h" -#include "core/table.h" -#include "serde/table-name.h" + using hbase::MiniCluster; diff --git hbase-native-client/test-util/mini-cluster.h hbase-native-client/test-util/mini-cluster.h index 9b8ca92..54842e1 100644 --- hbase-native-client/test-util/mini-cluster.h +++ hbase-native-client/test-util/mini-cluster.h @@ -18,17 +18,11 @@ */ #pragma once -#include #include -#include "core/client.h" -#include "core/configuration.h" -#include "core/get.h" -#include "core/hbase_configuration_loader.h" -#include "core/result.h" -#include "core/table.h" #include "jni.h" -#include "serde/table-name.h" + namespace hbase { + class MiniCluster { public: jobject StartCluster(int numRegionServers, std::string conf_path);