You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kudu.apache.org by wd...@apache.org on 2019/02/15 23:37:52 UTC

[kudu] 02/02: [tools] Add useful flags to 'kudu remote_replica list'

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

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

commit df105295b3da8515992815c6cddabb031fc7b089
Author: Will Berkeley <wd...@gmail.org>
AuthorDate: Mon Feb 11 14:28:40 2019 -0800

    [tools] Add useful flags to 'kudu remote_replica list'
    
    1. --include_schema: The ability to exclude schema.
    2. --table_name and --tablets: The ability to filter on tablet id, table name.
    
    Change-Id: I462515f1bc3e8487185aebb6cb99d1c5c00cea40
    Reviewed-on: http://gerrit.cloudera.org:8080/12450
    Reviewed-by: Adar Dembo <ad...@cloudera.com>
    Reviewed-by: Alexey Serbin <as...@cloudera.com>
    Tested-by: Kudu Jenkins
---
 src/kudu/tools/kudu-tool-test.cc             | 102 +++++++++++++++++++++------
 src/kudu/tools/tool_action_remote_replica.cc |  30 +++++++-
 2 files changed, 108 insertions(+), 24 deletions(-)

diff --git a/src/kudu/tools/kudu-tool-test.cc b/src/kudu/tools/kudu-tool-test.cc
index f6542c0..6e3909e 100644
--- a/src/kudu/tools/kudu-tool-test.cc
+++ b/src/kudu/tools/kudu-tool-test.cc
@@ -1913,31 +1913,87 @@ TEST_F(ToolTest, TestRemoteReplicaList) {
   vector<ListTabletsResponsePB::StatusAndSchemaPB> tablets;
   ASSERT_OK(WaitForNumTabletsOnTS(ts, kNumTablets, kTimeout, &tablets));
   const string& ts_addr = cluster_->tablet_server(0)->bound_rpc_addr().ToString();
-  string stdout;
-  NO_FATALS(RunActionStdoutString(
-        Substitute("remote_replica list $0", ts_addr), &stdout));
-  const auto& tablet_status = tablets[0].tablet_status();
 
-  // Some fields like state or estimated on disk size may vary. Just check a
-  // few whose values we should know exactly.
-  ASSERT_STR_CONTAINS(stdout,
-                      Substitute("Tablet id: $0", tablet_status.tablet_id()));
-  ASSERT_STR_CONTAINS(stdout,
-                      Substitute("Table name: $0", workload.table_name()));
-  ASSERT_STR_CONTAINS(stdout,
-      Substitute("Data dirs: $0", JoinStrings(tablet_status.data_dirs(), ", ")));
-
-  // Tombstone the replica and try again.
-  ASSERT_OK(DeleteTablet(ts, tablet_status.tablet_id(),
-                         TabletDataState::TABLET_DATA_TOMBSTONED, kTimeout));
-  NO_FATALS(RunActionStdoutString(
+  const auto& tablet_status = tablets[0].tablet_status();
+  {
+    // Test the basic case.
+    string stdout;
+    NO_FATALS(RunActionStdoutString(
         Substitute("remote_replica list $0", ts_addr), &stdout));
-  ASSERT_STR_CONTAINS(stdout,
-                      Substitute("Tablet id: $0", tablet_status.tablet_id()));
-  ASSERT_STR_CONTAINS(stdout,
-                      Substitute("Table name: $0", workload.table_name()));
-  ASSERT_STR_CONTAINS(stdout,
-      Substitute("Data dirs: $0", JoinStrings(tablet_status.data_dirs(), ", ")));
+
+    // Some fields like state or estimated on disk size may vary. Just check a
+    // few whose values we should know exactly.
+    ASSERT_STR_CONTAINS(stdout,
+                        Substitute("Tablet id: $0", tablet_status.tablet_id()));
+    ASSERT_STR_CONTAINS(stdout,
+                        Substitute("Table name: $0", workload.table_name()));
+    ASSERT_STR_CONTAINS(stdout, "key INT32 NOT NULL");
+    ASSERT_STR_CONTAINS(stdout,
+        Substitute("Data dirs: $0", JoinStrings(tablet_status.data_dirs(), ", ")));
+  }
+
+  {
+    // Test we lose the schema with --include_schema=false.
+    string stdout;
+    NO_FATALS(RunActionStdoutString(
+          Substitute("remote_replica list $0 --include_schema=false", ts_addr),
+          &stdout));
+    ASSERT_STR_NOT_CONTAINS(stdout, "key INT32 NOT NULL");
+  }
+
+  {
+    // Test we see the tablet when matching on wrong tablet id or wrong table
+    // name.
+    string stdout;
+    NO_FATALS(RunActionStdoutString(
+          Substitute("remote_replica list $0 --table_name=$1",
+                     ts_addr, workload.table_name()),
+          &stdout));
+    ASSERT_STR_CONTAINS(stdout,
+                        Substitute("Tablet id: $0",
+                                   tablet_status.tablet_id()));
+    stdout.clear();
+    NO_FATALS(RunActionStdoutString(
+          Substitute("remote_replica list $0 --tablets=$1",
+                     ts_addr, tablet_status.tablet_id()),
+          &stdout));
+    ASSERT_STR_CONTAINS(stdout,
+                        Substitute("Tablet id: $0",
+                                   tablet_status.tablet_id()));
+  }
+
+  {
+    // Test we lose the tablet when matching on the wrong tablet id or the wrong
+    // table name.
+    string stdout;
+    NO_FATALS(RunActionStdoutString(
+          Substitute("remote_replica list $0 --table_name=foo", ts_addr),
+          &stdout));
+    ASSERT_STR_NOT_CONTAINS(stdout,
+                            Substitute("Tablet id: $0",
+                                       tablet_status.tablet_id()));
+    stdout.clear();
+    NO_FATALS(RunActionStdoutString(
+          Substitute("remote_replica list $0 --tablets=foo", ts_addr),
+          &stdout));
+    ASSERT_STR_NOT_CONTAINS(stdout,
+                            Substitute("Tablet id: $0",
+                                       tablet_status.tablet_id()));
+  }
+
+  {
+    // Finally, tombstone the replica and try again.
+    string stdout;
+    ASSERT_OK(DeleteTablet(ts, tablet_status.tablet_id(),
+                           TabletDataState::TABLET_DATA_TOMBSTONED, kTimeout));
+    NO_FATALS(RunActionStdoutString(
+          Substitute("remote_replica list $0", ts_addr), &stdout));
+    ASSERT_STR_CONTAINS(stdout,
+                        Substitute("Tablet id: $0", tablet_status.tablet_id()));
+    ASSERT_STR_CONTAINS(stdout,
+                        Substitute("Table name: $0", workload.table_name()));
+    ASSERT_STR_CONTAINS(stdout, "Data dirs: <not available>");
+  }
 }
 
 // Test 'kudu local_replica delete' tool with --clean_unsafe flag for
diff --git a/src/kudu/tools/tool_action_remote_replica.cc b/src/kudu/tools/tool_action_remote_replica.cc
index 6323f9b..e3b12b1 100644
--- a/src/kudu/tools/tool_action_remote_replica.cc
+++ b/src/kudu/tools/tool_action_remote_replica.cc
@@ -21,6 +21,7 @@
 #include <memory>
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <utility>
 #include <vector>
 
@@ -44,6 +45,7 @@
 #include "kudu/gutil/map-util.h"
 #include "kudu/gutil/strings/human_readable.h"
 #include "kudu/gutil/strings/join.h"
+#include "kudu/gutil/strings/split.h"
 #include "kudu/gutil/strings/substitute.h"
 #include "kudu/rpc/rpc_controller.h"
 #include "kudu/server/server_base.pb.h"
@@ -62,6 +64,10 @@
 
 DEFINE_bool(force_copy, false,
             "Force the copy when the destination tablet server has this replica");
+DEFINE_bool(include_schema, true,
+            "Whether to include the schema of each replica");
+DECLARE_string(table_name);
+DECLARE_string(tablets);
 DECLARE_int64(timeout_ms); // defined in ksck
 
 namespace kudu {
@@ -82,6 +88,7 @@ using std::cout;
 using std::endl;
 using std::string;
 using std::unique_ptr;
+using std::unordered_set;
 using std::vector;
 using tablet::TabletStatusPB;
 using tserver::DeleteTabletRequestPB;
@@ -178,6 +185,10 @@ Status GetReplicas(TabletServerServiceProxy* proxy,
   RpcController rpc;
   rpc.set_timeout(MonoDelta::FromMilliseconds(FLAGS_timeout_ms));
 
+  // Even with FLAGS_include_schema=false, don't set need_schema_info=false
+  // in the request. The reason is that the schema is still needed to decode
+  // the partition of each replica, and the partition information is pretty
+  // much always nice to have.
   RETURN_NOT_OK(proxy->ListTablets(req, &resp, &rpc));
   if (resp.has_error()) {
     return StatusFromPB(resp.error().status());
@@ -281,7 +292,16 @@ Status ListReplicas(const RunnerContext& context) {
   vector<ListTabletsResponsePB::StatusAndSchemaPB> replicas;
   RETURN_NOT_OK(GetReplicas(proxy.get(), &replicas));
 
+  unordered_set<string> tablet_ids = strings::Split(FLAGS_tablets, ",");
   for (const auto& r : replicas) {
+    if (!FLAGS_table_name.empty() &&
+        r.tablet_status().table_name() != FLAGS_table_name) {
+      continue;
+    }
+    if (!FLAGS_tablets.empty() &&
+        !ContainsKey(tablet_ids, r.tablet_status().tablet_id())) {
+      continue;
+    }
     Schema schema;
     RETURN_NOT_OK_PREPEND(
         SchemaFromPB(r.schema(), &schema),
@@ -311,7 +331,9 @@ Status ListReplicas(const RunnerContext& context) {
     } else {
       cout << "Data dirs: <not available>" << endl;
     }
-    cout << "Schema: " << schema.ToString() << endl;
+    if (FLAGS_include_schema) {
+      cout << "Schema: " << schema.ToString() << endl;
+    }
   }
 
   return Status::OK();
@@ -437,6 +459,12 @@ unique_ptr<Mode> BuildRemoteReplicaMode() {
       ActionBuilder("list", &ListReplicas)
       .Description("List all tablet replicas on a Kudu Tablet Server")
       .AddRequiredParameter({ kTServerAddressArg, kTServerAddressDesc })
+      .AddOptionalParameter("include_schema")
+      .AddOptionalParameter("table_name")
+      .AddOptionalParameter("tablets",
+                            string(""),
+                            string("Comma-separated list of tablet IDs used to "
+                                   "filter the list of replicas"))
       .Build();
 
   unique_ptr<Action> unsafe_change_config =