blob: 3e820f91ff4123b995bcd838817664a5e92fa96d [file] [log] [blame]
// 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 <cstdint>
#include <functional>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <unordered_set>
#include <utility>
#include <vector>
#include "kudu/client/authz_token_cache.h"
#include "kudu/client/client.h"
#include "kudu/common/partition.h"
#include "kudu/gutil/macros.h"
#include "kudu/gutil/ref_counted.h"
#include "kudu/rpc/rpc_controller.h"
#include "kudu/rpc/user_credentials.h"
#include "kudu/util/atomic.h"
#include "kudu/util/locks.h"
#include "kudu/util/monotime.h"
#include "kudu/util/net/net_util.h"
#include "kudu/util/status.h"
#include "kudu/util/status_callback.h"
namespace kudu {
class DnsResolver;
class Sockaddr;
namespace security {
class SignedTokenPB;
} // namespace security
namespace master {
class AlterTableRequestPB;
class AlterTableResponsePB;
class ConnectToMasterResponsePB;
class CreateTableRequestPB;
class CreateTableResponsePB;
class ListTabletServersRequestPB;
class ListTabletServersResponsePB;
class MasterServiceProxy;
class TableIdentifierPB;
} // namespace master
namespace rpc {
class Messenger;
class RequestTracker;
} // namespace rpc
namespace transactions {
class TxnManagerServiceProxy;
} // namespace transactions
namespace client {
class KuduSchema;
namespace internal {
class ConnectToClusterRpc;
class MetaCache;
class RemoteTablet;
class RemoteTabletServer;
} // namespace internal
class KuduClient::Data {
public:
static const uint32_t kSoftDeletedTableReservationSeconds = 60 * 60 * 24 * 7;
Data();
~Data();
// Selects a TS replica from the given RemoteTablet subject
// to liveness and the provided selection criteria and blacklist.
//
// If no appropriate replica can be found, a non-OK status is returned and 'ts' is untouched.
//
// The 'candidates' return parameter indicates tservers that are live and meet the selection
// criteria, but are possibly filtered by the blacklist. This is useful for implementing
// retry logic.
Status GetTabletServer(KuduClient* client,
const scoped_refptr<internal::RemoteTablet>& rt,
ReplicaSelection selection,
const std::set<std::string>& blacklist,
std::vector<internal::RemoteTabletServer*>* candidates,
internal::RemoteTabletServer** ts);
static Status CreateTable(KuduClient* client,
const master::CreateTableRequestPB& req,
master::CreateTableResponsePB* resp,
const MonoTime& deadline,
bool has_range_partition_bounds,
bool has_range_specific_hash_schema);
static Status IsCreateTableInProgress(KuduClient* client,
master::TableIdentifierPB table,
const MonoTime& deadline,
bool* create_in_progress);
static Status WaitForCreateTableToFinish(KuduClient* client,
master::TableIdentifierPB table,
const MonoTime& deadline);
static Status DeleteTable(KuduClient* client,
const std::string& table_name,
const MonoTime& deadline,
bool modify_external_catalogs = true,
uint32_t reserve_seconds = kSoftDeletedTableReservationSeconds);
static Status RecallTable(KuduClient* client,
const std::string& table_id,
const MonoTime& deadline,
const std::string& new_table_name = "");
static Status AlterTable(KuduClient* client,
const master::AlterTableRequestPB& req,
master::AlterTableResponsePB* resp,
const MonoTime& deadline,
bool has_add_drop_partition,
bool adding_range_with_custom_hash_schema);
static Status IsAlterTableInProgress(KuduClient* client,
master::TableIdentifierPB table,
const MonoTime& deadline,
bool* alter_in_progress);
static Status WaitForAlterTableToFinish(KuduClient* client,
master::TableIdentifierPB table,
const MonoTime& deadline);
struct PartitionWithTabletId {
std::string tablet_id;
Partition partition;
};
struct TableInfo {
std::string table_name;
uint64_t live_row_count;
int num_tablets;
int num_replicas;
std::vector<PartitionWithTabletId> partition_with_tablet_info;
};
static Status ListTablesWithInfo(KuduClient* client,
std::vector<TableInfo>* tables_info,
const std::string& filter,
bool list_tablet_with_partition = false,
bool show_soft_deleted = false);
// Open the table identified by 'table_identifier'.
Status OpenTable(KuduClient* client,
const master::TableIdentifierPB& table_identifier,
client::sp::shared_ptr<KuduTable>* table);
// Get the table information identified by 'table_identifier'.
// The table information (they can be null):
// 'schema' The schema for the table.
// 'partition_schema' The partition schema for the table.
// 'table_id' The table unique id.
// 'table_name' The table unique name.
// 'num_replicas' The table replication factor.
// 'owner' The owner of the table.
// 'comment' The comment for the table.
// 'extra_configs' The table's extra configuration properties.
Status GetTableSchema(KuduClient* client,
const MonoTime& deadline,
const master::TableIdentifierPB& table,
KuduSchema* schema,
PartitionSchema* partition_schema,
std::string* table_id,
std::string* table_name,
int* num_replicas,
std::string* owner,
std::string* comment,
std::map<std::string, std::string>* extra_configs);
Status InitLocalHostNames();
bool IsLocalHostPort(const HostPort& hp) const;
bool IsTabletServerLocal(const internal::RemoteTabletServer& rts) const;
Status ListTabletServers(KuduClient* client,
const MonoTime& deadline,
const master::ListTabletServersRequestPB& req,
master::ListTabletServersResponsePB* resp) const;
// Returns a non-failed replica of the specified tablet based on the provided
// selection criteria and tablet server blacklist.
//
// Returns NULL if there are no valid tablet servers.
internal::RemoteTabletServer* SelectTServer(
const scoped_refptr<internal::RemoteTablet>& rt,
const ReplicaSelection selection,
const std::set<std::string>& blacklist,
std::vector<internal::RemoteTabletServer*>* candidates) const;
// Sets 'master_proxy_' from the address specified by 'leader_addr'.
// Called by ConnectToClusterRpc::SendRpcCb() upon successful completion.
//
// See also: ConnectToClusterAsync.
void ConnectedToClusterCb(const Status& status,
const std::pair<Sockaddr, std::string>& leader_addr_and_name,
const master::ConnectToMasterResponsePB& connect_response,
rpc::CredentialsPolicy cred_policy);
// Asynchronously sets 'master_proxy_' to the leader master by
// cycling through servers listed in 'master_server_addrs_' until
// one responds with a Raft configuration that contains the leader
// master or 'deadline' expires.
//
// Invokes 'cb' with the appropriate status when finished.
//
// Works with both a distributed and non-distributed configuration.
void ConnectToClusterAsync(KuduClient* client,
const MonoTime& deadline,
const StatusCallback& cb,
rpc::CredentialsPolicy creds_policy);
// Synchronous version of ConnectToClusterAsync method above.
//
// NOTE: since this uses a Synchronizer, this may not be invoked by
// a method that's on a reactor thread.
Status ConnectToCluster(
KuduClient* client,
const MonoTime& deadline,
rpc::CredentialsPolicy creds_policy = rpc::CredentialsPolicy::ANY_CREDENTIALS);
// Asynchronously fetches an authz token from the master for the given table.
//
// Invokes 'cb' with the appropriate status when finished.
void RetrieveAuthzTokenAsync(const KuduTable* table,
const StatusCallback& cb,
const MonoTime& deadline);
// Synchronous version of RetrieveAuthzTokenAsync.
//
// NOTE: since this uses a Synchronizer, this may not be invoked by a method
// that's on a reactor thread.
Status RetrieveAuthzToken(const KuduTable* table, const MonoTime& deadline);
// Fetches the cached authz token for the given table ID, returning false if
// no such token exists.
bool FetchCachedAuthzToken(const std::string& table_id, security::SignedTokenPB* token);
// Stores the token into the cache, associating it with the given table ID.
void StoreAuthzToken(const std::string& table_id,
const security::SignedTokenPB& token);
std::shared_ptr<master::MasterServiceProxy> master_proxy() const;
std::shared_ptr<transactions::TxnManagerServiceProxy> txn_manager_proxy() const;
HostPort leader_master_hostport() const;
std::vector<HostPort> master_hostports() const;
std::string location() const;
std::string cluster_id() const;
uint64_t GetLatestObservedTimestamp() const;
void UpdateLatestObservedTimestamp(uint64_t timestamp);
// The unique id of this client.
std::string client_id_;
// The location of this client. This is an empty string if a location has not
// been assigned by the leader master. Protected by 'leader_master_lock_'.
std::string location_;
// The ID of the cluster that this client is connected to.
// Protected by 'leader_master_lock_'.
std::string cluster_id_;
// The user credentials of the client. This field is constant after the client
// is built.
rpc::UserCredentials user_credentials_;
// The request tracker for this client.
scoped_refptr<rpc::RequestTracker> request_tracker_;
std::unique_ptr<DnsResolver> dns_resolver_;
std::shared_ptr<rpc::Messenger> messenger_;
scoped_refptr<internal::MetaCache> meta_cache_;
// Authorization tokens stored for each table, indexed by table ID. Note that
// these may be expired, and it is up to the user of a token to refresh it
// upon learning of its expiration.
internal::AuthzTokenCache authz_token_cache_;
// Set of hostnames and IPs on the local host.
// This is initialized at client startup.
std::unordered_set<std::string> local_host_names_;
// Options the client was built with.
std::vector<std::string> master_server_addrs_;
MonoDelta default_admin_operation_timeout_;
MonoDelta default_rpc_timeout_;
MonoDelta connection_negotiation_timeout_;
// The host port of the leader master. This is set in
// ConnectedToClusterCb, which is invoked as a callback by
// ConnectToClusterAsync.
HostPort leader_master_hostport_;
// The master RPC host ports as configured on the most recently connected to
// leader master in ConnectedToClusterCb.
std::vector<HostPort> master_hostports_;
// The Hive Metastore configuration of the most recently connected to leader
// master, or an empty string if the leader master is not configured to
// integrate with a Hive Metastore.
std::string hive_metastore_uris_;
bool hive_metastore_sasl_enabled_;
std::string hive_metastore_uuid_;
// Proxy to the leader master.
std::shared_ptr<master::MasterServiceProxy> master_proxy_;
// A proxy to TxnManagerService instance. As of now, every master hosts
// a TxnManagerService, so it's easy to find one.
//
// TODO(aserbin): switch to multiple (per-master) proxies from TxnManager
// and distribute transaction-related requests among those
std::shared_ptr<transactions::TxnManagerServiceProxy> txn_manager_proxy_;
// Ref-counted RPC instance: since 'ConnectToClusterAsync' call
// is asynchronous, we need to hold a reference in this class
// itself, as to avoid a "use-after-free" scenario.
scoped_refptr<internal::ConnectToClusterRpc> leader_master_rpc_any_creds_;
std::vector<StatusCallback> leader_master_callbacks_any_creds_;
scoped_refptr<internal::ConnectToClusterRpc> leader_master_rpc_primary_creds_;
std::vector<StatusCallback> leader_master_callbacks_primary_creds_;
// Protects 'leader_master_rpc_{any,primary}_creds_',
// 'leader_master_hostport_', 'master_hostports_', 'master_proxy_',
// 'location_', and 'cluster_id'.
//
// See: KuduClient::Data::ConnectToClusterAsync for a more
// in-depth explanation of why this is needed and how it works.
mutable simple_spinlock leader_master_lock_;
AtomicInt<uint64_t> latest_observed_timestamp_;
private:
DISALLOW_COPY_AND_ASSIGN(Data);
};
// Retry helper, takes a function like: Status funcName(const MonoTime& deadline, bool *retry, ...)
// The function should set the retry flag (default true) if the function should
// be retried again. On retry == false the return status of the function will be
// returned to the caller, otherwise a Status::Timeout() will be returned.
// If the deadline is already expired, no attempt will be made.
Status RetryFunc(const MonoTime& deadline,
const std::string& retry_msg,
const std::string& timeout_msg,
const std::function<Status(const MonoTime&, bool*)>& func);
// Set logging verbose level through environment variable.
void SetVerboseLevelFromEnvVar();
extern const char* kVerboseEnvVar;
} // namespace client
} // namespace kudu