This is an automated email from the ASF dual-hosted git repository.

alexey pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/kudu.git


The following commit(s) were added to refs/heads/master by this push:
     new a6e8aa2fd [tool] Add partitions show with tablet id
a6e8aa2fd is described below

commit a6e8aa2fd5063abb2cc5c8944c9d19fdb38b8aa0
Author: kedeng <kdeng...@gmail.com>
AuthorDate: Tue Jun 14 15:43:05 2022 +0800

    [tool] Add partitions show with tablet id
    
    With this commit help, we can get the corresponding relationship
    between partitions and tablet id. Which will help us to observe
    the partitions more easily.
    
    The command looks like:
    `kudu table list --list_tablets --show_tablet_partition_info <table_name> 
<master_addresses> [-negotiation_timeout_ms=<ms>] [-timeout_ms=<ms>]`
    
    The output of the command looks like:
    `
    TestTableListPartition
      T e72c529ad1a8481390683fd0fe3fb917 : HASH (key_hash0) PARTITION 0, HASH 
(key_hash1, key_hash2) PARTITION 0, RANGE (key_range) PARTITION 0 <= VALUES < 1
        L 8afe7243874943058e849fecebb84d98 127.28.231.1:11503
    
      T 674c732628b74fbab0a03a11f357b432 : HASH (key_hash0) PARTITION 0, HASH 
(key_hash1, key_hash2) PARTITION 0, RANGE (key_range) PARTITION 2 <= VALUES < 3
        L 8afe7243874943058e849fecebb84d98 127.28.231.1:11503
    
      T 1c9a5a6f62d1402aba04dc84f32b6b04 : HASH (key_hash0) PARTITION 0, HASH 
(key_hash1, key_hash2) PARTITION 1, RANGE (key_range) PARTITION 0 <= VALUES < 1
        L 8afe7243874943058e849fecebb84d98 127.28.231.1:11503
    
      T 44046ee1b43a43f4b59dad75f611ac0a : HASH (key_hash0) PARTITION 0, HASH 
(key_hash1, key_hash2) PARTITION 1, RANGE (key_range) PARTITION 2 <= VALUES < 3
        L 8afe7243874943058e849fecebb84d98 127.28.231.1:11503
    
      T 12ca618464074d8a9ae3f9581701bcf0 : HASH (key_hash0) PARTITION 0, HASH 
(key_hash1, key_hash2) PARTITION 2, RANGE (key_range) PARTITION 0 <= VALUES < 1
        L 8afe7243874943058e849fecebb84d98 127.28.231.1:11503
    
      T edc1cbdae0934df9a48866fe65cfbec8 : HASH (key_hash0) PARTITION 0, HASH 
(key_hash1, key_hash2) PARTITION 2, RANGE (key_range) PARTITION 2 <= VALUES < 3
        L 8afe7243874943058e849fecebb84d98 127.28.231.1:11503
    
      T 91ebccd823634878a6e0a8a4e941aa4f : HASH (key_hash0) PARTITION 1, HASH 
(key_hash1, key_hash2) PARTITION 0, RANGE (key_range) PARTITION 0 <= VALUES < 1
        L 8afe7243874943058e849fecebb84d98 127.28.231.1:11503
    
      T 0057ad8aea0d4ad3a626b6417f14bcac : HASH (key_hash0) PARTITION 1, HASH 
(key_hash1, key_hash2) PARTITION 0, RANGE (key_range) PARTITION 2 <= VALUES < 3
        L 8afe7243874943058e849fecebb84d98 127.28.231.1:11503
    
      T de3f9629a97148069aae9e598cb0d3fa : HASH (key_hash0) PARTITION 1, HASH 
(key_hash1, key_hash2) PARTITION 1, RANGE (key_range) PARTITION 0 <= VALUES < 1
        L 8afe7243874943058e849fecebb84d98 127.28.231.1:11503
    
      T d7f9c9103f1943ef9b5131f03e9f8738 : HASH (key_hash0) PARTITION 1, HASH 
(key_hash1, key_hash2) PARTITION 1, RANGE (key_range) PARTITION 2 <= VALUES < 3
        L 8afe7243874943058e849fecebb84d98 127.28.231.1:11503
    
      T 63777094ede14232a5822a3ac50925fd : HASH (key_hash0) PARTITION 1, HASH 
(key_hash1, key_hash2) PARTITION 2, RANGE (key_range) PARTITION 0 <= VALUES < 1
        L 8afe7243874943058e849fecebb84d98 127.28.231.1:11503
    
      T 87f91f80595140fd9c9582a186a3f52b : HASH (key_hash0) PARTITION 1, HASH 
(key_hash1, key_hash2) PARTITION 2, RANGE (key_range) PARTITION 2 <= VALUES < 3
        L 8afe7243874943058e849fecebb84d98 127.28.231.1:11503
     `
    
    Change-Id: Ia9c3b62111c7f302ea934324d1636f79731f18f1
    Reviewed-on: http://gerrit.cloudera.org:8080/18617
    Tested-by: Kudu Jenkins
    Reviewed-by: Alexey Serbin <ale...@apache.org>
