You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by zg...@apache.org on 2019/04/10 13:48:52 UTC
[hbase] 80/137: HBASE-16365 [C++] End to end Table::Put()
This is an automated email from the ASF dual-hosted git repository.
zghao pushed a commit to branch hbase-native-client
in repository https://gitbox.apache.org/repos/asf/hbase.git
commit ab47d94c061e02c7ec7f1a9ebf0023817f9c1d33
Author: Enis Soztutar <en...@apache.org>
AuthorDate: Wed Mar 29 16:53:45 2017 -0700
HBASE-16365 [C++] End to end Table::Put()
---
core/BUCK | 5 ++
core/async-rpc-retrying-test.cc | 5 +-
core/cell-test.cc | 175 +++++++++++++++++++---------------------
core/cell.cc | 22 +++++
core/cell.h | 2 +
core/client-test.cc | 119 ++++++++++++++++++---------
core/filter-test.cc | 18 +++--
core/get-test.cc | 14 ++--
core/mutation.h | 9 +--
core/put-test.cc | 135 +++++++++++++++++++++++++++++++
core/put.cc | 5 +-
core/raw-async-table.cc | 15 ++++
core/raw-async-table.h | 5 ++
core/request-converter.cc | 68 ++++++++++++++++
core/request-converter.h | 16 +++-
core/result-test.cc | 8 +-
core/result.cc | 22 +++++
core/result.h | 2 +
core/simple-client.cc | 124 ++++++++++++----------------
core/table.cc | 5 ++
core/table.h | 8 ++
test-util/mini-cluster.cc | 19 -----
test-util/mini-cluster.h | 3 -
test-util/test-util.cc | 6 +-
test-util/test-util.h | 2 -
25 files changed, 548 insertions(+), 264 deletions(-)
diff --git a/core/BUCK b/core/BUCK
index 03fc0fc..30c3390 100644
--- a/core/BUCK
+++ b/core/BUCK
@@ -130,6 +130,11 @@ cxx_test(
deps=[":core",],
run_test_separately=True,)
cxx_test(
+ name="put-test",
+ srcs=["put-test.cc",],
+ deps=[":core",],
+ run_test_separately=True,)
+cxx_test(
name="retry-test",
srcs=["async-rpc-retrying-test.cc",],
deps=[
diff --git a/core/async-rpc-retrying-test.cc b/core/async-rpc-retrying-test.cc
index 5086286..3ed6866 100644
--- a/core/async-rpc-retrying-test.cc
+++ b/core/async-rpc-retrying-test.cc
@@ -163,8 +163,6 @@ TEST(AsyncRpcRetryTest, TestGetBasic) {
test_util->StartMiniCluster(2);
test_util->CreateTable("t", "d");
- test_util->TablePut("t", "test2", "d", "2", "value2");
- test_util->TablePut("t", "test2", "d", "extra", "value for extra");
// Create TableName and Row to be fetched from HBase
auto tn = folly::to<hbase::pb::TableName>("t");
@@ -180,6 +178,9 @@ TEST(AsyncRpcRetryTest, TestGetBasic) {
auto table = client.Table(tn);
ASSERT_TRUE(table) << "Unable to get connection to Table.";
+ table->Put(Put{"test2"}.AddColumn("d", "2", "value2"));
+ table->Put(Put{"test2"}.AddColumn("d", "extra", "value for extra"));
+
/* init region location and rpc channel */
auto region_location = table->GetRegionLocation(row);
diff --git a/core/cell-test.cc b/core/cell-test.cc
index 2ec983b..efb835d 100644
--- a/core/cell-test.cc
+++ b/core/cell-test.cc
@@ -23,75 +23,65 @@
#include <gtest/gtest.h>
#include <memory>
-using namespace hbase;
-TEST(CellTest, CellFailureTest) {
- CellType cell_type = CellType::PUT;
- std::string row = "row";
- std::string family = "family";
- std::string column = "column";
- std::string value = "value";
+using hbase::Cell;
+using hbase::CellType;
+
+TEST(CellTest, Constructor) {
+ std::string row = "row-value";
+ std::string family = "family-value";
+ std::string column = "column-value";
+ std::string value = "value-value";
int64_t timestamp = std::numeric_limits<int64_t>::max();
- std::unique_ptr<Cell> cell(new Cell(row, family, column, timestamp, value, cell_type));
- if (cell.get()) {
- EXPECT_NE("row-value", cell.get()->Row());
- EXPECT_NE("family-value", cell.get()->Family());
- EXPECT_NE("column-value", cell.get()->Qualifier());
- EXPECT_NE("value-value", cell.get()->Value());
- EXPECT_NE(8975431260, cell.get()->Timestamp());
- EXPECT_NE(CellType::MAXIMUM, cell.get()->Type());
- }
+ CellType cell_type = CellType::PUT;
+
+ Cell cell{row, family, column, timestamp, value, cell_type};
+
+ EXPECT_EQ(row, cell.Row());
+ EXPECT_EQ(family, cell.Family());
+ EXPECT_EQ(column, cell.Qualifier());
+ EXPECT_EQ(value, cell.Value());
+ EXPECT_EQ(timestamp, cell.Timestamp());
+ EXPECT_EQ(cell_type, cell.Type());
}
-TEST(CellTest, CellSuceessTest) {
+TEST(CellTest, CopyConstructor) {
std::string row = "row-value";
std::string family = "family-value";
std::string column = "column-value";
std::string value = "value-value";
int64_t timestamp = std::numeric_limits<int64_t>::max();
CellType cell_type = CellType::PUT;
- const std::unique_ptr<Cell> cell(new Cell(row, family, column, timestamp, value, cell_type));
- if (cell.get()) {
- EXPECT_EQ(row, cell.get()->Row());
- EXPECT_EQ(family, cell.get()->Family());
- EXPECT_EQ(column, cell.get()->Qualifier());
- EXPECT_EQ(value, cell.get()->Value());
- EXPECT_EQ(timestamp, cell.get()->Timestamp());
- EXPECT_EQ(cell_type, cell.get()->Type());
- }
+
+ auto cell = std::make_unique<Cell>(row, family, column, timestamp, value, cell_type);
+ Cell cell2{*cell};
+ cell = nullptr;
+
+ EXPECT_EQ(row, cell2.Row());
+ EXPECT_EQ(family, cell2.Family());
+ EXPECT_EQ(column, cell2.Qualifier());
+ EXPECT_EQ(value, cell2.Value());
+ EXPECT_EQ(timestamp, cell2.Timestamp());
+ EXPECT_EQ(cell_type, cell2.Type());
}
-TEST(CellTest, MultipleCellsTest) {
- std::vector<const Cell *> cells;
- for (int i = 0; i < 5; i++) {
- std::string row = "row-value";
- std::string family = "family-value";
- std::string column = "column-value";
- std::string value = "value-value";
- int64_t timestamp = std::numeric_limits<int64_t>::max();
- row += std::to_string(i);
- value += std::to_string(i);
- CellType cell_type = CellType::PUT;
- const Cell *cell = new Cell(row, family, column, timestamp, value, cell_type);
- cells.push_back(cell);
- }
- int i = 0;
- for (const auto cell : cells) {
- std::string row = "row-value";
- std::string value = "value-value";
- row += std::to_string(i);
- value += std::to_string(i);
- EXPECT_EQ(row, cell->Row());
- EXPECT_EQ("family-value", cell->Family());
- EXPECT_EQ("column-value", cell->Qualifier());
- EXPECT_EQ(value, cell->Value());
- EXPECT_EQ(std::numeric_limits<int64_t>::max(), cell->Timestamp());
- EXPECT_EQ(CellType::PUT, cell->Type());
- i += 1;
- }
- for (const auto cell : cells) {
- delete cell;
- }
- cells.clear();
+TEST(CellTest, CopyAssignment) {
+ std::string row = "row-value";
+ std::string family = "family-value";
+ std::string column = "column-value";
+ std::string value = "value-value";
+ int64_t timestamp = std::numeric_limits<int64_t>::max();
+ CellType cell_type = CellType::PUT;
+
+ auto cell = std::make_unique<Cell>(row, family, column, timestamp, value, cell_type);
+ Cell cell2 = *cell;
+ cell = nullptr;
+
+ EXPECT_EQ(row, cell2.Row());
+ EXPECT_EQ(family, cell2.Family());
+ EXPECT_EQ(column, cell2.Qualifier());
+ EXPECT_EQ(value, cell2.Value());
+ EXPECT_EQ(timestamp, cell2.Timestamp());
+ EXPECT_EQ(cell_type, cell2.Type());
}
TEST(CellTest, CellRowTest) {
@@ -101,15 +91,14 @@ TEST(CellTest, CellRowTest) {
std::string value = "";
int64_t timestamp = std::numeric_limits<int64_t>::max();
CellType cell_type = CellType::PUT;
- std::unique_ptr<Cell> cell(new Cell(row, family, column, timestamp, value, cell_type));
- if (cell.get()) {
- EXPECT_EQ(row, cell.get()->Row());
- EXPECT_EQ(family, cell.get()->Family());
- EXPECT_EQ(column, cell.get()->Qualifier());
- EXPECT_EQ(value, cell.get()->Value());
- EXPECT_EQ(timestamp, cell.get()->Timestamp());
- EXPECT_EQ(cell_type, cell.get()->Type());
- }
+ Cell cell{row, family, column, timestamp, value, cell_type};
+
+ EXPECT_EQ(row, cell.Row());
+ EXPECT_EQ(family, cell.Family());
+ EXPECT_EQ(column, cell.Qualifier());
+ EXPECT_EQ(value, cell.Value());
+ EXPECT_EQ(timestamp, cell.Timestamp());
+ EXPECT_EQ(cell_type, cell.Type());
}
TEST(CellTest, CellRowFamilyTest) {
@@ -119,15 +108,14 @@ TEST(CellTest, CellRowFamilyTest) {
std::string value = "";
int64_t timestamp = std::numeric_limits<int64_t>::max();
CellType cell_type = CellType::PUT;
- const std::unique_ptr<Cell> cell(new Cell(row, family, column, timestamp, value, cell_type));
- if (cell.get()) {
- EXPECT_EQ(row, cell.get()->Row());
- EXPECT_EQ(family, cell.get()->Family());
- EXPECT_EQ(column, cell.get()->Qualifier());
- EXPECT_EQ(value, cell.get()->Value());
- EXPECT_EQ(timestamp, cell.get()->Timestamp());
- EXPECT_EQ(cell_type, cell.get()->Type());
- }
+ Cell cell{row, family, column, timestamp, value, cell_type};
+
+ EXPECT_EQ(row, cell.Row());
+ EXPECT_EQ(family, cell.Family());
+ EXPECT_EQ(column, cell.Qualifier());
+ EXPECT_EQ(value, cell.Value());
+ EXPECT_EQ(timestamp, cell.Timestamp());
+ EXPECT_EQ(cell_type, cell.Type());
}
TEST(CellTest, CellRowFamilyValueTest) {
@@ -137,15 +125,15 @@ TEST(CellTest, CellRowFamilyValueTest) {
std::string value = "only-value";
int64_t timestamp = std::numeric_limits<int64_t>::max();
CellType cell_type = CellType::PUT;
- const std::unique_ptr<Cell> cell(new Cell(row, family, column, timestamp, value, cell_type));
- if (cell.get()) {
- EXPECT_EQ(row, cell.get()->Row());
- EXPECT_EQ(family, cell.get()->Family());
- EXPECT_EQ(column, cell.get()->Qualifier());
- EXPECT_EQ(value, cell.get()->Value());
- EXPECT_EQ(timestamp, cell.get()->Timestamp());
- EXPECT_EQ(cell_type, cell.get()->Type());
- }
+
+ Cell cell{row, family, column, timestamp, value, cell_type};
+
+ EXPECT_EQ(row, cell.Row());
+ EXPECT_EQ(family, cell.Family());
+ EXPECT_EQ(column, cell.Qualifier());
+ EXPECT_EQ(value, cell.Value());
+ EXPECT_EQ(timestamp, cell.Timestamp());
+ EXPECT_EQ(cell_type, cell.Type());
}
TEST(CellTest, CellRowFamilyColumnValueTest) {
@@ -155,15 +143,14 @@ TEST(CellTest, CellRowFamilyColumnValueTest) {
std::string value = "only-value";
int64_t timestamp = std::numeric_limits<int64_t>::max();
CellType cell_type = CellType::PUT;
- std::unique_ptr<Cell> cell(new Cell(row, family, column, timestamp, value, cell_type));
- if (cell.get()) {
- EXPECT_EQ(row, cell.get()->Row());
- EXPECT_EQ(family, cell.get()->Family());
- EXPECT_EQ(column, cell.get()->Qualifier());
- EXPECT_EQ(value, cell.get()->Value());
- EXPECT_EQ(timestamp, cell.get()->Timestamp());
- EXPECT_EQ(cell_type, cell.get()->Type());
- }
+ Cell cell{row, family, column, timestamp, value, cell_type};
+
+ EXPECT_EQ(row, cell.Row());
+ EXPECT_EQ(family, cell.Family());
+ EXPECT_EQ(column, cell.Qualifier());
+ EXPECT_EQ(value, cell.Value());
+ EXPECT_EQ(timestamp, cell.Timestamp());
+ EXPECT_EQ(cell_type, cell.Type());
}
TEST(CellTest, CellDebugString) {
diff --git a/core/cell.cc b/core/cell.cc
index 14a8014..24788ab 100644
--- a/core/cell.cc
+++ b/core/cell.cc
@@ -19,6 +19,7 @@
#include "core/cell.h"
#include <climits>
+#include <limits>
#include <stdexcept>
#include "folly/Conv.h"
@@ -40,6 +41,27 @@ Cell::Cell(const std::string &row, const std::string &family, const std::string
if (0 >= timestamp) throw std::runtime_error("Timestamp should be greater than 0");
}
+Cell::Cell(const Cell &cell)
+ : row_(cell.row_),
+ family_(cell.family_),
+ qualifier_(cell.qualifier_),
+ timestamp_(cell.timestamp_),
+ cell_type_(cell.cell_type_),
+ value_(cell.value_),
+ sequence_id_(cell.sequence_id_) {}
+
+Cell &Cell::operator=(const Cell &cell) {
+ row_ = cell.row_;
+ family_ = cell.family_;
+ qualifier_ = cell.qualifier_;
+ timestamp_ = cell.timestamp_;
+ cell_type_ = cell.cell_type_;
+ value_ = cell.value_;
+ sequence_id_ = cell.sequence_id_;
+
+ return *this;
+}
+
Cell::~Cell() {}
const std::string &Cell::Row() const { return row_; }
diff --git a/core/cell.h b/core/cell.h
index c062e45..acedd96 100644
--- a/core/cell.h
+++ b/core/cell.h
@@ -38,6 +38,8 @@ class Cell {
public:
Cell(const std::string &row, const std::string &family, const std::string &qualifier,
const int64_t timestamp, const std::string &value, const hbase::CellType &cell_type);
+ Cell(const Cell &cell);
+ Cell &operator=(const Cell &cell);
virtual ~Cell();
const std::string &Row() const;
const std::string &Family() const;
diff --git a/core/client-test.cc b/core/client-test.cc
index 184a6a7..ff4879a 100644
--- a/core/client-test.cc
+++ b/core/client-test.cc
@@ -17,24 +17,47 @@
*
*/
-#include "core/client.h"
#include <gtest/gtest.h>
+
+#include "core/cell.h"
+#include "core/client.h"
#include "core/configuration.h"
#include "core/get.h"
#include "core/hbase-configuration-loader.h"
+#include "core/put.h"
#include "core/result.h"
#include "core/table.h"
#include "serde/table-name.h"
#include "test-util/test-util.h"
+using hbase::Cell;
+using hbase::Configuration;
+using hbase::Get;
+using hbase::Put;
+using hbase::Table;
+using hbase::TestUtil;
+
class ClientTest : public ::testing::Test {
public:
- const static std::string kDefHBaseConfPath;
-
- const static std::string kHBaseDefaultXml;
- const static std::string kHBaseSiteXml;
-
- const static std::string kHBaseXmlData;
+ static const constexpr char *kDefHBaseConfPath = "./build/test-data/client-test/conf/";
+ static const constexpr char *kHBaseDefaultXml = "hbase-default.xml";
+ static const constexpr char *kHBaseSiteXml = "hbase-site.xml";
+ static const constexpr char *kHBaseXmlData =
+ "<?xml version=\"1.0\"?>\n<?xml-stylesheet type=\"text/xsl\" "
+ "href=\"configuration.xsl\"?>\n<!--\n/**\n *\n * Licensed to the Apache "
+ "Software Foundation (ASF) under one\n * or more contributor license "
+ "agreements. See the NOTICE file\n * distributed with this work for "
+ "additional information\n * regarding copyright ownership. The ASF "
+ "licenses this file\n * to you under the Apache License, Version 2.0 "
+ "(the\n * \"License\"); you may not use this file except in compliance\n * "
+ "with the License. You may obtain a copy of the License at\n *\n * "
+ "http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by "
+ "applicable law or agreed to in writing, software\n * distributed under "
+ "the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES "
+ "OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License "
+ "for the specific language governing permissions and\n * limitations under "
+ "the License.\n "
+ "*/\n-->\n<configuration>\n\n</configuration>";
static void WriteDataToFile(const std::string &file, const std::string &xml_data) {
std::ofstream hbase_conf;
@@ -55,7 +78,7 @@ class ClientTest : public ::testing::Test {
// Creating Empty Config Files so that we dont get a Configuration exception @Client
CreateHBaseConf(kDefHBaseConfPath, kHBaseDefaultXml, kHBaseXmlData);
// the hbase-site.xml would be persisted by MiniCluster
- setenv("HBASE_CONF", kDefHBaseConfPath.c_str(), 1);
+ setenv("HBASE_CONF", kDefHBaseConfPath, 1);
}
static std::unique_ptr<hbase::TestUtil> test_util;
@@ -67,28 +90,6 @@ class ClientTest : public ::testing::Test {
};
std::unique_ptr<hbase::TestUtil> ClientTest::test_util = nullptr;
-const std::string ClientTest::kDefHBaseConfPath("./build/test-data/client-test/conf/");
-
-const std::string ClientTest::kHBaseDefaultXml("hbase-default.xml");
-const std::string ClientTest::kHBaseSiteXml("hbase-site.xml");
-
-const std::string ClientTest::kHBaseXmlData(
- "<?xml version=\"1.0\"?>\n<?xml-stylesheet type=\"text/xsl\" "
- "href=\"configuration.xsl\"?>\n<!--\n/**\n *\n * Licensed to the Apache "
- "Software Foundation (ASF) under one\n * or more contributor license "
- "agreements. See the NOTICE file\n * distributed with this work for "
- "additional information\n * regarding copyright ownership. The ASF "
- "licenses this file\n * to you under the Apache License, Version 2.0 "
- "(the\n * \"License\"); you may not use this file except in compliance\n * "
- "with the License. You may obtain a copy of the License at\n *\n * "
- "http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by "
- "applicable law or agreed to in writing, software\n * distributed under "
- "the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES "
- "OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License "
- "for the specific language governing permissions and\n * limitations under "
- "the License.\n "
- "*/\n-->\n<configuration>\n\n</configuration>");
-
TEST_F(ClientTest, EmptyConfigurationPassedToClient) { ASSERT_ANY_THROW(hbase::Client client); }
TEST_F(ClientTest, ConfigurationPassedToClient) {
@@ -114,18 +115,13 @@ TEST_F(ClientTest, DefaultConfiguration) {
client.Close();
}
-TEST_F(ClientTest, Get) {
+TEST_F(ClientTest, PutGet) {
// Using TestUtil to populate test data
ClientTest::test_util->CreateTable("t", "d");
- ClientTest::test_util->TablePut("t", "test2", "d", "2", "value2");
- ClientTest::test_util->TablePut("t", "test2", "d", "extra", "value for extra");
// Create TableName and Row to be fetched from HBase
auto tn = folly::to<hbase::pb::TableName>("t");
- auto row = "test2";
-
- // Get to be performed on above HBase Table
- hbase::Get get(row);
+ auto row = "test1";
// Create a client
hbase::Client client(*ClientTest::test_util->conf());
@@ -134,13 +130,18 @@ TEST_F(ClientTest, Get) {
auto table = client.Table(tn);
ASSERT_TRUE(table) << "Unable to get connection to Table.";
+ // Perform Puts
+ table->Put(Put{"test1"}.AddColumn("d", "1", "value1"));
+ table->Put(Put{"test1"}.AddColumn("d", "extra", "value for extra"));
+
// Perform the Get
+ hbase::Get get(row);
auto result = table->Get(get);
// Test the values, should be same as in put executed on hbase shell
ASSERT_TRUE(!result->IsEmpty()) << "Result shouldn't be empty.";
- EXPECT_EQ("test2", result->Row());
- EXPECT_EQ("value2", *(result->Value("d", "2")));
+ EXPECT_EQ("test1", result->Row());
+ EXPECT_EQ("value1", *(result->Value("d", "1")));
EXPECT_EQ("value for extra", *(result->Value("d", "extra")));
table->Close();
@@ -150,7 +151,7 @@ TEST_F(ClientTest, Get) {
TEST_F(ClientTest, GetForNonExistentTable) {
// Create TableName and Row to be fetched from HBase
auto tn = folly::to<hbase::pb::TableName>("t_not_exists");
- auto row = "test2";
+ auto row = "test1";
// Get to be performed on above HBase Table
hbase::Get get(row);
@@ -194,3 +195,41 @@ TEST_F(ClientTest, GetForNonExistentRow) {
table->Close();
client.Close();
}
+
+TEST_F(ClientTest, PutsWithTimestamp) {
+ // Using TestUtil to populate test data
+ ClientTest::test_util->CreateTable("t_puts_with_timestamp", "d");
+
+ // Create TableName and Row to be fetched from HBase
+ auto tn = folly::to<hbase::pb::TableName>("t_puts_with_timestamp");
+ auto row = "test1";
+
+ // Create a client
+ hbase::Client client(*ClientTest::test_util->conf());
+
+ // Get connection to HBase Table
+ auto table = client.Table(tn);
+ ASSERT_TRUE(table) << "Unable to get connection to Table.";
+
+ int64_t ts = 42;
+ // Perform Puts
+ table->Put(Put{"test1"}.AddColumn("d", "1", ts, "value1"));
+ auto cell =
+ std::make_unique<Cell>("test1", "d", "extra", ts, "value for extra", hbase::CellType::PUT);
+ table->Put(Put{"test1"}.Add(std::move(cell)));
+
+ // Perform the Get
+ hbase::Get get(row);
+ auto result = table->Get(get);
+
+ // Test the values, should be same as in put executed on hbase shell
+ ASSERT_TRUE(!result->IsEmpty()) << "Result shouldn't be empty.";
+ EXPECT_EQ("test1", result->Row());
+ EXPECT_EQ("value1", *(result->Value("d", "1")));
+ EXPECT_EQ("value for extra", *(result->Value("d", "extra")));
+ EXPECT_EQ(ts, result->ColumnLatestCell("d", "1")->Timestamp());
+ EXPECT_EQ(ts, result->ColumnLatestCell("d", "extra")->Timestamp());
+
+ table->Close();
+ client.Close();
+}
diff --git a/core/filter-test.cc b/core/filter-test.cc
index 40081cc..f401698 100644
--- a/core/filter-test.cc
+++ b/core/filter-test.cc
@@ -21,6 +21,7 @@
#include "core/client.h"
#include "core/configuration.h"
#include "core/get.h"
+#include "core/put.h"
#include "core/result.h"
#include "core/table.h"
#include "if/Comparator.pb.h"
@@ -30,6 +31,7 @@
using hbase::Configuration;
using hbase::Get;
+using hbase::Put;
using hbase::FilterFactory;
using hbase::Table;
using hbase::TestUtil;
@@ -57,9 +59,6 @@ std::unique_ptr<TestUtil> FilterTest::test_util_ = nullptr;
TEST_F(FilterTest, GetWithColumnPrefixFilter) {
// write row1 with 3 columns (column_1, column_2, and foo_column)
FilterTest::test_util_->CreateTable("t", "d");
- FilterTest::test_util_->TablePut("t", "row1", "d", "column_1", "value1");
- FilterTest::test_util_->TablePut("t", "row1", "d", "column_2", "value2");
- FilterTest::test_util_->TablePut("t", "row1", "d", "foo_column", "value3");
// Create TableName and Row to be fetched from HBase
auto tn = folly::to<hbase::pb::TableName>("t");
@@ -75,11 +74,13 @@ TEST_F(FilterTest, GetWithColumnPrefixFilter) {
// Create a client
hbase::Client client(*(FilterTest::test_util_->conf()));
-
- // Get connection to HBase Table
auto table = client.Table(tn);
ASSERT_TRUE(table) << "Unable to get connection to Table.";
+ table->Put(Put{"row1"}.AddColumn("d", "column_1", "value1"));
+ table->Put(Put{"row1"}.AddColumn("d", "column_2", "value2"));
+ table->Put(Put{"row1"}.AddColumn("d", "foo_column", "value3"));
+
// Perform the Get
auto result_all = table->Get(get_all);
auto result_one = table->Get(get_one);
@@ -106,9 +107,6 @@ TEST_F(FilterTest, GetWithColumnPrefixFilter) {
TEST_F(FilterTest, GetWithQualifierFilter) {
// write row1 with 3 columns (a,b,c)
FilterTest::test_util_->CreateTable("t1", "d");
- FilterTest::test_util_->TablePut("t1", "row1", "d", "a", "value1");
- FilterTest::test_util_->TablePut("t1", "row1", "d", "b", "value2");
- FilterTest::test_util_->TablePut("t1", "row1", "d", "c", "value3");
// Create TableName and Row to be fetched from HBase
auto tn = folly::to<hbase::pb::TableName>("t1");
@@ -126,6 +124,10 @@ TEST_F(FilterTest, GetWithQualifierFilter) {
auto table = client.Table(tn);
ASSERT_TRUE(table) << "Unable to get connection to Table.";
+ table->Put(Put{"row1"}.AddColumn("d", "a", "value1"));
+ table->Put(Put{"row1"}.AddColumn("d", "b", "value2"));
+ table->Put(Put{"row1"}.AddColumn("d", "c", "value3"));
+
// Perform the Get
auto result = table->Get(get);
diff --git a/core/get-test.cc b/core/get-test.cc
index fafff39..6127e23 100644
--- a/core/get-test.cc
+++ b/core/get-test.cc
@@ -17,12 +17,15 @@
*
*/
+#include "core/cell.h"
#include "core/get.h"
#include <glog/logging.h>
#include <gtest/gtest.h>
+using hbase::Cell;
using hbase::Get;
+
const int NUMBER_OF_GETS = 5;
void CheckFamilies(Get &get) {
@@ -199,21 +202,16 @@ TEST(Get, SingleGet) {
}
TEST(Get, MultiGet) {
- std::vector<Get *> gets;
+ std::vector<std::unique_ptr<Get>> gets;
for (int i = 0; i < NUMBER_OF_GETS; i++) {
std::string row_str = "row-test";
row_str += std::to_string(i);
- Get *get = new Get(row_str);
+ auto get = std::make_unique<Get>(row_str);
GetMethods(*get, row_str);
- gets.push_back(get);
+ gets.push_back(std::move(get));
}
EXPECT_EQ(NUMBER_OF_GETS, gets.size());
-
- for (const auto &get : gets) {
- delete get;
- }
- gets.clear();
}
TEST(Get, Exception) {
diff --git a/core/mutation.h b/core/mutation.h
index 83392e1..5e0381b 100644
--- a/core/mutation.h
+++ b/core/mutation.h
@@ -65,11 +65,6 @@ class Mutation: public Row {
}
/**
- * @brief Returns the row for this operation
- */
- const std::string& row() const;
-
- /**
* @brief Returns true if family map is non empty false otherwise
*/
bool HasFamilies() const;
@@ -85,8 +80,10 @@ class Mutation: public Row {
*/
Mutation& SetDurability(pb::MutationProto_Durability durability);
- protected:
+ public:
static const constexpr int64_t kLatestTimestamp = std::numeric_limits<int64_t>::max();
+
+ protected:
std::map<std::string, std::vector<std::unique_ptr<Cell>>> family_map_;
pb::MutationProto_Durability durability_ =
hbase::pb::MutationProto_Durability::MutationProto_Durability_USE_DEFAULT;
diff --git a/core/put-test.cc b/core/put-test.cc
new file mode 100644
index 0000000..d4ed00a
--- /dev/null
+++ b/core/put-test.cc
@@ -0,0 +1,135 @@
+/*
+ * 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 <glog/logging.h>
+#include <gtest/gtest.h>
+
+#include "core/mutation.h"
+#include "core/put.h"
+#include "utils/time-util.h"
+
+using hbase::Put;
+using hbase::Cell;
+using hbase::CellType;
+using hbase::Mutation;
+using hbase::TimeUtil;
+
+const constexpr int64_t Mutation::kLatestTimestamp;
+
+TEST(Put, Row) {
+ Put put{"foo"};
+ EXPECT_EQ("foo", put.row());
+}
+
+TEST(Put, Durability) {
+ Put put{"row"};
+ EXPECT_EQ(hbase::pb::MutationProto_Durability_USE_DEFAULT, put.Durability());
+
+ auto skipWal = hbase::pb::MutationProto_Durability_SKIP_WAL;
+ put.SetDurability(skipWal);
+ EXPECT_EQ(skipWal, put.Durability());
+}
+
+TEST(Put, Timestamp) {
+ Put put{"row"};
+
+ // test default timestamp
+ EXPECT_EQ(Mutation::kLatestTimestamp, put.TimeStamp());
+
+ // set custom timestamp
+ auto ts = TimeUtil::ToMillis(TimeUtil::GetNowNanos());
+ put.SetTimeStamp(ts);
+ EXPECT_EQ(ts, put.TimeStamp());
+
+ // Add a column with custom timestamp
+ put.AddColumn("f", "q", "v");
+ auto &cell = put.FamilyMap().at("f")[0];
+ EXPECT_EQ(ts, cell->Timestamp());
+}
+
+TEST(Put, HasFamilies) {
+ Put put{"row"};
+
+ EXPECT_EQ(false, put.HasFamilies());
+
+ put.AddColumn("f", "q", "v");
+ EXPECT_EQ(true, put.HasFamilies());
+}
+
+TEST(Put, Add) {
+ CellType cell_type = CellType::PUT;
+ std::string row = "row";
+ std::string family = "family";
+ std::string column = "column";
+ std::string value = "value";
+ int64_t timestamp = std::numeric_limits<int64_t>::max();
+ auto cell = std::make_unique<Cell>(row, family, column, timestamp, value, cell_type);
+
+ // add first cell
+ Put put{"row"};
+ put.Add(std::move(cell));
+ EXPECT_EQ(1, put.FamilyMap().size());
+ EXPECT_EQ(1, put.FamilyMap().at(family).size());
+
+ // add a non-matching row
+ auto cell2 = std::make_unique<Cell>(row, family, column, timestamp, value, cell_type);
+ Put put2{"foo"};
+ ASSERT_THROW(put2.Add(std::move(cell2)), std::runtime_error); // rows don't match
+
+ // add a second cell with same family
+ auto cell3 = std::make_unique<Cell>(row, family, "column-2", timestamp, value, cell_type);
+ put.Add(std::move(cell3));
+ EXPECT_EQ(1, put.FamilyMap().size());
+ EXPECT_EQ(2, put.FamilyMap().at(family).size());
+
+ // add a cell to a different family
+ auto cell4 = std::make_unique<Cell>(row, "family-2", "column-2", timestamp, value, cell_type);
+ put.Add(std::move(cell4));
+ EXPECT_EQ(2, put.FamilyMap().size());
+ EXPECT_EQ(1, put.FamilyMap().at("family-2").size());
+}
+
+TEST(Put, AddColumn) {
+ std::string row = "row";
+ std::string family = "family";
+ std::string column = "column";
+ std::string value = "value";
+
+ Put put{"row"};
+ put.AddColumn(family, column, value);
+ EXPECT_EQ(1, put.FamilyMap().size());
+ EXPECT_EQ(1, put.FamilyMap().at(family).size());
+
+ // add a second cell with same family
+ put.AddColumn(family, "column-2", value);
+ EXPECT_EQ(1, put.FamilyMap().size());
+ EXPECT_EQ(2, put.FamilyMap().at(family).size());
+
+ // add a cell to a different family
+ put.AddColumn("family-2", column, value);
+ EXPECT_EQ(2, put.FamilyMap().size());
+ EXPECT_EQ(1, put.FamilyMap().at("family-2").size());
+
+ // use the AddColumn overload
+ auto ts = TimeUtil::ToMillis(TimeUtil::GetNowNanos());
+ put.AddColumn(family, column, ts, value);
+ EXPECT_EQ(2, put.FamilyMap().size());
+ EXPECT_EQ(3, put.FamilyMap().at(family).size());
+ auto &cell = put.FamilyMap().at(family)[2];
+ EXPECT_EQ(ts, cell->Timestamp());
+}
diff --git a/core/put.cc b/core/put.cc
index b81051e..bb20c5c 100644
--- a/core/put.cc
+++ b/core/put.cc
@@ -24,6 +24,7 @@
#include <algorithm>
#include <limits>
#include <stdexcept>
+#include <utility>
namespace hbase {
@@ -35,7 +36,7 @@ namespace hbase {
*/
Put& Put::AddColumn(const std::string& family, const std::string& qualifier,
const std::string& value) {
- return AddColumn(family, qualifier, kLatestTimestamp, value);
+ return AddColumn(family, qualifier, timestamp_, value);
}
/**
@@ -57,7 +58,7 @@ Put& Put::AddColumn(const std::string& family, const std::string& qualifier, int
Put& Put::Add(std::unique_ptr<Cell> cell) {
if (cell->Row() != row_) {
- throw std::runtime_error("The row in" + cell->DebugString() +
+ throw std::runtime_error("The row in " + cell->DebugString() +
" doesn't match the original one " + row_);
}
diff --git a/core/raw-async-table.cc b/core/raw-async-table.cc
index 9a680ed..2bc9f36 100644
--- a/core/raw-async-table.cc
+++ b/core/raw-async-table.cc
@@ -76,4 +76,19 @@ Future<std::shared_ptr<Result>> RawAsyncTable::Get(const hbase::Get& get) {
return caller->Call().then([caller](const auto r) { return r; });
}
+Future<Unit> RawAsyncTable::Put(const hbase::Put& put) {
+ auto caller =
+ CreateCallerBuilder<Unit>(put.row(), connection_conf_->write_rpc_timeout())
+ ->action([=, &put](std::shared_ptr<hbase::HBaseRpcController> controller,
+ std::shared_ptr<hbase::RegionLocation> loc,
+ std::shared_ptr<hbase::RpcClient> rpc_client) -> folly::Future<Unit> {
+ return Call<hbase::Put, hbase::Request, hbase::Response, Unit>(
+ rpc_client, controller, loc, put, &hbase::RequestConverter::ToMutateRequest,
+ [](const Response& r) -> Unit { return folly::unit; });
+ })
+ ->Build();
+
+ return caller->Call().then([caller](const auto r) { return r; });
+}
+
} /* namespace hbase */
diff --git a/core/raw-async-table.h b/core/raw-async-table.h
index bbdc6bd..978a2b8 100644
--- a/core/raw-async-table.h
+++ b/core/raw-async-table.h
@@ -19,6 +19,7 @@
#pragma once
#include <folly/futures/Future.h>
+#include <folly/futures/Unit.h>
#include <chrono>
#include <memory>
@@ -29,9 +30,11 @@
#include "core/async-rpc-retrying-caller.h"
#include "core/connection-configuration.h"
#include "core/get.h"
+#include "core/put.h"
#include "core/result.h"
using folly::Future;
+using folly::Unit;
using hbase::pb::TableName;
using std::chrono::nanoseconds;
using std::chrono::milliseconds;
@@ -52,6 +55,8 @@ class RawAsyncTable {
virtual ~RawAsyncTable() = default;
Future<std::shared_ptr<Result>> Get(const hbase::Get& get);
+
+ Future<Unit> Put(const hbase::Put& put);
void Close() {}
private:
diff --git a/core/request-converter.cc b/core/request-converter.cc
index c40a56e..4c12ee7 100644
--- a/core/request-converter.cc
+++ b/core/request-converter.cc
@@ -18,6 +18,9 @@
*/
#include "core/request-converter.h"
+
+#include <folly/Conv.h>
+
#include <utility>
#include "if/Client.pb.h"
@@ -152,4 +155,69 @@ std::unique_ptr<hbase::pb::Get> RequestConverter::ToGet(const Get &get) {
}
return pb_get;
}
+
+std::unique_ptr<MutationProto> RequestConverter::ToMutation(const MutationType type,
+ const Mutation &mutation,
+ const int64_t nonce) {
+ auto pb_mut = std::make_unique<MutationProto>();
+ pb_mut->set_row(mutation.row());
+ pb_mut->set_mutate_type(type);
+ pb_mut->set_durability(mutation.Durability());
+ pb_mut->set_timestamp(mutation.TimeStamp());
+ // TODO: set attributes from the mutation (key value pairs).
+
+ if (nonce > 0) {
+ pb_mut->set_nonce(nonce);
+ }
+
+ for (const auto &family : mutation.FamilyMap()) {
+ for (const auto &cell : family.second) {
+ auto column = pb_mut->add_column_value();
+ column->set_family(cell->Family());
+ auto qual = column->add_qualifier_value();
+ qual->set_qualifier(cell->Qualifier());
+ qual->set_timestamp(cell->Timestamp());
+ auto cell_type = cell->Type();
+ if (type == pb::MutationProto_MutationType_DELETE ||
+ (type == pb::MutationProto_MutationType_PUT && IsDelete(cell_type))) {
+ qual->set_delete_type(ToDeleteType(cell_type));
+ }
+
+ qual->set_value(cell->Value());
+ }
+ }
+ return std::move(pb_mut);
+}
+
+DeleteType RequestConverter::ToDeleteType(const CellType type) {
+ switch (type) {
+ case DELETE:
+ return pb::MutationProto_DeleteType_DELETE_ONE_VERSION;
+ case DELETE_COLUMN:
+ return pb::MutationProto_DeleteType_DELETE_MULTIPLE_VERSIONS;
+ case DELETE_FAMILY:
+ return pb::MutationProto_DeleteType_DELETE_FAMILY;
+ case DELETE_FAMILY_VERSION:
+ return pb::MutationProto_DeleteType_DELETE_FAMILY_VERSION;
+ default:
+ throw std::runtime_error("Unknown delete type: " + folly::to<std::string>(type));
+ }
+}
+
+bool RequestConverter::IsDelete(const CellType type) {
+ return CellType::DELETE <= type && type <= CellType::DELETE_FAMILY;
+}
+
+std::unique_ptr<Request> RequestConverter::ToMutateRequest(const Put &put,
+ const std::string ®ion_name) {
+ auto pb_req = Request::mutate();
+ auto pb_msg = std::static_pointer_cast<hbase::pb::MutateRequest>(pb_req->req_msg());
+ RequestConverter::SetRegion(region_name, pb_msg->mutable_region());
+
+ pb_msg->set_allocated_mutation(
+ ToMutation(MutationType::MutationProto_MutationType_PUT, put, -1).release());
+
+ VLOG(3) << "Req is " << pb_req->req_msg()->ShortDebugString();
+ return pb_req;
+}
} /* namespace hbase */
diff --git a/core/request-converter.h b/core/request-converter.h
index 003afaa..ff6b290 100644
--- a/core/request-converter.h
+++ b/core/request-converter.h
@@ -24,16 +24,23 @@
#include <vector>
#include "connection/request.h"
#include "core/action.h"
+#include "core/cell.h"
#include "core/get.h"
#include "core/region-request.h"
#include "core/scan.h"
#include "core/server-request.h"
+#include "core/mutation.h"
+#include "core/put.h"
+#include "if/Client.pb.h"
#include "if/HBase.pb.h"
-using hbase::pb::RegionSpecifier;
+using hbase::pb::MutationProto;
using hbase::pb::RegionAction;
+using hbase::pb::RegionSpecifier;
using hbase::pb::ServerName;
using hbase::ServerRequest;
+using MutationType = hbase::pb::MutationProto_MutationType;
+using DeleteType = hbase::pb::MutationProto_DeleteType;
namespace hbase {
@@ -64,6 +71,11 @@ class RequestConverter {
static std::unique_ptr<Request> ToMultiRequest(const ActionsByRegion ®ion_requests);
+ static std::unique_ptr<Request> ToMutateRequest(const Put &put, const std::string ®ion_name);
+
+ static std::unique_ptr<MutationProto> ToMutation(const MutationType type,
+ const Mutation &mutation, const int64_t nonce);
+
private:
// Constructor not required. We have all static methods to create PB requests.
RequestConverter();
@@ -76,6 +88,8 @@ class RequestConverter {
*/
static void SetRegion(const std::string ®ion_name, RegionSpecifier *region_specifier);
static std::unique_ptr<hbase::pb::Get> ToGet(const Get &get);
+ static DeleteType ToDeleteType(const CellType type);
+ static bool IsDelete(const CellType type);
};
} /* namespace hbase */
diff --git a/core/result-test.cc b/core/result-test.cc
index 09d4e15..520f4b9 100644
--- a/core/result-test.cc
+++ b/core/result-test.cc
@@ -17,8 +17,6 @@
*
*/
-#include "core/result.h"
-
#include <gtest/gtest.h>
#include <limits>
#include <memory>
@@ -26,7 +24,11 @@
#include <vector>
#include "core/cell.h"
-using namespace hbase;
+#include "core/result.h"
+
+using hbase::Cell;
+using hbase::CellType;
+using hbase::Result;
void PopulateCells(std::vector<std::shared_ptr<Cell> > &cells) {
// Populate some Results
diff --git a/core/result.cc b/core/result.cc
index eb28b32..9d9ddb3 100644
--- a/core/result.cc
+++ b/core/result.cc
@@ -109,4 +109,26 @@ const std::map<std::string, std::string> Result::FamilyMap(const std::string &fa
}
return family_map;
}
+
+std::string Result::DebugString() const {
+ std::string ret{"keyvalues="};
+ if (IsEmpty()) {
+ ret += "NONE";
+ return ret;
+ }
+ ret += "{";
+ bool is_first = true;
+ for (const auto &cell : cells_) {
+ if (is_first) {
+ is_first = false;
+ } else {
+ ret += ", ";
+ }
+ ret += cell->DebugString();
+ }
+ ret += "}";
+
+ return ret;
+}
+
} /* namespace hbase */
diff --git a/core/result.h b/core/result.h
index 8064197..627d161 100644
--- a/core/result.h
+++ b/core/result.h
@@ -113,6 +113,8 @@ class Result {
*/
const std::map<std::string, std::string> FamilyMap(const std::string &family) const;
+ std::string DebugString() const;
+
private:
bool exists_ = false;
bool stale_ = false;
diff --git a/core/simple-client.cc b/core/simple-client.cc
index 4b1144c..b417353 100644
--- a/core/simple-client.cc
+++ b/core/simple-client.cc
@@ -19,111 +19,91 @@
#include <folly/Logging.h>
#include <folly/Random.h>
-#include <folly/futures/Future.h>
#include <gflags/gflags.h>
-#include <wangle/concurrent/CPUThreadPoolExecutor.h>
-#include <wangle/concurrent/IOThreadPoolExecutor.h>
#include <atomic>
#include <chrono>
#include <iostream>
#include <thread>
-#include "connection/connection-pool.h"
#include "core/client.h"
-#include "core/keyvalue-codec.h"
-#include "if/Client.pb.h"
-#include "if/ZooKeeper.pb.h"
+#include "core/get.h"
+#include "core/put.h"
+#include "core/table.h"
#include "serde/server-name.h"
#include "serde/table-name.h"
+#include "utils/time-util.h"
-using namespace folly;
-using namespace std;
-using namespace std::chrono;
+using hbase::Client;
using hbase::Configuration;
-using hbase::Response;
-using hbase::Request;
-using hbase::HBaseService;
-using hbase::KeyValueCodec;
-using hbase::LocationCache;
-using hbase::ConnectionPool;
-using hbase::ConnectionFactory;
+using hbase::Get;
+using hbase::Put;
+using hbase::Table;
using hbase::pb::TableName;
using hbase::pb::ServerName;
-using hbase::pb::RegionSpecifier_RegionSpecifierType;
-using hbase::pb::MutateRequest;
-using hbase::pb::MutationProto_MutationType;
+using hbase::TimeUtil;
-// TODO(eclark): remove the need for this.
-DEFINE_string(table, "t", "What region to send a get");
-DEFINE_string(row, "test", "What row to get");
+DEFINE_string(table, "test_table", "What table to do the reads or writes");
+DEFINE_string(row, "row_", "row prefix");
DEFINE_string(zookeeper, "localhost:2181", "What zk quorum to talk to");
-DEFINE_uint64(columns, 10000, "How many columns to write");
+DEFINE_uint64(num_rows, 10000, "How many rows to write and read");
+DEFINE_bool(display_results, false, "Whether to display the Results from Gets");
DEFINE_int32(threads, 6, "How many cpu threads");
-std::unique_ptr<Request> MakeRequest(uint64_t col, std::string region_name) {
- auto req = Request::mutate();
- auto msg = std::static_pointer_cast<MutateRequest>(req->req_msg());
- auto region = msg->mutable_region();
- auto suf = folly::to<std::string>(col);
-
- region->set_value(region_name);
- region->set_type(
- RegionSpecifier_RegionSpecifierType::RegionSpecifier_RegionSpecifierType_REGION_NAME);
- auto mutation = msg->mutable_mutation();
- mutation->set_row(FLAGS_row + suf);
- mutation->set_mutate_type(MutationProto_MutationType::MutationProto_MutationType_PUT);
- auto column = mutation->add_column_value();
- column->set_family("d");
- auto qual = column->add_qualifier_value();
- qual->set_qualifier(suf);
- qual->set_value(".");
-
- return std::move(req);
+std::unique_ptr<Put> MakePut(const std::string &row) {
+ auto put = std::make_unique<Put>(row);
+ put->AddColumn("f", "q", row);
+ return std::move(put);
+}
+
+std::string Row(const std::string &prefix, uint64_t i) {
+ auto suf = folly::to<std::string>(i);
+ return prefix + suf;
}
int main(int argc, char *argv[]) {
google::SetUsageMessage("Simple client to get a single row from HBase on the comamnd line");
google::ParseCommandLineFlags(&argc, &argv, true);
google::InitGoogleLogging(argv[0]);
-
- // Set up thread pools.
- auto cpu_pool = std::make_shared<wangle::CPUThreadPoolExecutor>(FLAGS_threads);
- auto io_pool = std::make_shared<wangle::IOThreadPoolExecutor>(5);
- auto codec = std::make_shared<KeyValueCodec>();
- auto cp = std::make_shared<ConnectionPool>(io_pool, codec);
+ google::InstallFailureSignalHandler();
+ FLAGS_logtostderr = 1;
+ FLAGS_stderrthreshold = 1;
// Configuration
auto conf = std::make_shared<Configuration>();
conf->Set("hbase.zookeeper.quorum", FLAGS_zookeeper);
-
- // Create the cache.
- LocationCache cache{conf, cpu_pool, cp};
+ conf->SetInt("hbase.client.cpu.thread.pool.size", FLAGS_threads);
auto row = FLAGS_row;
- auto tn = folly::to<TableName>(FLAGS_table);
-
- auto loc = cache.LocateRegion(tn, row).get(milliseconds(5000));
- auto connection = loc->service();
-
- auto num_puts = FLAGS_columns;
-
- auto results = std::vector<Future<std::unique_ptr<Response>>>{};
- auto col = uint64_t{0};
- for (; col < num_puts; col++) {
- results.push_back(
- folly::makeFuture(col)
- .via(cpu_pool.get())
- .then([loc](uint64_t col) { return MakeRequest(col, loc->region_name()); })
- .then([connection](std::unique_ptr<Request> req) {
- return (*connection)(std::move(req));
- }));
+ auto tn = std::make_shared<TableName>(folly::to<TableName>(FLAGS_table));
+ auto num_puts = FLAGS_num_rows;
+
+ auto client = std::make_unique<Client>(*conf);
+ auto table = client->Table(*tn);
+
+ // Do the Put requests
+ auto start_ns = TimeUtil::GetNowNanos();
+ for (uint64_t i = 0; i < num_puts; i++) {
+ table->Put(*MakePut(Row(FLAGS_row, i)));
+ }
+
+ LOG(INFO) << "Successfully sent " << num_puts << " Put requests in "
+ << TimeUtil::ElapsedMillis(start_ns) << " ms.";
+
+ // Do the Get requests
+ start_ns = TimeUtil::GetNowNanos();
+ for (uint64_t i = 0; i < num_puts; i++) {
+ auto result = table->Get(Get{Row(FLAGS_row, i)});
+ if (FLAGS_display_results) {
+ LOG(INFO) << result->DebugString();
+ }
}
- auto allf = folly::collect(results).get();
- LOG(ERROR) << "Successfully sent " << allf.size() << " requests.";
+ LOG(INFO) << "Successfully sent " << num_puts << " Get requests in "
+ << TimeUtil::ElapsedMillis(start_ns) << " ms.";
- io_pool->stop();
+ table->Close();
+ client->Close();
return 0;
}
diff --git a/core/table.cc b/core/table.cc
index 3c54d78..8ace4af 100644
--- a/core/table.cc
+++ b/core/table.cc
@@ -54,6 +54,11 @@ std::shared_ptr<hbase::Result> Table::Get(const hbase::Get &get) {
return context.get(operation_timeout());
}
+void Table::Put(const hbase::Put &put) {
+ auto future = async_table_->Put(put);
+ future.get(operation_timeout());
+}
+
milliseconds Table::operation_timeout() const {
return TimeUtil::ToMillis(async_connection_->connection_conf()->operation_timeout());
}
diff --git a/core/table.h b/core/table.h
index 803befe..cbb95b7 100644
--- a/core/table.h
+++ b/core/table.h
@@ -58,6 +58,14 @@ class Table {
// std::vector<std::unique_ptr<hbase::Result>> Get(const std::vector<hbase::Get> &gets);
/**
+ * @brief - Puts some data in the table.
+ * @param - put Put object to perform HBase Put operation.
+ */
+ void Put(const hbase::Put &put);
+
+ // TODO: Batch Puts
+
+ /**
* @brief - Close the client connection.
*/
void Close();
diff --git a/test-util/mini-cluster.cc b/test-util/mini-cluster.cc
index fb58fc1..34da54c 100644
--- a/test-util/mini-cluster.cc
+++ b/test-util/mini-cluster.cc
@@ -239,25 +239,6 @@ jobject MiniCluster::admin() {
return admin;
}
-jobject MiniCluster::TablePut(const std::string &table, const std::string &row,
- const std::string &family, const std::string &column,
- const std::string &value) {
- env();
- jobject conn = env_->CallObjectMethod(htu(), get_conn_mid_);
- jobject put = env_->NewObject(put_class_, put_ctor_, StrToByteChar(row));
- if (put == NULL) {
- LOG(INFO) << "Couldn't create Put";
- exit(-1);
- }
- env_->CallObjectMethod(put, add_col_mid_, StrToByteChar(family), StrToByteChar(column),
- StrToByteChar(value));
- jobject table_name_obj = env_->CallStaticObjectMethod(table_name_class_, tbl_name_value_of_mid_,
- env_->NewStringUTF(table.c_str()));
- jobject table_obj = env_->CallObjectMethod(conn, get_table_mid_, table_name_obj);
- env_->CallObjectMethod(table_obj, put_mid_, put);
- return table_obj;
-}
-
// moves region to server
void MiniCluster::MoveRegion(const std::string ®ion, const std::string &server) {
jobject admin_ = admin();
diff --git a/test-util/mini-cluster.h b/test-util/mini-cluster.h
index a9502b5..4119cb5 100644
--- a/test-util/mini-cluster.h
+++ b/test-util/mini-cluster.h
@@ -39,9 +39,6 @@ class MiniCluster {
jobject GetConf();
// returns the value for config key retrieved from cluster
const std::string GetConfValue(const std::string &key);
- // Does Put into table for family fam, qualifier col with value
- jobject TablePut(const std::string &table, const std::string &row, const std::string &family,
- const std::string &column, const std::string &value);
private:
JNIEnv *env_;
diff --git a/test-util/test-util.cc b/test-util/test-util.cc
index 54d2c83..c4e6ed2 100644
--- a/test-util/test-util.cc
+++ b/test-util/test-util.cc
@@ -58,19 +58,17 @@ void TestUtil::StartMiniCluster(int32_t num_region_servers) {
conf()->Set(ZKUtil::kHBaseZookeeperClientPort_,
mini_->GetConfValue(ZKUtil::kHBaseZookeeperClientPort_));
}
+
void TestUtil::StopMiniCluster() { mini_->StopCluster(); }
void TestUtil::CreateTable(const std::string &table, const std::string &family) {
mini_->CreateTable(table, family);
}
+
void TestUtil::CreateTable(const std::string &table, const std::string &family,
const std::vector<std::string> &keys) {
mini_->CreateTable(table, family, keys);
}
-void TestUtil::TablePut(const std::string &table, const std::string &row, const std::string &family,
- const std::string &column, const std::string &value) {
- mini_->TablePut(table, row, family, column, value);
-}
void TestUtil::StartStandAloneInstance() {
auto p = temp_dir_.path().string();
diff --git a/test-util/test-util.h b/test-util/test-util.h
index b5714ee..5729674 100644
--- a/test-util/test-util.h
+++ b/test-util/test-util.h
@@ -61,8 +61,6 @@ class TestUtil {
void CreateTable(const std::string &table, const std::string &family);
void CreateTable(const std::string &table, const std::string &family,
const std::vector<std::string> &keys);
- void TablePut(const std::string &table, const std::string &row, const std::string &family,
- const std::string &column, const std::string &value);
void StartStandAloneInstance();
void StopStandAloneInstance();