From ed0e382c93a1c7175893251299cba334b2203611 Mon Sep 17 00:00:00 2001 From: Sudeep Sunthankar Date: Sat, 10 Dec 2016 02:42:44 +1100 Subject: [PATCH] 1) Addition of Result and ResultScanner classes 2) Added copy construtor in Cell 3) Added unit-tests in BUCK diff --git a/hbase-native-client/core/BUCK b/hbase-native-client/core/BUCK index fa01eb3..76b24ec 100644 --- a/hbase-native-client/core/BUCK +++ b/hbase-native-client/core/BUCK @@ -32,6 +32,8 @@ cxx_library( "configuration.h", "hbase_configuration_loader.h", "scan.h", + "result.h", + "result_scanner.h", ], srcs=[ "cell.cc", @@ -43,6 +45,8 @@ cxx_library( "configuration.cc", "hbase_configuration_loader.cc", "scan.cc", + "result.cc", + "result_scanner.cc", ], deps=[ "//connection:connection", @@ -53,46 +57,53 @@ cxx_library( "//third-party:zookeeper_mt", ], compiler_flags=['-Weffc++'], - visibility=[ - 'PUBLIC', - ], ) -cxx_test(name="location-cache-test", - srcs=[ - "location-cache-test.cc", + visibility=['PUBLIC', ], ) +cxx_test( + name="location-cache-test", + srcs=["location-cache-test.cc", ], + deps=[ + ":core", + "//test-util:test-util", ], - deps=[":core", - "//test-util:test-util", ], run_test_separately=True, ) -cxx_test(name="cell-test", - srcs=[ - "cell-test.cc", - ], +cxx_test( + name="cell-test", + srcs=["cell-test.cc", ], deps=[":core", ], run_test_separately=True, ) -cxx_test(name="get-test", - srcs=[ - "get-test.cc", - ], +cxx_test( + name="get-test", + srcs=["get-test.cc", ], deps=[":core", ], run_test_separately=True, ) -cxx_test(name="time_range-test", - srcs=[ - "time_range-test.cc", - ], +cxx_test( + name="time_range-test", + srcs=["time_range-test.cc", ], deps=[":core", ], run_test_separately=True, ) -cxx_test(name="hbase_configuration-test", - srcs=[ - "hbase_configuration-test.cc", - ], +cxx_test( + name="hbase_configuration-test", + srcs=["hbase_configuration-test.cc", ], deps=[":core", ], run_test_separately=True, ) -cxx_test(name="scan-test", - srcs=[ - "scan-test.cc", - ], +cxx_test( + name="scan-test", + srcs=["scan-test.cc", ], + deps=[":core", ], + run_test_separately=True, ) +cxx_test( + name="result-test", + srcs=["result-test.cc", ], deps=[":core", ], run_test_separately=True, ) -cxx_binary(name="simple-client", + +cxx_test( + name="result_scanner-test", + srcs=["result_scanner-test.cc", ], + deps=[":core", ], + run_test_separately=True, ) + +cxx_binary( + name="simple-client", srcs=["simple-client.cc", ], deps=[":core", "//connection:connection"], ) diff --git a/hbase-native-client/core/cell.cc b/hbase-native-client/core/cell.cc index 5129bc9..339e1bb 100644 --- a/hbase-native-client/core/cell.cc +++ b/hbase-native-client/core/cell.cc @@ -18,16 +18,20 @@ */ #include "core/cell.h" +#include #include namespace hbase { -Cell::Cell(const std::string &row, const std::string &family, - const std::string &qualifier, const long ×tamp, - const std::string &value, const hbase::CellType &cell_type) - : row_(row), family_(family), qualifier_(qualifier), timestamp_(timestamp), - cell_type_(cell_type), value_(value), sequence_id_(0) { - +Cell::Cell(const std::string &row, const std::string &family, const std::string &qualifier, + const long ×tamp, const std::string &value, const hbase::CellType &cell_type) + : row_(row), + family_(family), + qualifier_(qualifier), + timestamp_(timestamp), + cell_type_(cell_type), + value_(value), + sequence_id_(0) { if (0 == row.size()) throw std::runtime_error("Row size should be greater than 0"); @@ -38,20 +42,150 @@ Cell::Cell(const std::string &row, const std::string &family, throw std::runtime_error("Timestamp should be greater than 0"); } -Cell::~Cell() {} +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() { +} + +const std::string &Cell::Row() const { + return row_; +} + +const std::string &Cell::Family() const { + return family_; +} + +const std::string &Cell::Qualifier() const { + return qualifier_; +} + +unsigned long Cell::Timestamp() const { + return timestamp_; +} + +const std::string &Cell::Value() const { + return value_; +} + +hbase::CellType Cell::Type() const { + return cell_type_; +} + +long Cell::SequenceId() const { + return sequence_id_; +} + +Cell *Cell::ParseCellData(const std::string &cell_data) { + DLOG(INFO) << "cell_data.size() = " << cell_data.size(); + + int offset = 0; + unsigned int cell_size_length; + unsigned int *pSize = (unsigned int *) &cell_data[offset]; // pCurrent; + cell_size_length = *pSize; + SwapByteOrder(cell_size_length); + + // Key length offset starts from kHBaseSizeOfInt and not 0 coz @ o we have + // cell_size_length + int key_length_offset = kHBaseSizeOfInt; + pSize = (unsigned int *) &cell_data[key_length_offset]; + unsigned int key_length = *pSize; + SwapByteOrder(key_length); + + // Value offset is @ key_len_offset + sizeof(key_len) + int value_length_offset = key_length_offset + kHBaseSizeOfKeyLength; + pSize = (unsigned int *) &cell_data[value_length_offset]; + unsigned int value_length = *pSize; + SwapByteOrder(value_length); + + // Row length is @ kHBaseKeyValueInfrastructeSize + sizeof(cell_size_length) + int row_length_offset = kHBaseSizeOfKeyValueInfrastructure + kHBaseSizeOfInt; + int row_offset = row_length_offset + kHBaseSizeOfRowLength; + unsigned short *pRowLength = (unsigned short *) &cell_data[row_length_offset]; + unsigned short row_length = *pRowLength; + SwapByteOrder2Bytes(row_length); + std::string row(cell_data, row_offset, row_length); + + // Column family length is @ row_offset + row_length + int column_family_length_offset = row_offset + row_length; + int column_family_offset = column_family_length_offset + kHBaseSizeOfFamilyLength; + unsigned char column_family_length = cell_data[column_family_length_offset]; // 1 byte + std::string column_family(cell_data, column_family_offset, column_family_length); + + // Column Qualifier starts @ column_family_offset + column_family_lengthh + int column_qualifier_offset = column_family_offset + column_family_length; + int column_qualifier_length = key_length + - (row_length + column_family_length + kHBaseSizeOfKeyInfrastructure); + std::string column_qualifier(cell_data, column_qualifier_offset, column_qualifier_length); + + // Timestamp starts @ column_qualifier_offset + column_qualifier_length + int timestamp_offset = column_qualifier_offset + column_qualifier_length; + unsigned long timestamp = 0L; + for (int i = timestamp_offset; i < (timestamp_offset + kHBaseSizeOfTimestamp); i++) { + timestamp <<= 8; + timestamp ^= cell_data[i] & 0xFF; + } -const std::string &Cell::Row() const { return row_; } + // Key Type starts @ timestamp_offset + kHBaseSizeOfTimestamp + int key_type_offset = timestamp_offset + kHBaseSizeOfTimestamp; + unsigned char key_type = static_cast(cell_data[key_type_offset]); // 1 byte -const std::string &Cell::Family() const { return family_; } + // Value starts @ key_type_offset + kHBaseSizeOfKeyType + int value_offset = key_type_offset + kHBaseSizeOfKeyType; + std::string value(cell_data, value_offset, value_length); +#if 0 + DLOG(INFO) << "cell_size_length:- " << cell_size_length; + DLOG(INFO) << "key_length:- " << key_length; + DLOG(INFO) << "value_length:- " << value_length; -const std::string &Cell::Qualifier() const { return qualifier_; } + DLOG(INFO) << "row_length_offset:- " << row_length_offset; + DLOG(INFO) << "row_offset:- " << row_offset; + DLOG(INFO) << "row_length:- " << row_length; + DLOG(INFO) << "row:- " << row; -unsigned long Cell::Timestamp() const { return timestamp_; } + DLOG(INFO) << "column_family_length_offset:- " << column_family_length_offset; + DLOG(INFO) << "column_family_offset:- " << column_family_offset; + DLOG(INFO) << "column_family_length:- " + << static_cast(column_family_length); + DLOG(INFO) << "column:- " << column_family; -const std::string &Cell::Value() const { return value_; } + DLOG(INFO) << "column_qualifier_offset:- " << column_qualifier_offset; + DLOG(INFO) << "column_qualifier_length:- " << column_qualifier_length; + DLOG(INFO) << "column_qualifier:- " << column_qualifier; -hbase::CellType Cell::Type() const { return cell_type_; } + DLOG(INFO) << "timestamp_offset:- " << timestamp_offset; + DLOG(INFO) << "timestamp:- " << timestamp; -long Cell::SequenceId() const { return sequence_id_; } + DLOG(INFO) << "key_type_offset:- " << key_type_offset; + DLOG(INFO) << "key_type:- " << static_cast(key_type); -} /* namespace hbase */ + DLOG(INFO) << "value_offset:- " << value_offset; + DLOG(INFO) << "value:- " << value; +#endif + return Cell::CreateCell(row, column_family, column_qualifier, timestamp, value, + static_cast(key_type)); +} + +Cell *Cell::CreateCell(const std::string &row, const std::string &family, + const std::string &qualifier, const long ×tamp, + const std::string &value, const hbase::CellType &cell_type) { + Cell *cell = new Cell(row, family, qualifier, timestamp, value, cell_type); + return cell; +} + +void Cell::SwapByteOrder(uint32_t &ui) { + ui = (ui >> 24) | ((ui << 8) & 0x00FF0000) | ((ui >> 8) & 0x0000FF00) | (ui << 24); +} + +void Cell::SwapByteOrder2Bytes(unsigned short &us) { + us = ((((us) >> 8) & 0x00FF) | (((us) << 8) & 0xFF00)); +} +} +/* namespace hbase */ diff --git a/hbase-native-client/core/cell.h b/hbase-native-client/core/cell.h index 2b15ad6..5dcd3a6 100644 --- a/hbase-native-client/core/cell.h +++ b/hbase-native-client/core/cell.h @@ -34,11 +34,11 @@ enum CellType { }; class Cell { -public: - Cell(const std::string &row, const std::string &family, - const std::string &qualifier, const long ×tamp, - const std::string &value, const hbase::CellType &cell_type); - virtual ~Cell(); + public: + Cell(const std::string &row, const std::string &family, const std::string &qualifier, + const long ×tamp, const std::string &value, const hbase::CellType &cell_type); + Cell(const Cell &cell); + ~Cell(); const std::string &Row() const; const std::string &Family() const; const std::string &Qualifier() const; @@ -46,8 +46,12 @@ public: const std::string &Value() const; CellType Type() const; long SequenceId() const; + static Cell *ParseCellData(const std::string &cell_data); + static Cell *CreateCell(const std::string &row, const std::string &family, + const std::string &qualifier, const long ×tamp, + const std::string &value, const hbase::CellType &cell_type); -private: + private: std::string row_; std::string family_; std::string qualifier_; @@ -55,6 +59,46 @@ private: hbase::CellType cell_type_; std::string value_; long sequence_id_; + + /** + * Size of boolean in bytes + */ + static const int kHBaseSizeOfBoolean = sizeof(char) / sizeof(char); + + /** + * Size of byte in bytes + */ + static const int kHBaseSizeOfByte = kHBaseSizeOfBoolean; + + /** + * Size of int in bytes + */ + static const int kHBaseSizeOfInt = sizeof(int) / sizeof(char); + + /** + * Size of long in bytes + */ + static const int kHBaseSizeOfLong = sizeof(long) / sizeof(char); + + /** + * Size of Short in bytes + */ + static const int kHBaseSizeOfShort = sizeof(short) / sizeof(char); + + static const int kHBaseSizeOfKeyLength = kHBaseSizeOfInt; + static const int kHBaseSizeOfValueLength = kHBaseSizeOfInt; + static const int kHBaseSizeOfRowLength = kHBaseSizeOfShort; + static const int kHBaseSizeOfFamilyLength = kHBaseSizeOfByte; + static const int kHBaseSizeOfTimestamp = kHBaseSizeOfLong; + static const int kHBaseSizeOfKeyType = kHBaseSizeOfByte; + static const int kHBaseSizeOfTimestampAndKey = kHBaseSizeOfTimestamp + kHBaseSizeOfKeyType; + static const int kHBaseSizeOfKeyInfrastructure = kHBaseSizeOfRowLength + kHBaseSizeOfFamilyLength + + kHBaseSizeOfTimestampAndKey; + static const int kHBaseSizeOfKeyValueInfrastructure = kHBaseSizeOfKeyLength + + kHBaseSizeOfValueLength; + + static void SwapByteOrder(uint32_t &ui); + static void SwapByteOrder2Bytes(unsigned short &us); }; } /* namespace hbase */ diff --git a/hbase-native-client/core/result-test.cc b/hbase-native-client/core/result-test.cc new file mode 100644 index 0000000..56bee61 --- /dev/null +++ b/hbase-native-client/core/result-test.cc @@ -0,0 +1,182 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "core/result.h" + +#include +#include +#include +#include +#include + +#include "core/cell.h" +using namespace hbase; + +void PopulateCells(std::vector> &cells) { + // Populate some Result + for (int i = 0; i < 10; i++) { + std::string row = "row-" + std::to_string(i); + std::string family = "family-" + std::to_string(i); + std::string column = "column-" + std::to_string(i); + std::string value = "value-" + std::to_string(i); + cells.push_back( + std::make_unique < Cell + > (row, family, column, std::numeric_limits::max(), value, CellType::PUT)); + // Add some more cells + switch (i) { + case 5: { + cells.push_back( + std::make_unique < Cell + > ("row-X", family, column, std::numeric_limits::max(), "value-X", CellType::PUT)); + break; + } + case 8: { + cells.push_back( + std::make_unique < Cell + > ("row-X", family, column, std::numeric_limits::max(), "value-X", CellType::PUT)); + cells.push_back( + std::make_unique < Cell + > ("row-Y", family, column, std::numeric_limits::max(), "value-Y", CellType::PUT)); + break; + } + case 9: { + cells.push_back( + std::make_unique < Cell + > ("row-X", family, column, std::numeric_limits::max(), "value-X", CellType::PUT)); + cells.push_back( + std::make_unique < Cell + > ("row-Y", family, column, std::numeric_limits::max(), "value-Y", CellType::PUT)); + cells.push_back( + std::make_unique < Cell + > ("row-Z", family, column, std::numeric_limits::max(), "value-Z", CellType::PUT)); + break; + } + } + } + return; +} + +TEST(Result, EmptyResult) { + Result result; + EXPECT_EQ(true, result.IsEmpty()); +} + +TEST(Result, ReadOnly) { + Result result(true); +} + +TEST(Result, FilledResult) { + std::vector> cells; + PopulateCells(cells); + + Result result(cells, true, false, false); + EXPECT_EQ(false, result.IsEmpty()); + + // Get Latest Cell for the given family and qualifier. + auto latest_cell(result.ColumnLatestCell("family", "column")); + // Nothing of the above sort is there so it should be nullptr + ASSERT_FALSE(latest_cell.get()); + + // Try to get the latest cell for the given family and qualifier. + latest_cell = result.ColumnLatestCell("family-4", "column-4"); + // Now shouldn't be a nullptr + ASSERT_TRUE(latest_cell.get()); + + // And Value must match too + EXPECT_EQ("value-4", latest_cell->Value()); + + // Value will be nullptr as no such family and qualifier is present + ASSERT_FALSE(result.Value("family-4", "qualifier")); + // Value will be present as family and qualifier is present + ASSERT_TRUE(result.Value("family-4", "column-4")); + // Value should be present and match. + EXPECT_EQ(latest_cell->Value(), (*result.ColumnLatestCell("family-4", "column-4")).Value()); + // Value should be present and match. + EXPECT_EQ("value-7", *result.Value("family-7", "column-7")); + + // Get cells for the given family and qualifier + auto column_cells = result.ColumnCells("family", "column"); + // Size should be 0 + EXPECT_EQ(0, column_cells.size()); + + // Size shouldn't be 0 and Row() and Value() must match + column_cells = result.ColumnCells("family-5", "column-5"); + EXPECT_EQ(2, column_cells.size()); + EXPECT_EQ("row-5", column_cells[0]->Row()); + EXPECT_EQ("row-X", column_cells[1]->Row()); + EXPECT_EQ("value-5", column_cells[0]->Value()); + EXPECT_EQ("value-X", column_cells[1]->Value()); + // Size shouldn't be 0 and Row() and Value() must match + column_cells = result.ColumnCells("family-8", "column-8"); + EXPECT_EQ(3, column_cells.size()); + EXPECT_EQ("row-8", column_cells[0]->Row()); + EXPECT_EQ("row-X", column_cells[1]->Row()); + EXPECT_EQ("row-Y", column_cells[2]->Row()); + EXPECT_EQ("value-8", column_cells[0]->Value()); + EXPECT_EQ("value-X", column_cells[1]->Value()); + EXPECT_EQ("value-Y", column_cells[2]->Value()); + + // Size shouldn't be 0 and Row() and Value() must match + column_cells = result.ColumnCells("family-9", "column-9"); + EXPECT_EQ(4, column_cells.size()); + EXPECT_EQ("row-9", column_cells[0]->Row()); + EXPECT_EQ("row-X", column_cells[1]->Row()); + EXPECT_EQ("row-Y", column_cells[2]->Row()); + EXPECT_EQ("row-Z", column_cells[3]->Row()); + EXPECT_EQ("value-9", column_cells[0]->Value()); + EXPECT_EQ("value-X", column_cells[1]->Value()); + EXPECT_EQ("value-Y", column_cells[2]->Value()); + EXPECT_EQ("value-Z", column_cells[3]->Value()); + + // Test all the Cell values + const auto& result_cells = result.Cells(); + int i = 0, j = 0; + for (const auto &cell : result_cells) { + std::string row = "row-" + std::to_string(i); + std::string family = "family-" + std::to_string(i); + std::string column = "column-" + std::to_string(i); + std::string value = "value-" + std::to_string(i); + switch (j) { + case 6: + case 10: + case 13: { + EXPECT_EQ("row-X", cell->Row()); + ++j; + continue; + } + case 11: + case 14: { + EXPECT_EQ("row-Y", cell->Row()); + ++j; + continue; + } + case 15: { + EXPECT_EQ("row-Z", cell->Row()); + ++j; + continue; + } + } + EXPECT_EQ(row, cell->Row()); + EXPECT_EQ(family, cell->Family()); + EXPECT_EQ(column, cell->Qualifier()); + EXPECT_EQ(value, cell->Value()); + ++i; + ++j; + } +} diff --git a/hbase-native-client/core/result.cc b/hbase-native-client/core/result.cc new file mode 100644 index 0000000..104f480 --- /dev/null +++ b/hbase-native-client/core/result.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/result.h" + +namespace hbase { + +Result::Result() { +} + +Result::Result(const Result& result) { + empty_ = result.empty_; + exists_ = result.exists_; + stale_ = result.stale_; + partial_ = result.partial_; + readonly_ = result.readonly_; + for (const auto &cell : result.cells_) { + cells_.push_back(std::make_unique < Cell > (*cell)); + } +} + +Result::Result(bool readonly) + : readonly_(readonly) { +} + +Result::~Result() { + // TODO Auto-generated destructor stub +} + +Result::Result(std::vector>& cells, bool exists, bool stale, bool partial, + bool readonly) + : exists_(exists), + stale_(stale), + partial_(partial), + readonly_(readonly) { + for (const auto &cell : cells) { + cells_.push_back(std::make_unique < Cell > (*cell)); + } + empty_ = cells_.empty(); +} + +const std::vector>& Result::Cells() const { + return cells_; +} + +std::vector> Result::ColumnCells(const std::string& family, + const std::string& qualifier) const { + std::vector> column_cells; + for (const auto &cell : cells_) { + if (cell->Family() == family && cell->Qualifier() == qualifier) { + column_cells.push_back(std::make_unique < Cell > (*cell)); + } + } + return column_cells; +} + +std::unique_ptr Result::ColumnLatestCell(const std::string& family, + const std::string& qualifier) const { + std::unique_ptr latest_cell; + for (const auto &cell : cells_) { + if (cell->Family() == family && cell->Qualifier() == qualifier) + latest_cell = std::make_unique < Cell > (*cell); + } + return std::move(latest_cell); +} + +std::unique_ptr Result::Value(const std::string& family, + const std::string& qualifier) const { + std::unique_ptr value; + std::unique_ptr latest_cell(ColumnLatestCell(family, qualifier)); + if (latest_cell.get()) { + value = std::make_unique < std::string > (latest_cell->Value()); + } + return std::move(value); +} + +bool Result::IsEmpty() const { + return empty_; +} + +} /* namespace hbase */ diff --git a/hbase-native-client/core/result.h b/hbase-native-client/core/result.h new file mode 100644 index 0000000..56080ab --- /dev/null +++ b/hbase-native-client/core/result.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 + +#include "core/cell.h" + +namespace hbase { + +class Result { + public: + Result(); + Result(const Result& result); + Result(bool readonly); + Result(std::vector> &cells, bool exists, bool stale, bool partial, + bool readonly = false); + ~Result(); + const std::vector>& Cells() const; + std::vector> ColumnCells(const std::string &family, + const std::string &qualifier) const; + std::unique_ptr ColumnLatestCell(const std::string &family, + const std::string &qualifier) const; + std::unique_ptr Value(const std::string &family, const std::string &qualifier) const; + bool IsEmpty() const; + + private: + bool empty_ = true; + bool exists_ = false; + bool stale_ = false; + bool partial_ = false; + bool readonly_ = false; + std::string row_ = ""; + std::vector> cells_; +}; +} /* namespace hbase */ diff --git a/hbase-native-client/core/result_scanner-test.cc b/hbase-native-client/core/result_scanner-test.cc new file mode 100644 index 0000000..9cacba2 --- /dev/null +++ b/hbase-native-client/core/result_scanner-test.cc @@ -0,0 +1,88 @@ +/* + * 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/result_scanner.h" + +#include +#include +#include + +#include + +#include "core/cell.h" +#include "core/result.h" + +using namespace hbase; + +void PopulateCellsForResult(std::vector> &cells, const std::string &suffix) { + // Populate some Result + for (int i = 0; i < 10; i++) { + std::string row = "row-" + suffix + "-" + std::to_string(i); + std::string family = "family-" + std::to_string(i); + std::string column = "column-" + std::to_string(i); + std::string value = "value-" + suffix + "-" + std::to_string(i); + cells.push_back( + std::make_unique < Cell + > (row, family, column, std::numeric_limits::max(), value, CellType::PUT)); + } + return; +} + +TEST(ResultScanner, Object) { + std::vector> results; + for (int i = 0; i < 5; i++) { + std::string suffix = "res-" + std::to_string(i); + std::vector> cells; + PopulateCellsForResult(cells, suffix); + results.push_back(std::make_unique < Result > (cells, true, false, false)); + } + + + ResultScanner res_scanner(results); + + std::vector> res_rows(res_scanner.Next(3)); + ASSERT_EQ(3, res_rows.size()); + int i = 0; + for (const auto &result : res_rows) { + std::string value = "value-res-" + std::to_string(i) + "-4"; + ASSERT_EQ(value, *result->Value("family-4", "column-4")); + i += 1; + } + + res_rows = res_scanner.Next(5); + ASSERT_EQ(5, res_rows.size()); + i = 0; + for (const auto &result : res_rows) { + std::string value = "value-res-" + std::to_string(i) + "-4"; + ASSERT_EQ(value, *result->Value("family-4", "column-4")); + i += 1; + } + + i = 0; + while (std::unique_ptr result = res_scanner.Next()) { + ASSERT_TRUE(result); + std::string value = "value-res-" + std::to_string(i) + "-4"; + ASSERT_EQ(value, *result->Value("family-4", "column-4")); + i += 1; + } + std::unique_ptr result = res_scanner.Next(); + ASSERT_FALSE(result); + +} + diff --git a/hbase-native-client/core/result_scanner.cc b/hbase-native-client/core/result_scanner.cc new file mode 100644 index 0000000..e22166d --- /dev/null +++ b/hbase-native-client/core/result_scanner.cc @@ -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. + * + */ + +#include "core/result_scanner.h" + +namespace hbase { + +ResultScanner::ResultScanner(std::vector> &results) { + for (const auto &result : results) { + results_.push_back(std::make_unique < Result > (*result)); + } +} + +ResultScanner::ResultScanner(const ResultScanner& res_scanner) { + for (const auto &result : res_scanner.results_) { + results_.push_back(std::make_unique < Result > (*result)); + } +} + +ResultScanner::~ResultScanner() { + results_.clear(); +} + +std::unique_ptr ResultScanner::Next() { + std::unique_ptr result; + if (results_.size() > 0) { + result = std::make_unique < Result > (*results_.front()); + results_.erase(results_.begin()); + } + return std::move(result); +} + +std::vector> ResultScanner::Next(int num_rows) { + std::vector> results; + for (int i = 0; i < num_rows; i++) { + std::unique_ptr result = std::make_unique < Result > (*results_[i]); + if (result.get()) { + results.push_back(std::move(result)); + } + } + return results; +} + +bool ResultScanner::RenewLease() const { + return true; +} + +void ResultScanner::Close() { + close_scanner_ = true; +} + +} /* namespace hbase */ + diff --git a/hbase-native-client/core/result_scanner.h b/hbase-native-client/core/result_scanner.h new file mode 100644 index 0000000..37520b8 --- /dev/null +++ b/hbase-native-client/core/result_scanner.h @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#pragma once + +#include +#include + +#include "core/result.h" +namespace hbase { + +class ResultScanner { + public: + ResultScanner(std::vector> &results); + ResultScanner(const ResultScanner &res_scanner); + ~ResultScanner(); + std::unique_ptr Next(); + std::vector> Next(int num_rows); + bool RenewLease() const; + void Close(); + + private: + bool close_scanner_ = false; + std::vector> results_; +}; + +} /* namespace hbase */ -- 1.8.3.1