---
 src/kudu/client/client-internal.cc               |  23 +++++-
 src/kudu/client/client-internal.h                |  12 ++-
 src/kudu/common/partition.h                      |   2 -
 src/kudu/integration-tests/cluster_itest_util.cc |  18 ++++
 src/kudu/integration-tests/cluster_itest_util.h  |   7 ++
 src/kudu/master/catalog_manager.cc               |  39 ++++++---
 src/kudu/master/catalog_manager.h                |   7 ++
 src/kudu/master/master.proto                     |  10 +++
 src/kudu/tools/kudu-admin-test.cc                | 100 +++++++++++++++++++++++
 src/kudu/tools/tool_action_table.cc              |  50 +++++++++++-
 10 files changed, 248 insertions(+), 20 deletions(-)

diff --git a/src/kudu/client/client-internal.cc 
b/src/kudu/client/client-internal.cc
index 5c650599f..9095ae9c2 100644
--- a/src/kudu/client/client-internal.cc
+++ b/src/kudu/client/client-internal.cc
@@ -444,12 +444,15 @@ Status KuduClient::Data::WaitForAlterTableToFinish(
 
 Status KuduClient::Data::ListTablesWithInfo(KuduClient* client,
                                             vector<TableInfo>* tables_info,
-                                            const string& filter) {
+                                            const string& filter,
+                                            bool list_tablet_with_partition) {
   ListTablesRequestPB req;
   if (!filter.empty()) {
     req.set_name_filter(filter);
   }
 
+  req.set_list_tablet_with_partition(list_tablet_with_partition);
+
   auto deadline = MonoTime::Now() + client->default_admin_operation_timeout();
   Synchronizer sync;
   ListTablesResponsePB resp;
@@ -468,8 +471,26 @@ Status KuduClient::Data::ListTablesWithInfo(KuduClient* 
client,
     info.live_row_count = table.has_live_row_count() ? table.live_row_count() 
: 0;
     info.num_tablets = table.has_num_tablets() ? table.num_tablets() : 0;
     info.num_replicas = table.has_num_replicas() ? table.num_replicas() : 0;
+    if (list_tablet_with_partition) {
+      for (const auto& pt : table.tablet_with_partition()) {
+        Partition partition;
+        Partition::FromPB(pt.partition(), &partition);
+        PartitionWithTabletId partition_with_tablet_id = {pt.tablet_id(), 
std::move(partition)};
+        
info.partition_with_tablet_info.emplace_back(std::move(partition_with_tablet_id));
+      }
+    }
+
+    // sort by range key
+    // Different range partitions of the same table do not intersect.
+    // So we just compare the start/begin key of two ranges.
+    std::sort(info.partition_with_tablet_info.begin(), 
info.partition_with_tablet_info.end(),
+              [] (const PartitionWithTabletId& lhs, const 
PartitionWithTabletId& rhs) {
+      return lhs.partition.begin().range_key() < 
rhs.partition.begin().range_key();
+    });
+
     tables_info->emplace_back(std::move(info));
   }
+
   return Status::OK();
 }
 
diff --git a/src/kudu/client/client-internal.h 
b/src/kudu/client/client-internal.h
index 61661f73b..8a062b2c8 100644
--- a/src/kudu/client/client-internal.h
+++ b/src/kudu/client/client-internal.h
@@ -28,6 +28,7 @@
 
 #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"
@@ -42,7 +43,6 @@
 namespace kudu {
 
 class DnsResolver;
-class PartitionSchema;
 class Sockaddr;
 
 namespace security {
@@ -138,15 +138,23 @@ class KuduClient::Data {
                                           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);
+                                   const std::string& filter,
+                                   bool list_tablet_with_partition = false);
 
   // Open the table identified by 'table_identifier'.
   Status OpenTable(KuduClient* client,
diff --git a/src/kudu/common/partition.h b/src/kudu/common/partition.h
index 7b0878b15..90e67ef6b 100644
--- a/src/kudu/common/partition.h
+++ b/src/kudu/common/partition.h
@@ -24,8 +24,6 @@
 #include <utility>
 #include <vector>
 
-#include <gtest/gtest_prod.h>
-
 #include "kudu/common/schema.h"
 #include "kudu/gutil/port.h"
 #include "kudu/util/slice.h"
diff --git a/src/kudu/integration-tests/cluster_itest_util.cc 
b/src/kudu/integration-tests/cluster_itest_util.cc
index dfdacd804..10a5a68a4 100644
--- a/src/kudu/integration-tests/cluster_itest_util.cc
+++ b/src/kudu/integration-tests/cluster_itest_util.cc
@@ -972,6 +972,24 @@ Status GetTabletLocations(const 
shared_ptr<MasterServiceProxy>& master_proxy,
   return Status::OK();
 }
 
+Status ListTablesWithInfo(const shared_ptr<MasterServiceProxy>& master_proxy,
+                          const string& filter,
+                          const MonoDelta& timeout,
+                          master::ListTablesResponsePB* tables_info) {
+  master::ListTablesRequestPB req;
+  if (!filter.empty()) {
+    req.set_name_filter(filter);
+  }
+  req.set_list_tablet_with_partition(true);
+  rpc::RpcController rpc;
+  rpc.set_timeout(timeout);
+  RETURN_NOT_OK(master_proxy->ListTables(req, tables_info, &rpc));
+  if (tables_info->has_error()) {
+    return StatusFromPB(tables_info->error().status());
+  }
+  return Status::OK();
+}
+
 Status GetTableLocations(const shared_ptr<MasterServiceProxy>& master_proxy,
                          const string& table_name,
                          const MonoDelta& timeout,
diff --git a/src/kudu/integration-tests/cluster_itest_util.h 
b/src/kudu/integration-tests/cluster_itest_util.h
index c716cef63..e1d635cd7 100644
--- a/src/kudu/integration-tests/cluster_itest_util.h
+++ b/src/kudu/integration-tests/cluster_itest_util.h
@@ -342,6 +342,13 @@ Status GetTabletLocations(const 
std::shared_ptr<master::MasterServiceProxy>& mas
                           master::ReplicaTypeFilter filter,
                           master::GetTabletLocationsResponsePB* 
tablet_locations);
 
+// Get information on the specified tables from master.
+// When @filter is not empty, only returns tables that satisfy a substring 
match on filter.
+Status ListTablesWithInfo(const std::shared_ptr<master::MasterServiceProxy>& 
master_proxy,
+                          const std::string& filter,
+                          const MonoDelta& timeout,
+                          master::ListTablesResponsePB* tables_info);
+
 // Get the list of tablet locations for all tablets in the specified table via 
the given
 // table name (and table ID if provided) from the Master.
 Status GetTableLocations(const std::shared_ptr<master::MasterServiceProxy>& 
master_proxy,
diff --git a/src/kudu/master/catalog_manager.cc 
b/src/kudu/master/catalog_manager.cc
index 3048abcad..7476df1a9 100644
--- a/src/kudu/master/catalog_manager.cc
+++ b/src/kudu/master/catalog_manager.cc
@@ -3641,12 +3641,8 @@ Status CatalogManager::ListTables(const 
ListTablesRequestPB* req,
       if (table_name != ltm.data().name()) {
         continue;
       }
-      ListTablesResponsePB::TableInfo* table = resp->add_tables();
-      table->set_id(table_info->id());
-      table->set_name(table_name);
-      
table->set_live_row_count(table_info->GetMetrics()->live_row_count->value());
-      table->set_num_tablets(table_info->num_tablets());
-      table->set_num_replicas(ltm.data().pb.num_replicas());
+      FillListTablesResponse(table_name, table_info, 
ltm.data().pb.num_replicas(),
+                             req->list_tablet_with_partition(), resp);
     }
   } else {
     // Otherwise, pass all tables through.
@@ -3654,17 +3650,36 @@ Status CatalogManager::ListTables(const 
ListTablesRequestPB* req,
       const auto& table_name = name_and_table_info.first;
       const auto& table_info = name_and_table_info.second;
       TableMetadataLock ltm(table_info.get(), LockMode::READ);
-      ListTablesResponsePB::TableInfo* table = resp->add_tables();
-      table->set_id(table_info->id());
-      table->set_name(table_name);
-      
table->set_live_row_count(table_info->GetMetrics()->live_row_count->value());
-      table->set_num_tablets(table_info->num_tablets());
-      table->set_num_replicas(ltm.data().pb.num_replicas());
+      FillListTablesResponse(table_name, table_info, 
ltm.data().pb.num_replicas(),
+                             req->list_tablet_with_partition(), resp);
     }
   }
   return Status::OK();
 }
 
+void CatalogManager::FillListTablesResponse(const string& table_name,
+                                            const scoped_refptr<TableInfo>& 
table_info,
+                                            int replica_num,
+                                            bool list_tablet_with_partition,
+                                            ListTablesResponsePB* resp) {
+  ListTablesResponsePB::TableInfo* table = resp->add_tables();
+  table->set_id(table_info->id());
+  table->set_name(table_name);
+  table->set_live_row_count(table_info->GetMetrics()->live_row_count->value());
+  table->set_num_tablets(table_info->num_tablets());
+  table->set_num_replicas(replica_num);
+  if (list_tablet_with_partition) {
+    const auto& tablet_map = table_info->tablet_map();
+    for (const auto& tablet : tablet_map) {
+      ListTablesResponsePB::TabletWithPartition* tablet_with_partition =
+          table->add_tablet_with_partition();
+      TabletMetadataLock t(tablet.second.get(), LockMode::READ);
+      tablet_with_partition->set_tablet_id(tablet.second->id());
+      tablet_with_partition->mutable_partition()->CopyFrom(
+          tablet.second->metadata().state().pb.partition());
+    }
+  }
+}
 Status CatalogManager::GetTableStatistics(const GetTableStatisticsRequestPB* 
req,
                                           GetTableStatisticsResponsePB* resp,
                                           const optional<string>& user) {
diff --git a/src/kudu/master/catalog_manager.h 
b/src/kudu/master/catalog_manager.h
index 9de7ba230..9282fa28b 100644
--- a/src/kudu/master/catalog_manager.h
+++ b/src/kudu/master/catalog_manager.h
@@ -1146,6 +1146,13 @@ class CatalogManager : public 
tserver::TabletReplicaLookupIf {
 
   void ResetTableLocationsCache();
 
+  // Fill in the reply of ListTables request.
+  static void FillListTablesResponse(const std::string& table_name,
+                                     const scoped_refptr<TableInfo>& 
table_info,
+                                     int replica_num,
+                                     bool list_tablet_with_partition,
+                                     ListTablesResponsePB* resp);
+
   // Task that takes care of deleted tables, is called in a backgroud thread.
   // Clean up the metadata of tables if the time since they were deleted has 
passed
   // 'FLAGS_metadata_for_deleted_table_and_tablet_reserved_secs'.
diff --git a/src/kudu/master/master.proto b/src/kudu/master/master.proto
index e660a74df..d556245fa 100644
--- a/src/kudu/master/master.proto
+++ b/src/kudu/master/master.proto
@@ -591,18 +591,28 @@ message ListTablesRequestPB {
   // interpreted as if it were set to [TableTypePB::DEFAULT_TABLE], meaning
   // to include only user-defined tables.
   repeated TableTypePB type_filter = 2;
+
+  // Set this field 'true' to include information on the partition backed by
+  // each tablet in the result list.
+  optional bool list_tablet_with_partition = 3 [default = false];
 }
 
 message ListTablesResponsePB {
   // The error, if an error occurred with this request.
   optional MasterErrorPB error = 1;
 
+  message TabletWithPartition {
+    optional string tablet_id = 1;
+    optional PartitionPB partition = 2;
+  }
+
   message TableInfo {
     required bytes id = 1;
     required string name = 2;
     optional uint64 live_row_count = 3;
     optional int32 num_tablets = 4;
     optional int32 num_replicas = 5;
+    repeated TabletWithPartition tablet_with_partition = 6;
   }
 
   repeated TableInfo tables = 2;
diff --git a/src/kudu/tools/kudu-admin-test.cc 
b/src/kudu/tools/kudu-admin-test.cc
index 9482afb09..45e66b292 100644
--- a/src/kudu/tools/kudu-admin-test.cc
+++ b/src/kudu/tools/kudu-admin-test.cc
@@ -44,6 +44,8 @@
 #include "kudu/client/write_op.h"
 #include "kudu/common/common.pb.h"
 #include "kudu/common/partial_row.h"
+#include "kudu/common/partition.h"
+#include "kudu/common/schema.h"
 #include "kudu/common/wire_protocol.pb.h"
 #include "kudu/consensus/consensus.pb.h"
 #include "kudu/consensus/metadata.pb.h"
@@ -112,6 +114,7 @@ using kudu::consensus::OpId;
 using kudu::itest::FindTabletFollowers;
 using kudu::itest::FindTabletLeader;
 using kudu::itest::GetConsensusState;
+using kudu::itest::ListTablesWithInfo;
 using kudu::itest::StartElection;
 using kudu::itest::WaitUntilLeader;
 using kudu::itest::TabletServerMap;
@@ -2083,6 +2086,103 @@ TEST_F(AdminCliTest, TestDescribeTableNoOwner) {
   ASSERT_STR_CONTAINS(stdout, "OWNER \n");
 }
 
+TEST_F(AdminCliTest, TestListTabletWithPartition) {
+  FLAGS_num_tablet_servers = 1;
+  FLAGS_num_replicas = 1;
+
+  NO_FATALS(BuildAndStart());
+
+  vector<TServerDetails*> tservers;
+  vector<string> base_tablet_ids;
+  AppendValuesFromMap(tablet_servers_, &tservers);
+  ListRunningTabletIds(tservers.front(),
+                       MonoDelta::FromSeconds(30), &base_tablet_ids);
+
+  // Test a table with all types in its schema, multiple hash partitioning
+  // levels, multiple range partitions, and non-covered ranges.
+  const string kTableId = "TestTableListPartition";
+  KuduSchema schema;
+
+  // Build the schema.
+  {
+    KuduSchemaBuilder builder;
+    builder.AddColumn("key_hash0")->Type(KuduColumnSchema::INT32)->NotNull();
+    builder.AddColumn("key_hash1")->Type(KuduColumnSchema::INT32)->NotNull();
+    builder.AddColumn("key_hash2")->Type(KuduColumnSchema::INT32)->NotNull();
+    builder.AddColumn("key_range")->Type(KuduColumnSchema::INT32)->NotNull();
+    builder.SetPrimaryKey({ "key_hash0", "key_hash1", "key_hash2", "key_range" 
});
+    ASSERT_OK(builder.Build(&schema));
+  }
+
+  // Set up partitioning and create the table.
+  {
+    unique_ptr<KuduPartialRow> lower_bound0(schema.NewRow());
+    ASSERT_OK(lower_bound0->SetInt32("key_range", 0));
+    unique_ptr<KuduPartialRow> upper_bound0(schema.NewRow());
+    ASSERT_OK(upper_bound0->SetInt32("key_range", 1));
+    unique_ptr<KuduPartialRow> lower_bound1(schema.NewRow());
+    ASSERT_OK(lower_bound1->SetInt32("key_range", 2));
+    unique_ptr<KuduPartialRow> upper_bound1(schema.NewRow());
+    ASSERT_OK(upper_bound1->SetInt32("key_range", 3));
+    unique_ptr<KuduTableCreator> table_creator(client_->NewTableCreator());
+    ASSERT_OK(table_creator->table_name(kTableId)
+        .schema(&schema)
+        .add_hash_partitions({"key_hash0"}, 2)
+        .add_hash_partitions({"key_hash1", "key_hash2"}, 3)
+        .set_range_partition_columns({"key_range"})
+        .add_range_partition(lower_bound0.release(), upper_bound0.release())
+        .add_range_partition(lower_bound1.release(), upper_bound1.release())
+        .num_replicas(FLAGS_num_replicas)
+        .Create());
+  }
+
+  vector<string> new_tablet_ids;
+  ListRunningTabletIds(tservers.front(),
+                       MonoDelta::FromSeconds(30), &new_tablet_ids);
+  vector<string> delta_tablet_ids;
+  for (auto& tablet_id : base_tablet_ids) {
+    if (std::find(new_tablet_ids.begin(), new_tablet_ids.end(), tablet_id) ==
+        new_tablet_ids.end()) {
+      delta_tablet_ids.push_back(tablet_id);
+    }
+  }
+
+  // Test the list tablet with partition output.
+  string stdout;
+  string stderr;
+  Status s = RunKuduTool({
+    "table",
+    "list",
+    "--list_tablets",
+    "--show_tablet_partition_info",
+    "--tables",
+    kTableId,
+    cluster_->master()->bound_rpc_addr().ToString(),
+  }, &stdout, &stderr);
+  ASSERT_TRUE(s.ok()) << ToolRunInfo(s, stdout, stderr);
+
+  client::sp::shared_ptr<KuduTable> table;
+  ASSERT_OK(client_->OpenTable(kTableId, &table));
+  const auto& partition_schema = table->partition_schema();
+  const auto& schema_internal = KuduSchema::ToSchema(table->schema());
+
+  // make sure table name correct
+  ASSERT_STR_CONTAINS(stdout, kTableId);
+
+  master::ListTablesResponsePB tables_info;
+  ASSERT_OK(ListTablesWithInfo(cluster_->master_proxy(), kTableId,
+                               MonoDelta::FromSeconds(30), &tables_info));
+  for (const auto& table : tables_info.tables()) {
+    for (const auto& pt : table.tablet_with_partition()) {
+      Partition partition;
+      Partition::FromPB(pt.partition(), &partition);
+      string partition_str = partition_schema.PartitionDebugString(partition, 
schema_internal);
+      string tablet_with_partition = pt.tablet_id() + " : " + partition_str;
+      ASSERT_STR_CONTAINS(stdout, tablet_with_partition);
+    }
+  }
+}
+
 TEST_F(AdminCliTest, TestLocateRow) {
   FLAGS_num_tablet_servers = 1;
   FLAGS_num_replicas = 1;
diff --git a/src/kudu/tools/tool_action_table.cc 
b/src/kudu/tools/tool_action_table.cc
index e68c6f1f7..f6f82bbaa 100644
--- a/src/kudu/tools/tool_action_table.cc
+++ b/src/kudu/tools/tool_action_table.cc
@@ -109,6 +109,20 @@ DEFINE_bool(list_tablets, false,
 DEFINE_bool(show_table_info, false,
             "Include extra information such as number of tablets, replicas, "
             "and live row count for a table in the output");
+DEFINE_bool(show_tablet_partition_info, false,
+            "Include partition keys information corresponding to tablet in the 
output.");
+
+bool ValidateShowTabletPartitionInfo() {
+  if (!FLAGS_list_tablets && FLAGS_show_tablet_partition_info) {
+    LOG(ERROR) << Substitute("--show_tablet_partition_info is meaningless "
+                             "when --list_tablets=false");
+    return false;
+  }
+  return true;
+}
+
+GROUP_FLAG_VALIDATOR(show_tablet_partition_info, 
ValidateShowTabletPartitionInfo);
+
 DEFINE_bool(modify_external_catalogs, true,
             "Whether to modify external catalogs, such as the Hive Metastore, "
             "when renaming or dropping a table.");
@@ -167,14 +181,35 @@ namespace tools {
 // KuduReplica, KuduReplica::Data, and KuduClientBuilder.
 class TableLister {
  public:
+  static string SearchPartitionInfo(const KuduClient::Data::TableInfo& 
table_info,
+                                    const client::sp::shared_ptr<KuduTable>& 
table,
+                                    const string& tablet_id) {
+    string pinfo;
+    const auto& partition_with_tablet_info = 
table_info.partition_with_tablet_info;
+    for (const auto& pt : partition_with_tablet_info) {
+      if (tablet_id != pt.tablet_id) {
+        continue;
+      }
+
+      const auto& schema_internal = KuduSchema::ToSchema(table->schema());
+      const auto& partition_schema = table->partition_schema();
+      pinfo = partition_schema.PartitionDebugString(pt.partition, 
schema_internal);
+      break;
+    }
+    return pinfo;
+  }
+
   static Status ListTablets(const vector<string>& master_addresses) {
     client::sp::shared_ptr<KuduClient> client;
     RETURN_NOT_OK(CreateKuduClient(master_addresses,
                                    &client,
-                                   true /* can_see_all_replicas */));
+                                   true/* can_see_all_replicas */));
     vector<kudu::client::KuduClient::Data::TableInfo> tables_info;
     RETURN_NOT_OK(client->data_->ListTablesWithInfo(
-        client.get(), &tables_info, "" /* filter */));
+                                          client.get(),
+                                          &tables_info,
+                                          "" /* filter */,
+                                          FLAGS_show_tablet_partition_info));
 
     vector<string> table_filters = Split(FLAGS_tables, ",", 
strings::SkipEmpty());
     for (const auto& tinfo : tables_info) {
@@ -187,9 +222,11 @@ class TableLister {
       } else {
         cout << tname << endl;
       }
+
       if (!FLAGS_list_tablets) {
         continue;
       }
+
       client::sp::shared_ptr<KuduTable> client_table;
       RETURN_NOT_OK(client->OpenTable(tname, &client_table));
       vector<KuduScanToken*> tokens;
@@ -198,7 +235,12 @@ class TableLister {
       RETURN_NOT_OK(builder.Build(&tokens));
 
       for (const auto* token : tokens) {
-        cout << "  T " << token->tablet().id() << endl;
+        string partition_info;
+        string tablet_id = token->tablet().id();
+        if (FLAGS_show_tablet_partition_info) {
+          partition_info = " : " + SearchPartitionInfo(tinfo, client_table, 
tablet_id);
+        }
+        cout << "  T " << tablet_id << partition_info << endl;
         for (const auto* replica : token->tablet().replicas()) {
           const bool is_voter = ReplicaController::is_voter(*replica);
           const bool is_leader = replica->is_leader();
@@ -210,6 +252,7 @@ class TableLister {
       }
       cout << endl;
     }
+
     return Status::OK();
   }
 };
@@ -1504,6 +1547,7 @@ unique_ptr<Mode> BuildTableMode() {
       .Description("List tables")
       .AddOptionalParameter("tables")
       .AddOptionalParameter("list_tablets")
+      .AddOptionalParameter("show_tablet_partition_info")
       .AddOptionalParameter("show_table_info")
       .Build();
 

Reply via email to