From bd242e630b1741a664d636bb2123866cbd18a832 Mon Sep 17 00:00:00 2001 From: Xiaobing Zhou Date: Fri, 18 Nov 2016 11:00:30 -0800 Subject: [PATCH] HBASE-17051. libhbase++: implement RPC client and connection management --- hbase-native-client/Makefile | 2 +- hbase-native-client/connection/connection-id.h | 97 ++++++++++++++ .../connection/connection-pool-test.cc | 27 ++-- hbase-native-client/connection/connection-pool.cc | 51 ++++--- hbase-native-client/connection/connection-pool.h | 52 +++----- hbase-native-client/connection/rpc-client.cc | 148 +++++++++++++++++++++ hbase-native-client/connection/rpc-client.h | 128 ++++++++++++++++++ hbase-native-client/connection/rpc-connection.h | 54 ++++++++ hbase-native-client/core/location-cache.cc | 15 ++- hbase-native-client/security/user.h | 35 +++++ 10 files changed, 537 insertions(+), 72 deletions(-) create mode 100644 hbase-native-client/connection/connection-id.h create mode 100644 hbase-native-client/connection/rpc-client.cc create mode 100644 hbase-native-client/connection/rpc-client.h create mode 100644 hbase-native-client/connection/rpc-connection.h create mode 100644 hbase-native-client/security/user.h diff --git a/hbase-native-client/Makefile b/hbase-native-client/Makefile index 64cef06..fa4ad59 100644 --- a/hbase-native-client/Makefile +++ b/hbase-native-client/Makefile @@ -22,7 +22,7 @@ LD:=g++ DEBUG_PATH = build/debug RELEASE_PATH = build/release PROTO_SRC_DIR = build/if -MODULES = connection core serde test-util utils +MODULES = connection core serde test-util utils security SRC_DIR = $(MODULES) DEBUG_BUILD_DIR = $(addprefix $(DEBUG_PATH)/,$(MODULES)) RELEASE_BUILD_DIR = $(addprefix $(RELEASE_PATH)/,$(MODULES)) diff --git a/hbase-native-client/connection/connection-id.h b/hbase-native-client/connection/connection-id.h new file mode 100644 index 0000000..3c8904e --- /dev/null +++ b/hbase-native-client/connection/connection-id.h @@ -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. + * + */ +#pragma once + +#include +#include "if/HBase.pb.h" +#include "security/user.h" + +using hbase::pb::ServerName; +using hbase::security::User; + +namespace hbase { +class ConnectionId { +public: + ConnectionId(const std::string &host, uint16_t port) + : ConnectionId(host, port, nullptr, "") {} + + ConnectionId( + const std::string &host, + uint16_t port, + std::shared_ptr user) + : ConnectionId(host, port, user, "") {} + + ConnectionId( + const std::string &host, + uint16_t port, + std::shared_ptr user, + const std::string &service_name) + : user_(user), service_name_(service_name), host_(host), port_(port) {} + + virtual ~ConnectionId() = default; + + std::shared_ptr user() const {return user_;} + std::string service_name() const {return service_name_;} + std::string host() {return host_;} + uint16_t port() {return port_;} + +private: + std::shared_ptr user_; + std::string service_name_; + std::string host_; + uint16_t port_; +}; + + +/* Equals function for ConnectionId */ +struct ConnectionIdEquals { + /** equals */ + bool operator() ( + const std::shared_ptr &lhs, + const std::shared_ptr &rhs) const { + return + userEquals(lhs->user(), rhs->user()) + && lhs->host() == rhs->host() + && lhs->port() == rhs->port(); + } + +private: + bool userEquals( + const std::shared_ptr &lhs, + const std::shared_ptr &rhs) const { + return + lhs == nullptr ? + rhs == nullptr : + (rhs == nullptr ? false : lhs->user_name() == rhs->user_name()); + } +}; + + +/** Hash for ConnectionId. */ +struct ConnectionIdHash { + /** hash */ + std::size_t operator()(const std::shared_ptr &ci) const { + std::size_t h = 0; + boost::hash_combine(h, ci->user() == nullptr ? 0 : ci->user()->user_name()); + boost::hash_combine(h, ci->host()); + boost::hash_combine(h, ci->port()); + return h; + } +}; +} // namespace hbase diff --git a/hbase-native-client/connection/connection-pool-test.cc b/hbase-native-client/connection/connection-pool-test.cc index bd2d585..f235169 100644 --- a/hbase-native-client/connection/connection-pool-test.cc +++ b/hbase-native-client/connection/connection-pool-test.cc @@ -25,12 +25,14 @@ #include "connection/connection-factory.h" #include "if/HBase.pb.h" #include "serde/server-name.h" +#include "connection-id.h" using namespace hbase; using hbase::pb::ServerName; using ::testing::Return; using ::testing::_; +using hbase::ConnectionId; class MockConnectionFactory : public ConnectionFactory { public: @@ -75,13 +77,10 @@ TEST(TestConnectionPool, TestOnlyCreateOnce) { .WillRepeatedly(Return(mock_boot)); ConnectionPool cp{mock_cf}; - ServerName sn; - sn.set_host_name(hostname); - sn.set_port(port); - - auto result = cp.Get(sn); + auto remote_id = std::make_shared(hostname, port); + auto result = cp.GetConnection(remote_id); ASSERT_TRUE(result != nullptr); - result = cp.Get(sn); + result = cp.GetConnection(remote_id); } TEST(TestConnectionPool, TestOnlyCreateMultipleDispose) { @@ -102,13 +101,13 @@ TEST(TestConnectionPool, TestOnlyCreateMultipleDispose) { ConnectionPool cp{mock_cf}; { - auto result_one = cp.Get(folly::to( - hostname_one + ":" + folly::to(port))); - auto result_two = cp.Get(folly::to( - hostname_two + ":" + folly::to(port))); + auto remote_id = std::make_shared(hostname_one, port); + auto result_one = cp.GetConnection(remote_id); + auto remote_id2 = std::make_shared(hostname_two, port); + auto result_two = cp.GetConnection(remote_id2); } - auto result_one = cp.Get( - folly::to(hostname_one + ":" + folly::to(port))); - auto result_two = cp.Get( - folly::to(hostname_two + ":" + folly::to(port))); + auto remote_id = std::make_shared(hostname_one, port); + auto result_one = cp.GetConnection(remote_id); + auto remote_id2 = std::make_shared(hostname_two, port); + auto result_two = cp.GetConnection(remote_id2); } diff --git a/hbase-native-client/connection/connection-pool.cc b/hbase-native-client/connection/connection-pool.cc index aa3d094..b1fe1de 100644 --- a/hbase-native-client/connection/connection-pool.cc +++ b/hbase-native-client/connection/connection-pool.cc @@ -25,7 +25,6 @@ using std::mutex; using std::unique_ptr; using std::shared_ptr; -using hbase::pb::ServerName; using hbase::ConnectionPool; using hbase::HBaseService; using folly::SharedMutexWritePriority; @@ -42,33 +41,36 @@ ConnectionPool::~ConnectionPool() { SharedMutexWritePriority::WriteHolder holder(map_mutex_); for (auto &item : connections_) { auto &con = item.second; - con->close(); + con->Close(); } connections_.clear(); clients_.clear(); } -std::shared_ptr ConnectionPool::Get(const ServerName &sn) { +std::shared_ptr ConnectionPool::GetConnection( + std::shared_ptr remote_id) { // Try and get th cached connection. - auto found_ptr = GetCached(sn); + auto found_ptr = GetCachedConnection(remote_id); // If there's no connection then create it. if (found_ptr == nullptr) { - found_ptr = GetNew(sn); + found_ptr = GetNewConnection(remote_id); } return found_ptr; } -std::shared_ptr ConnectionPool::GetCached(const ServerName &sn) { +std::shared_ptr ConnectionPool::GetCachedConnection( + std::shared_ptr remote_id) { SharedMutexWritePriority::ReadHolder holder(map_mutex_); - auto found = connections_.find(sn); + auto found = connections_.find(remote_id); if (found == connections_.end()) { return nullptr; } return found->second; } -std::shared_ptr ConnectionPool::GetNew(const ServerName &sn) { +std::shared_ptr ConnectionPool::GetNewConnection( + std::shared_ptr remote_id) { // Grab the upgrade lock. While we are double checking other readers can // continue on SharedMutexWritePriority::UpgradeHolder u_holder{map_mutex_}; @@ -76,7 +78,7 @@ std::shared_ptr ConnectionPool::GetNew(const ServerName &sn) { // Now check if someone else created the connection before we got the lock // This is safe since we hold the upgrade lock. // upgrade lock is more power than the reader lock. - auto found = connections_.find(sn); + auto found = connections_.find(remote_id); if (found != connections_.end() && found->second != nullptr) { return found->second; } else { @@ -84,24 +86,33 @@ std::shared_ptr ConnectionPool::GetNew(const ServerName &sn) { SharedMutexWritePriority::WriteHolder w_holder{std::move(u_holder)}; // Make double sure there are not stale connections hanging around. - connections_.erase(sn); - - // Nope we are the ones who should create the new connection. - auto client = cf_->MakeBootstrap(); - auto dispatcher = cf_->Connect(client, sn.host_name(), sn.port()); - clients_.insert(std::make_pair(sn, client)); - connections_.insert(std::make_pair(sn, dispatcher)); - return dispatcher; + connections_.erase(remote_id); + + /* create new connection */ + auto clientBootstrap = cf_->MakeBootstrap(); + auto dispatcher = cf_->Connect( + clientBootstrap, + remote_id->host(), + remote_id->port()); + + auto conneciton = std::make_shared( + remote_id, + dispatcher); + + connections_.insert(std::make_pair(remote_id, conneciton)); + clients_.insert(std::make_pair(remote_id, clientBootstrap)); + + return conneciton; } } -void ConnectionPool::Close(const ServerName &sn) { +void ConnectionPool::Close(std::shared_ptr remote_id) { SharedMutexWritePriority::WriteHolder holder{map_mutex_}; - auto found = connections_.find(sn); + auto found = connections_.find(remote_id); if (found == connections_.end() || found->second == nullptr) { return; } - auto service = found->second; + found->second->Close(); connections_.erase(found); } diff --git a/hbase-native-client/connection/connection-pool.h b/hbase-native-client/connection/connection-pool.h index b8c950b..4b992b9 100644 --- a/hbase-native-client/connection/connection-pool.h +++ b/hbase-native-client/connection/connection-pool.h @@ -27,36 +27,21 @@ #include "connection/service.h" #include "if/HBase.pb.h" -namespace hbase { - -/** Equals function for server name that ignores start time */ -struct ServerNameEquals { +#include "connection-id.h" +#include "rpc-connection.h" - /** equals */ - bool operator()(const hbase::pb::ServerName &lhs, - const hbase::pb::ServerName &rhs) const { - return lhs.host_name() == rhs.host_name() && lhs.port() == rhs.port(); - } -}; +using hbase::ConnectionId; +using hbase::ConnectionIdEquals; +using hbase::ConnectionIdHash; +using hbase::RpcConnection; -/** Hash for ServerName that ignores the start time. */ -struct ServerNameHash { - /** hash */ - std::size_t operator()(hbase::pb::ServerName const &s) const { - std::size_t h = 0; - boost::hash_combine(h, s.host_name()); - boost::hash_combine(h, s.port()); - return h; - } -}; +namespace hbase { /** * @brief Connection pooling for HBase rpc connection. * * This is a thread safe connection pool. It allows getting - * a shared connection to HBase by server name. This is - * useful for keeping a single connection no matter how many regions a - * regionserver has on it. + * a shared rpc connection to HBase servers by connection id. */ class ConnectionPool { public: @@ -80,24 +65,25 @@ public: * Get a connection to the server name. Start time is ignored. * This can be a blocking operation for a short time. */ - std::shared_ptr Get(const hbase::pb::ServerName &sn); + std::shared_ptr GetConnection(std::shared_ptr remote_id); /** * Close/remove a connection. */ - void Close(const hbase::pb::ServerName &sn); + void Close(std::shared_ptr remote_id); private: - std::shared_ptr GetCached(const hbase::pb::ServerName &sn); - std::shared_ptr GetNew(const hbase::pb::ServerName &sn); - std::unordered_map, - ServerNameHash, ServerNameEquals> - connections_; + std::shared_ptr GetCachedConnection(std::shared_ptr remote_id); + std::shared_ptr GetNewConnection(std::shared_ptr remote_id); + std::unordered_map< + std::shared_ptr, + std::shared_ptr, + ConnectionIdHash, + ConnectionIdEquals> connections_; std::unordered_map< - hbase::pb::ServerName, + std::shared_ptr, std::shared_ptr>, - ServerNameHash, ServerNameEquals> - clients_; + ConnectionIdHash, ConnectionIdEquals> clients_; folly::SharedMutexWritePriority map_mutex_; std::shared_ptr cf_; }; diff --git a/hbase-native-client/connection/rpc-client.cc b/hbase-native-client/connection/rpc-client.cc new file mode 100644 index 0000000..8cf9255 --- /dev/null +++ b/hbase-native-client/connection/rpc-client.cc @@ -0,0 +1,148 @@ +/* + * 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 "rpc-client.h" +#include +#include + +using hbase::RpcClient; +using hbase::AbstractRpcChannel; + +namespace hbase { + +class RpcChannelImplementation : public AbstractRpcChannel { +public: + RpcChannelImplementation( + std::shared_ptr rpc_client, + const std::string &host, + uint16_t port, + std::shared_ptr ticket, + int rpc_timeout) + : AbstractRpcChannel(rpc_client, host, port, ticket, rpc_timeout) {} + + void CallMethod( + const MethodDescriptor* method, + RpcController* controller, + const Message* request, + Message* response, + Closure* done) override { + + rpc_client_->CallMethod(method, controller, request, response, done, + host_, port_, ticket_); + } +}; +} // namespace hbase + +RpcClient::RpcClient() { + + auto io_executor = + std::make_shared( + sysconf(_SC_NPROCESSORS_ONLN)); + + cp_ = std::make_shared(io_executor); +} + +void RpcClient::Close() { +} + +std::shared_ptr RpcClient::SyncCall( + const std::string &host, + uint16_t port, + std::unique_ptr req, + std::shared_ptr ticket) { + + return std::make_shared( + AsyncCall(host, port, std::move(req), ticket).get()); +} + +std::shared_ptr RpcClient::SyncCall( + const std::string &host, + uint16_t port, + std::unique_ptr req, + std::shared_ptr ticket, + const std::string &service_name) { + + return std::make_shared( + AsyncCall(host, port, std::move(req), ticket, service_name).get()); + +} + +folly::Future RpcClient::AsyncCall( + const std::string &host, + uint16_t port, + std::unique_ptr req, + std::shared_ptr ticket) { + + auto remote_id = std::make_shared(host, port, ticket); + return GetConnection(remote_id)->SendRequest(std::move(req)); +} + +folly::Future RpcClient::AsyncCall( + const std::string &host, + uint16_t port, + std::unique_ptr req, + std::shared_ptr ticket, + const std::string &service_name) { + + auto remote_id = std::make_shared(host, port, ticket, + service_name); + return GetConnection(remote_id)->SendRequest(std::move(req)); +} + + +std::shared_ptr RpcClient::GetConnection( + std::shared_ptr remote_id) { + return cp_->GetConnection(remote_id); +} + + +std::shared_ptr RpcClient::CreateRpcChannel(const std::string &host, + uint16_t port, std::shared_ptr ticket, int rpc_timeout) { + + std::shared_ptr channel = std::make_shared< + RpcChannelImplementation>(shared_from_this(), host, port, ticket, + rpc_timeout); + + /* static_pointer_cast is safe since RpcChannelImplementation derives + * from RpcChannel, otherwise, dynamic_pointer_cast should be used. */ + return std::static_pointer_cast(channel); +} + +void RpcClient::CallMethod( + const MethodDescriptor* method, + RpcController* controller, + const Message* req_msg, + Message* resp_msg, + Closure* done, + const std::string &host, + uint16_t port, + std::shared_ptr ticket) { + + std::shared_ptr shared_req(const_cast(req_msg)); + std::shared_ptr shared_resp(resp_msg); + + std::unique_ptr req = + std::make_unique(shared_req, shared_resp, method->name()); + + AsyncCall(host, port, std::move(req), ticket).then( + [done, this] (Response resp) { + done->Run(); + }); +} + diff --git a/hbase-native-client/connection/rpc-client.h b/hbase-native-client/connection/rpc-client.h new file mode 100644 index 0000000..adb25f0 --- /dev/null +++ b/hbase-native-client/connection/rpc-client.h @@ -0,0 +1,128 @@ +/* + * 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 "connection/request.h" +#include "connection/response.h" +#include "connection/connection-pool.h" +#include "connection-id.h" +#include "security/user.h" + +#include + +using hbase::security::User; +using hbase::pb::ServerName; +using hbase::Request; +using hbase::Response; +using hbase::ConnectionId; +using hbase::ConnectionPool; +using hbase::RpcConnection; +using hbase::security::User; + +using google::protobuf::MethodDescriptor; +using google::protobuf::RpcChannel; +using google::protobuf::Message; +using google::protobuf::RpcController; +using google::protobuf::Closure; + +class RpcChannelImplementation; + +namespace hbase { + +class RpcClient: public std::enable_shared_from_this { + + friend class RpcChannelImplementation; + +public: + RpcClient(); + + virtual ~RpcClient() {Close();} + + virtual std::shared_ptr SyncCall( + const std::string &host, + uint16_t port, + std::unique_ptr req, + std::shared_ptr ticket); + + virtual std::shared_ptr SyncCall( + const std::string &host, + uint16_t port, + std::unique_ptr req, + std::shared_ptr ticket, + const std::string &service_name); + + virtual folly::Future AsyncCall( + const std::string &host, + uint16_t port, + std::unique_ptr req, + std::shared_ptr ticket); + + virtual folly::Future AsyncCall( + const std::string &host, + uint16_t port, + std::unique_ptr req, + std::shared_ptr ticket, + const std::string &service_name); + + virtual void Close(); + + virtual std::shared_ptr CreateRpcChannel(const std::string &host, + uint16_t port, std::shared_ptr ticket, int rpc_timeout); + +private: + void CallMethod( + const MethodDescriptor* method, + RpcController* controller, + const Message* req_msg, + Message* resp_msg, + Closure* done, + const std::string &host, + uint16_t port, + std::shared_ptr ticket); + std::shared_ptr GetConnection(std::shared_ptr remote_id); + +private: + std::shared_ptr cp_; +}; + + + +class AbstractRpcChannel : public RpcChannel { +public: + AbstractRpcChannel( + std::shared_ptr rpc_client, + const std::string &host, + uint16_t port, + std::shared_ptr ticket, + int rpc_timeout) + : rpc_client_(rpc_client), host_(host), + port_(port), ticket_(ticket), + rpc_timeout_(rpc_timeout) {} + + virtual ~AbstractRpcChannel() = default; + +protected: + std::shared_ptr rpc_client_; + std::string host_; + uint16_t port_; + std::shared_ptr ticket_; + int rpc_timeout_; +}; +} // namespace hbase diff --git a/hbase-native-client/connection/rpc-connection.h b/hbase-native-client/connection/rpc-connection.h new file mode 100644 index 0000000..0cead70 --- /dev/null +++ b/hbase-native-client/connection/rpc-connection.h @@ -0,0 +1,54 @@ +/* + * 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 "connection-id.h" +#include "connection/request.h" +#include "connection/response.h" +#include "connection/service.h" + +using hbase::HBaseService; + +namespace hbase { +class RpcConnection { +public: + RpcConnection( + std::shared_ptr connection_id, + std::shared_ptr hbase_service) + : connection_id_(connection_id), hbase_service_(hbase_service) {} + + virtual ~RpcConnection() {Close();} + + virtual std::shared_ptr remote_id() const {return connection_id_;} + + virtual std::shared_ptr get_service() const {return hbase_service_;} + + virtual folly::Future SendRequest(std::unique_ptr req) { + return (*hbase_service_)(std::move(req)); + } + + virtual void Close() { + hbase_service_->close(); + } + +private: + std::shared_ptr connection_id_; + std::shared_ptr hbase_service_; +}; +} // namespace hbase diff --git a/hbase-native-client/core/location-cache.cc b/hbase-native-client/core/location-cache.cc index efd2210..3ff3dde 100644 --- a/hbase-native-client/core/location-cache.cc +++ b/hbase-native-client/core/location-cache.cc @@ -29,9 +29,11 @@ #include "serde/region-info.h" #include "serde/server-name.h" #include "serde/zk.h" +#include "connection/rpc-connection.h" using namespace std; using namespace folly; +using hbase::RpcConnection; using wangle::ServiceFilter; using hbase::Request; @@ -115,9 +117,12 @@ Future> LocationCache::LocateFromMeta(const TableName &tn, const string &row) { return this->LocateMeta() .via(cpu_executor_.get()) - .then([this](ServerName sn) { return this->cp_.Get(sn); }) - .then([tn, row, this](std::shared_ptr service) { - return (*service)(std::move(meta_util_.MetaRequest(tn, row))); + .then([this](ServerName sn) { + auto remote_id = std::make_shared(sn.host_name(), sn.port()); + return this->cp_.GetConnection(remote_id); + }) + .then([tn, row, this](std::shared_ptr rpc_connection) { + return (*rpc_connection->get_service())(std::move(meta_util_.MetaRequest(tn, row))); }) .then([this](Response resp) { // take the protobuf response and make it into @@ -133,8 +138,10 @@ LocationCache::LocateFromMeta(const TableName &tn, const string &row) { return rl; }) .then([this](std::shared_ptr rl) { + auto remote_id = std::make_shared( + rl->server_name().host_name(), rl->server_name().port()); // Now fill out the connection. - rl->set_service(cp_.Get(rl->server_name())); + rl->set_service(cp_.GetConnection(remote_id)->get_service()); return rl; }); } diff --git a/hbase-native-client/security/user.h b/hbase-native-client/security/user.h new file mode 100644 index 0000000..914f19a --- /dev/null +++ b/hbase-native-client/security/user.h @@ -0,0 +1,35 @@ +/* + * 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 { +namespace security { +class User { +public: + explicit User(const std::string& user_name) : user_name_(user_name) {} + virtual ~User() = default; + + std::string user_name() {return user_name_;} +private: + std::string user_name_; +}; +} +} -- 2.7.4 (Apple Git-66)