kudu-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mpe...@apache.org
Subject [4/7] kudu git commit: [catalog manager] introduce replica type filter
Date Sat, 02 Dec 2017 05:26:51 GMT
[catalog manager] introduce replica type filter

Introduced a replica type filter for GetTabletLocations RPC and
various wrapper methods used in master, catalog manager, and tests.
The filter is used to specify what type of tablet replicas to include
while populating the result of the GetTabletLocations RPC.

When not specified otherwise or when using earlier versions of the
GetTable[t]LocationsRequestPB protobuf messages, VOTER_REPLICA policy
is used.  To locate all replicas, specify ANY_REPLICA policy in the
'replica_type_filter' field of the GetTable[t]LocationsRequestPB.  The
latter is done now unconditionally for already existing non-voter
replica-related tests.  This will change by a follow-up commit:
the 'regular' client operations should work with voter replicas only,
so the use cases for getting all tablet replicas will be just
the following:

  * the kudu CLI tool fetching that information to report on replica
    membership status for listings in 'table list --tablets' and
    'ksck' sub-commands.

  * various tests exercising the functionality related to
    non-voter tablet replicas

Added an integration test to verify the functionality of the replica
type filter for GetTableLocations and GetTabletLocations RPC.

Change-Id: I303a6d158184575a9a105c2d2bf26961ae8b3e93
Reviewed-on: http://gerrit.cloudera.org:8080/8161
Tested-by: Alexey Serbin <aserbin@cloudera.com>
Reviewed-by: Mike Percy <mpercy@apache.org>
Reviewed-on: http://gerrit.cloudera.org:8080/8727
Reviewed-by: Alexey Serbin <aserbin@cloudera.com>
Tested-by: Mike Percy <mpercy@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/kudu/repo
Commit: http://git-wip-us.apache.org/repos/asf/kudu/commit/aacf05ed
Tree: http://git-wip-us.apache.org/repos/asf/kudu/tree/aacf05ed
Diff: http://git-wip-us.apache.org/repos/asf/kudu/diff/aacf05ed

Branch: refs/heads/branch-1.6.x
Commit: aacf05ed7d1b71b6ba58bb11eaf499397ca15e39
Parents: c2366d9
Author: Alexey Serbin <aserbin@cloudera.com>
Authored: Wed Sep 27 18:02:33 2017 -0700
Committer: Mike Percy <mpercy@apache.org>
Committed: Sat Dec 2 05:24:50 2017 +0000

----------------------------------------------------------------------
 src/kudu/client/meta_cache.cc                   |   1 +
 .../integration-tests/cluster_itest_util.cc     |  17 ++-
 src/kudu/integration-tests/cluster_itest_util.h |   7 +-
 .../integration-tests/delete_table-itest.cc     |   2 +-
 .../flex_partitioning-itest.cc                  |  15 +--
 .../raft_config_change-itest.cc                 |  14 ++-
 .../integration-tests/raft_consensus-itest.cc   |   8 +-
 .../raft_consensus_nonvoter-itest.cc            | 123 ++++++++++++++++++-
 src/kudu/integration-tests/registration-test.cc |   2 +-
 .../integration-tests/table_locations-itest.cc  |   1 -
 src/kudu/integration-tests/tablet_copy-itest.cc |   2 +-
 .../tombstoned_voting-itest.cc                  |   2 +-
 src/kudu/integration-tests/ts_itest-base.cc     |   1 +
 src/kudu/master/catalog_manager.cc              |  43 +++++--
 src/kudu/master/catalog_manager.h               |  15 ++-
 src/kudu/master/master.proto                    |  16 +++
 src/kudu/master/master_service.cc               |   5 +-
 src/kudu/tools/kudu-admin-test.cc               |  32 ++---
 18 files changed, 242 insertions(+), 64 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kudu/blob/aacf05ed/src/kudu/client/meta_cache.cc
----------------------------------------------------------------------
diff --git a/src/kudu/client/meta_cache.cc b/src/kudu/client/meta_cache.cc
index 8b1a226..08b222c 100644
--- a/src/kudu/client/meta_cache.cc
+++ b/src/kudu/client/meta_cache.cc
@@ -668,6 +668,7 @@ void LookupRpc::SendRpc() {
   req_.mutable_table()->set_table_id(table_->id());
   req_.set_partition_key_start(partition_key_);
   req_.set_max_returned_locations(max_returned_locations_);
+  req_.set_replica_type_filter(master::ANY_REPLICA);
 
   // The end partition key is left unset intentionally so that we'll prefetch
   // some additional tablets.

http://git-wip-us.apache.org/repos/asf/kudu/blob/aacf05ed/src/kudu/integration-tests/cluster_itest_util.cc
----------------------------------------------------------------------
diff --git a/src/kudu/integration-tests/cluster_itest_util.cc b/src/kudu/integration-tests/cluster_itest_util.cc
index 089dba1..4e4464b 100644
--- a/src/kudu/integration-tests/cluster_itest_util.cc
+++ b/src/kudu/integration-tests/cluster_itest_util.cc
@@ -86,7 +86,6 @@ using consensus::RunLeaderElectionRequestPB;
 using consensus::VoteRequestPB;
 using consensus::VoteResponsePB;
 using consensus::kInvalidOpIdIndex;
-using master::ListTabletServersResponsePB;
 using master::ListTabletServersResponsePB_Entry;
 using master::MasterServiceProxy;
 using master::TabletLocationsPB;
@@ -446,7 +445,7 @@ Status ListTabletServers(
     vector<ListTabletServersResponsePB_Entry>* tservers) {
   master::ListTabletServersRequestPB req;
   master::ListTabletServersResponsePB resp;
-  rpc::RpcController controller;
+  RpcController controller;
   controller.set_timeout(timeout);
 
   RETURN_NOT_OK(master_proxy->ListTabletServers(req, &resp, &controller));
@@ -481,11 +480,13 @@ Status WaitForReplicasReportedToMaster(
     const string& tablet_id,
     const MonoDelta& timeout,
     WaitForLeader wait_for_leader,
+    master::ReplicaTypeFilter filter,
     bool* has_leader,
     master::TabletLocationsPB* tablet_locations) {
   MonoTime deadline(MonoTime::Now() + timeout);
   while (true) {
-    RETURN_NOT_OK(GetTabletLocations(master_proxy, tablet_id, timeout, tablet_locations));
+    RETURN_NOT_OK(GetTabletLocations(
+        master_proxy, tablet_id, timeout, filter, tablet_locations));
     *has_leader = false;
     if (tablet_locations->replicas_size() == num_replicas) {
       for (const master::TabletLocationsPB_ReplicaPB& replica :
@@ -885,10 +886,13 @@ Status ListRunningTabletIds(const TServerDetails* ts,
 Status GetTabletLocations(const shared_ptr<MasterServiceProxy>& master_proxy,
                           const string& tablet_id,
                           const MonoDelta& timeout,
+                          master::ReplicaTypeFilter filter,
                           master::TabletLocationsPB* tablet_locations) {
-  master::GetTabletLocationsResponsePB resp;
   master::GetTabletLocationsRequestPB req;
   *req.add_tablet_ids() = tablet_id;
+  req.set_replica_type_filter(filter);
+
+  master::GetTabletLocationsResponsePB resp;
   rpc::RpcController rpc;
   rpc.set_timeout(timeout);
   RETURN_NOT_OK(master_proxy->GetTabletLocations(req, &resp, &rpc));
@@ -907,9 +911,11 @@ Status GetTabletLocations(const shared_ptr<MasterServiceProxy>& master_proxy,
 Status GetTableLocations(const shared_ptr<MasterServiceProxy>& master_proxy,
                          const string& table_name,
                          const MonoDelta& timeout,
+                         master::ReplicaTypeFilter filter,
                          master::GetTableLocationsResponsePB* table_locations) {
   master::GetTableLocationsRequestPB req;
   req.mutable_table()->set_table_name(table_name);
+  req.set_replica_type_filter(filter);
   req.set_max_returned_locations(1000);
   rpc::RpcController rpc;
   rpc.set_timeout(timeout);
@@ -930,7 +936,8 @@ Status WaitForNumVotersInConfigOnMaster(const shared_ptr<MasterServiceProxy>& ma
   while (true) {
     TabletLocationsPB tablet_locations;
     MonoDelta time_remaining = deadline - MonoTime::Now();
-    s = GetTabletLocations(master_proxy, tablet_id, time_remaining, &tablet_locations);
+    s = GetTabletLocations(master_proxy, tablet_id, time_remaining,
+                           master::VOTER_REPLICA, &tablet_locations);
     if (s.ok()) {
       num_voters_found = 0;
       for (const TabletLocationsPB::ReplicaPB& r : tablet_locations.replicas()) {

http://git-wip-us.apache.org/repos/asf/kudu/blob/aacf05ed/src/kudu/integration-tests/cluster_itest_util.h
----------------------------------------------------------------------
diff --git a/src/kudu/integration-tests/cluster_itest_util.h b/src/kudu/integration-tests/cluster_itest_util.h
index 215a90c..5c0ab9f 100644
--- a/src/kudu/integration-tests/cluster_itest_util.h
+++ b/src/kudu/integration-tests/cluster_itest_util.h
@@ -37,6 +37,7 @@
 #include "kudu/consensus/consensus.pb.h"
 #include "kudu/consensus/consensus.proxy.h"
 #include "kudu/consensus/metadata.pb.h"
+#include "kudu/master/master.pb.h"
 #include "kudu/server/server_base.proxy.h"
 #include "kudu/tablet/metadata.pb.h"
 #include "kudu/tserver/tablet_copy.pb.h"
@@ -61,10 +62,7 @@ class OpId;
 }
 
 namespace master {
-class GetTableLocationsResponsePB;
-class ListTabletServersResponsePB_Entry;
 class MasterServiceProxy;
-class TabletLocationsPB;
 } // namespace master
 
 namespace rpc {
@@ -204,6 +202,7 @@ Status WaitForReplicasReportedToMaster(
     int num_replicas, const std::string& tablet_id,
     const MonoDelta& timeout,
     WaitForLeader wait_for_leader,
+    master::ReplicaTypeFilter filter,
     bool* has_leader,
     master::TabletLocationsPB* tablet_locations);
 
@@ -334,12 +333,14 @@ Status ListRunningTabletIds(const TServerDetails* ts,
 Status GetTabletLocations(const std::shared_ptr<master::MasterServiceProxy>& master_proxy,
                           const std::string& tablet_id,
                           const MonoDelta& timeout,
+                          master::ReplicaTypeFilter filter,
                           master::TabletLocationsPB* tablet_locations);
 
 // Get the list of tablet locations for all tablets in the specified table from the Master.
 Status GetTableLocations(const std::shared_ptr<master::MasterServiceProxy>& master_proxy,
                          const std::string& table_name,
                          const MonoDelta& timeout,
+                         master::ReplicaTypeFilter filter,
                          master::GetTableLocationsResponsePB* table_locations);
 
 // Wait for the specified number of voters to be reported to the config on the

http://git-wip-us.apache.org/repos/asf/kudu/blob/aacf05ed/src/kudu/integration-tests/delete_table-itest.cc
----------------------------------------------------------------------
diff --git a/src/kudu/integration-tests/delete_table-itest.cc b/src/kudu/integration-tests/delete_table-itest.cc
index 2620b4f..e4bbce6 100644
--- a/src/kudu/integration-tests/delete_table-itest.cc
+++ b/src/kudu/integration-tests/delete_table-itest.cc
@@ -1147,7 +1147,7 @@ TEST_F(DeleteTableITest, TestNoDeleteTombstonedTablets) {
   ASSERT_OK(inspect_->WaitForReplicaCount(kNumReplicas));
   master::GetTableLocationsResponsePB table_locations;
   ASSERT_OK(itest::GetTableLocations(cluster_->master_proxy(), TestWorkload::kDefaultTableName,
-                                     kTimeout, &table_locations));
+                                     kTimeout, master::VOTER_REPLICA, &table_locations));
   ASSERT_EQ(1, table_locations.tablet_locations_size()); // Only 1 tablet.
   string tablet_id;
   std::set<string> replicas;

http://git-wip-us.apache.org/repos/asf/kudu/blob/aacf05ed/src/kudu/integration-tests/flex_partitioning-itest.cc
----------------------------------------------------------------------
diff --git a/src/kudu/integration-tests/flex_partitioning-itest.cc b/src/kudu/integration-tests/flex_partitioning-itest.cc
index 5b8486b..98b2f86 100644
--- a/src/kudu/integration-tests/flex_partitioning-itest.cc
+++ b/src/kudu/integration-tests/flex_partitioning-itest.cc
@@ -426,9 +426,10 @@ void FlexPartitioningITest::CheckPKRangeScan(int lower, int upper) {
 void FlexPartitioningITest::CheckPartitionKeyRangeScan() {
   GetTableLocationsResponsePB table_locations;
   ASSERT_OK(GetTableLocations(cluster_->master_proxy(),
-                    table_->name(),
-                    MonoDelta::FromSeconds(32),
-                    &table_locations));
+                              table_->name(),
+                              MonoDelta::FromSeconds(32),
+                              master::VOTER_REPLICA,
+                              &table_locations));
 
   vector<string> rows;
 
@@ -459,10 +460,10 @@ void FlexPartitioningITest::CheckPartitionKeyRangeScan() {
 void FlexPartitioningITest::CheckPartitionKeyRangeScanWithPKRange(int lower, int upper) {
   GetTableLocationsResponsePB table_locations;
   ASSERT_OK(GetTableLocations(cluster_->master_proxy(),
-                    table_->name(),
-                    MonoDelta::FromSeconds(32),
-                    &table_locations));
-
+                              table_->name(),
+                              MonoDelta::FromSeconds(32),
+                              master::VOTER_REPLICA,
+                              &table_locations));
   vector<string> rows;
 
   for (const master::TabletLocationsPB& tablet_locations :

http://git-wip-us.apache.org/repos/asf/kudu/blob/aacf05ed/src/kudu/integration-tests/raft_config_change-itest.cc
----------------------------------------------------------------------
diff --git a/src/kudu/integration-tests/raft_config_change-itest.cc b/src/kudu/integration-tests/raft_config_change-itest.cc
index 4099727..d7b1301 100644
--- a/src/kudu/integration-tests/raft_config_change-itest.cc
+++ b/src/kudu/integration-tests/raft_config_change-itest.cc
@@ -56,7 +56,9 @@ using kudu::consensus::RaftPeerAttrsPB;
 using kudu::consensus::RaftPeerPB;
 using kudu::consensus::REMOVE_PEER;
 using kudu::itest::BulkChangeConfig;
+using kudu::itest::GetTableLocations;
 using kudu::itest::TServerDetails;
+using kudu::master::VOTER_REPLICA;
 using kudu::pb_util::SecureShortDebugString;
 using std::string;
 using std::unordered_set;
@@ -121,8 +123,8 @@ TEST_F(RaftConfigChangeITest, TestKudu2147) {
   // The table should have replicas on three tservers.
   ASSERT_OK(inspect_->WaitForReplicaCount(3));
   master::GetTableLocationsResponsePB table_locations;
-  ASSERT_OK(itest::GetTableLocations(cluster_->master_proxy(), TestWorkload::kDefaultTableName,
-                                     kTimeout, &table_locations));
+  ASSERT_OK(GetTableLocations(cluster_->master_proxy(), TestWorkload::kDefaultTableName,
+                              kTimeout, VOTER_REPLICA, &table_locations));
   ASSERT_EQ(1, table_locations.tablet_locations_size()); // Only 1 tablet.
   ASSERT_EQ(3, table_locations.tablet_locations().begin()->replicas_size()); // 3 replicas.
   string tablet_id = table_locations.tablet_locations().begin()->tablet_id();
@@ -186,8 +188,8 @@ TEST_F(RaftConfigChangeITest, TestNonVoterPromotion) {
   // The table should initially have replicas on three tservers.
   ASSERT_OK(inspect_->WaitForReplicaCount(3));
   master::GetTableLocationsResponsePB table_locations;
-  ASSERT_OK(itest::GetTableLocations(cluster_->master_proxy(), TestWorkload::kDefaultTableName,
-                                     kTimeout, &table_locations));
+  ASSERT_OK(GetTableLocations(cluster_->master_proxy(), TestWorkload::kDefaultTableName,
+                              kTimeout, VOTER_REPLICA, &table_locations));
   ASSERT_EQ(1, table_locations.tablet_locations_size()); // Only 1 tablet.
   ASSERT_EQ(3, table_locations.tablet_locations().begin()->replicas_size()); // 3 replicas.
   string tablet_id = table_locations.tablet_locations().begin()->tablet_id();
@@ -244,8 +246,8 @@ TEST_F(RaftConfigChangeITest, TestBulkChangeConfig) {
 
   ASSERT_OK(inspect_->WaitForReplicaCount(kNumInitialReplicas));
   master::GetTableLocationsResponsePB table_locations;
-  ASSERT_OK(itest::GetTableLocations(cluster_->master_proxy(), TestWorkload::kDefaultTableName,
-                                     kTimeout, &table_locations));
+  ASSERT_OK(GetTableLocations(cluster_->master_proxy(), TestWorkload::kDefaultTableName,
+                              kTimeout, VOTER_REPLICA, &table_locations));
   ASSERT_EQ(1, table_locations.tablet_locations_size()); // Only 1 tablet.
   ASSERT_EQ(kNumInitialReplicas, table_locations.tablet_locations().begin()->replicas_size());
   string tablet_id = table_locations.tablet_locations().begin()->tablet_id();

http://git-wip-us.apache.org/repos/asf/kudu/blob/aacf05ed/src/kudu/integration-tests/raft_consensus-itest.cc
----------------------------------------------------------------------
diff --git a/src/kudu/integration-tests/raft_consensus-itest.cc b/src/kudu/integration-tests/raft_consensus-itest.cc
index f441024..72690ce 100644
--- a/src/kudu/integration-tests/raft_consensus-itest.cc
+++ b/src/kudu/integration-tests/raft_consensus-itest.cc
@@ -118,6 +118,7 @@ using kudu::itest::WaitUntilCommittedOpIdIndexIs;
 using kudu::itest::WaitUntilLeader;
 using kudu::itest::WriteSimpleTestRow;
 using kudu::master::TabletLocationsPB;
+using kudu::master::VOTER_REPLICA;
 using kudu::pb_util::SecureDebugString;
 using kudu::pb_util::SecureShortDebugString;
 using kudu::rpc::RpcController;
@@ -1700,7 +1701,8 @@ TEST_F(RaftConsensusITest, TestMasterNotifiedOnConfigChange) {
   master::TabletLocationsPB tablet_locations;
   bool has_leader;
   ASSERT_OK(WaitForReplicasReportedToMaster(cluster_->master_proxy(),
-                                            2, tablet_id, timeout, WAIT_FOR_LEADER,
+                                            2, tablet_id, timeout,
+                                            WAIT_FOR_LEADER, VOTER_REPLICA,
                                             &has_leader, &tablet_locations));
   LOG(INFO) << "Tablet locations:\n" << SecureDebugString(tablet_locations);
 
@@ -1721,7 +1723,7 @@ TEST_F(RaftConsensusITest, TestMasterNotifiedOnConfigChange) {
   LOG(INFO) << "Waiting for Master to see config change...";
   ASSERT_OK(WaitForReplicasReportedToMaster(cluster_->master_proxy(),
                                             3, tablet_id, timeout,
-                                            DONT_WAIT_FOR_LEADER,
+                                            DONT_WAIT_FOR_LEADER, VOTER_REPLICA,
                                             &has_leader, &tablet_locations));
   ASSERT_TRUE(has_leader) << SecureDebugString(tablet_locations);
   LOG(INFO) << "Tablet locations:\n" << SecureDebugString(tablet_locations);
@@ -1737,7 +1739,7 @@ TEST_F(RaftConsensusITest, TestMasterNotifiedOnConfigChange) {
   LOG(INFO) << "Waiting for Master to see config change...";
   ASSERT_OK(WaitForReplicasReportedToMaster(cluster_->master_proxy(),
                                             2, tablet_id, timeout,
-                                            DONT_WAIT_FOR_LEADER,
+                                            DONT_WAIT_FOR_LEADER, VOTER_REPLICA,
                                             &has_leader, &tablet_locations));
   ASSERT_TRUE(has_leader) << SecureDebugString(tablet_locations);
   LOG(INFO) << "Tablet locations:\n" << SecureDebugString(tablet_locations);

http://git-wip-us.apache.org/repos/asf/kudu/blob/aacf05ed/src/kudu/integration-tests/raft_consensus_nonvoter-itest.cc
----------------------------------------------------------------------
diff --git a/src/kudu/integration-tests/raft_consensus_nonvoter-itest.cc b/src/kudu/integration-tests/raft_consensus_nonvoter-itest.cc
index e8554dd..241ab4d 100644
--- a/src/kudu/integration-tests/raft_consensus_nonvoter-itest.cc
+++ b/src/kudu/integration-tests/raft_consensus_nonvoter-itest.cc
@@ -65,6 +65,8 @@ using kudu::consensus::RaftPeerPB;
 using kudu::consensus::IsRaftConfigMember;
 using kudu::itest::AddServer;
 using kudu::itest::GetInt64Metric;
+using kudu::itest::GetTableLocations;
+using kudu::itest::GetTabletLocations;
 using kudu::itest::LeaderStepDown;
 using kudu::itest::RemoveServer;
 using kudu::itest::StartElection;
@@ -72,7 +74,10 @@ using kudu::itest::TServerDetails;
 using kudu::itest::TabletServerMap;
 using kudu::itest::WAIT_FOR_LEADER;
 using kudu::itest::WaitForReplicasReportedToMaster;
+using kudu::master::ANY_REPLICA;
+using kudu::master::GetTableLocationsResponsePB;
 using kudu::master::TabletLocationsPB;
+using kudu::master::VOTER_REPLICA;
 using kudu::tablet::TABLET_DATA_COPYING;
 using kudu::tablet::TABLET_DATA_TOMBSTONED;
 using std::string;
@@ -234,6 +239,105 @@ void RaftConsensusNonVoterITest::GetServersWithoutReplica(
   }
 }
 
+// Verify that GetTableLocations() and GetTabletLocations() return the expected
+// set of replicas when for the specified replica type filter.
+TEST_F(RaftConsensusNonVoterITest, GetTableAndTabletLocations) {
+  const MonoDelta kTimeout = MonoDelta::FromSeconds(60);
+  const int kOriginalReplicasNum = 3;
+  FLAGS_num_tablet_servers = kOriginalReplicasNum + 1;
+  FLAGS_num_replicas = kOriginalReplicasNum;
+  NO_FATALS(BuildAndStart());
+  ASSERT_EQ(FLAGS_num_tablet_servers, tablet_servers_.size());
+  ASSERT_EQ(kOriginalReplicasNum, tablet_replicas_.size());
+
+  const string& tablet_id = tablet_id_;
+  TabletServerMap replica_servers;
+  for (const auto& e : tablet_replicas_) {
+    if (e.first == tablet_id) {
+      replica_servers.emplace(e.second->uuid(), e.second);
+    }
+  }
+  ASSERT_EQ(FLAGS_num_replicas, replica_servers.size());
+
+  TServerDetails* new_replica = nullptr;
+  for (const auto& ts : tablet_servers_) {
+    if (replica_servers.find(ts.first) == replica_servers.end()) {
+      new_replica = ts.second;
+      break;
+    }
+  }
+  ASSERT_NE(nullptr, new_replica);
+
+  ASSERT_OK(AddReplica(tablet_id, new_replica, RaftPeerPB::NON_VOTER, kTimeout));
+  // Wait the newly added replica to start.
+  ASSERT_OK(WaitForNumTabletsOnTS(
+      new_replica, 1, kTimeout, nullptr, tablet::RUNNING));
+
+  const auto count_roles = [this](const TabletLocationsPB& tablet_locations,
+      int* num_leaders, int* num_followers, int* num_learners) {
+    *num_leaders = 0;
+    *num_followers = 0;
+    *num_learners = 0;
+    for (const auto& r : tablet_locations.replicas()) {
+      *num_leaders += (r.role() == RaftPeerPB::LEADER) ? 1 : 0;
+      *num_followers += (r.role() == RaftPeerPB::FOLLOWER) ? 1 : 0;
+      *num_learners += (r.role() == RaftPeerPB::LEARNER) ? 1 : 0;
+    }
+  };
+
+  // Verify that replica type filter yields appropriate results for
+  // GetTableLocations() RPC.
+  {
+    GetTableLocationsResponsePB table_locations;
+    ASSERT_OK(GetTableLocations(cluster_->master_proxy(), table_->name(),
+                                kTimeout, VOTER_REPLICA, &table_locations));
+    ASSERT_EQ(1, table_locations.tablet_locations().size());
+    const TabletLocationsPB& locations = table_locations.tablet_locations(0);
+    ASSERT_EQ(tablet_id_, locations.tablet_id());
+    ASSERT_EQ(kOriginalReplicasNum, locations.replicas_size());
+    int num_leaders = 0, num_followers = 0, num_learners = 0;
+    count_roles(locations, &num_leaders, &num_followers, &num_learners);
+    ASSERT_EQ(kOriginalReplicasNum, num_leaders + num_followers);
+    ASSERT_EQ(0, num_learners);
+  }
+  {
+    GetTableLocationsResponsePB table_locations;
+    ASSERT_OK(GetTableLocations(cluster_->master_proxy(), table_->name(),
+                                kTimeout, ANY_REPLICA, &table_locations));
+    ASSERT_EQ(1, table_locations.tablet_locations().size());
+    const TabletLocationsPB& locations = table_locations.tablet_locations(0);
+    ASSERT_EQ(tablet_id_, locations.tablet_id());
+    ASSERT_EQ(kOriginalReplicasNum + 1, locations.replicas_size());
+    int num_leaders = 0, num_followers = 0, num_learners = 0;
+    count_roles(locations, &num_leaders, &num_followers, &num_learners);
+    ASSERT_EQ(kOriginalReplicasNum, num_leaders + num_followers);
+    ASSERT_EQ(1, num_learners);
+  }
+
+  // Verify that replica type filter yields appropriate results for
+  // GetTabletLocations() RPC.
+  {
+    TabletLocationsPB tablet_locations;
+    ASSERT_OK(GetTabletLocations(cluster_->master_proxy(), tablet_id_,
+                                 kTimeout, VOTER_REPLICA, &tablet_locations));
+    ASSERT_EQ(kOriginalReplicasNum, tablet_locations.replicas_size());
+    int num_leaders = 0, num_followers = 0, num_learners = 0;
+    count_roles(tablet_locations, &num_leaders, &num_followers, &num_learners);
+    ASSERT_EQ(kOriginalReplicasNum, num_leaders + num_followers);
+    ASSERT_EQ(0, num_learners);
+  }
+  {
+    TabletLocationsPB tablet_locations;
+    ASSERT_OK(GetTabletLocations(cluster_->master_proxy(), tablet_id_,
+                                 kTimeout, ANY_REPLICA, &tablet_locations));
+    ASSERT_EQ(kOriginalReplicasNum + 1, tablet_locations.replicas_size());
+    int num_leaders = 0, num_followers = 0, num_learners = 0;
+    count_roles(tablet_locations, &num_leaders, &num_followers, &num_learners);
+    ASSERT_EQ(kOriginalReplicasNum, num_leaders + num_followers);
+    ASSERT_EQ(1, num_learners);
+  }
+}
+
 // Ensure that adding a NON_VOTER replica is properly handled by the system:
 //
 //   * Updating Raft configuration for tablet by adding a NON_VOTER replica
@@ -352,7 +456,7 @@ TEST_F(RaftConsensusNonVoterITest, AddNonVoterReplica) {
   TabletLocationsPB tablet_locations;
   ASSERT_OK(WaitForReplicasReportedToMaster(
       cluster_->master_proxy(), kOriginalReplicasNum + 1, tablet_id, kTimeout,
-      WAIT_FOR_LEADER, &has_leader, &tablet_locations));
+      WAIT_FOR_LEADER, ANY_REPLICA, &has_leader, &tablet_locations));
   ASSERT_TRUE(has_leader);
 
   // Check the update cluster is able to elect a leader.
@@ -377,6 +481,8 @@ TEST_F(RaftConsensusNonVoterITest, AddNonVoterReplica) {
   // all OpIds match in local files under all tablet servers of the cluster,
   // so NON_VOTER replicas are covered by this check as well.
   ClusterVerifier v(cluster_.get());
+  v.SetOperationsTimeout(kTimeout);
+  v.SetVerificationTimeout(kTimeout);
   NO_FATALS(v.CheckCluster());
   NO_FATALS(v.CheckRowCount(workload.table_name(),
                             ClusterVerifier::EXACTLY,
@@ -454,6 +560,8 @@ TEST_F(RaftConsensusNonVoterITest, AddThenRemoveNonVoterReplica) {
   // Ensure that nothing crashes and the replicas converge.
   NO_FATALS(cluster_->AssertNoCrashes());
   ClusterVerifier v(cluster_.get());
+  v.SetOperationsTimeout(kTimeout);
+  v.SetVerificationTimeout(kTimeout);
   NO_FATALS(v.CheckCluster());
   NO_FATALS(v.CheckRowCount(workload.table_name(),
                             ClusterVerifier::EXACTLY,
@@ -476,7 +584,7 @@ TEST_F(RaftConsensusNonVoterITest, AddThenRemoveNonVoterReplica) {
   TabletLocationsPB tablet_locations;
   ASSERT_OK(WaitForReplicasReportedToMaster(
       cluster_->master_proxy(), kOriginalReplicasNum, tablet_id, kTimeout,
-      WAIT_FOR_LEADER, &has_leader, &tablet_locations));
+      WAIT_FOR_LEADER, ANY_REPLICA, &has_leader, &tablet_locations));
   ASSERT_TRUE(has_leader);
 
   // Make sure it's possible to insert data into the tablet once the NON_VOTER
@@ -764,6 +872,8 @@ TEST_F(RaftConsensusNonVoterITest, PromoteAndDemote) {
     ASSERT_OK(WaitForServersToAgree(kTimeout, replica_servers, tablet_id, 1));
 
     ClusterVerifier v(cluster_.get());
+    v.SetOperationsTimeout(kTimeout);
+    v.SetVerificationTimeout(kTimeout);
     NO_FATALS(v.CheckCluster());
     NO_FATALS(v.CheckRowCount(workload.table_name(),
                               ClusterVerifier::EXACTLY,
@@ -791,7 +901,7 @@ TEST_F(RaftConsensusNonVoterITest, PromoteAndDemote) {
     TabletLocationsPB tablet_locations;
     ASSERT_OK(WaitForReplicasReportedToMaster(
         cluster_->master_proxy(), kInitialReplicasNum, tablet_id, kTimeout,
-        WAIT_FOR_LEADER, &has_leader, &tablet_locations));
+        WAIT_FOR_LEADER, ANY_REPLICA, &has_leader, &tablet_locations));
     ASSERT_TRUE(has_leader);
   }
 
@@ -994,6 +1104,7 @@ TEST_F(RaftConsensusNonVoterITest, CatalogManagerEvictsExcessNonVoter) {
                                             tablet_id_,
                                             kTimeout,
                                             WAIT_FOR_LEADER,
+                                            ANY_REPLICA,
                                             &has_leader,
                                             &tablet_locations));
 
@@ -1024,6 +1135,7 @@ TEST_F(RaftConsensusNonVoterITest, CatalogManagerEvictsExcessNonVoter) {
                                             tablet_id_,
                                             kTimeout,
                                             WAIT_FOR_LEADER,
+                                            ANY_REPLICA,
                                             &has_leader,
                                             &tablet_locations));
   NO_FATALS(cluster_->AssertNoCrashes());
@@ -1077,6 +1189,7 @@ TEST_F(RaftConsensusNonVoterITest, CatalogManagerAddsNonVoter) {
                                             tablet_id_,
                                             kTimeout,
                                             WAIT_FOR_LEADER,
+                                            ANY_REPLICA,
                                             &has_leader,
                                             &tablet_locations));
   NO_FATALS(cluster_->AssertNoCrashes());
@@ -1154,6 +1267,7 @@ TEST_F(RaftConsensusNonVoterITest, TabletServerIsGoneAndBack) {
                                             tablet_id_,
                                             kTimeout,
                                             WAIT_FOR_LEADER,
+                                            ANY_REPLICA,
                                             &has_leader,
                                             &tablet_locations));
 
@@ -1168,6 +1282,7 @@ TEST_F(RaftConsensusNonVoterITest, TabletServerIsGoneAndBack) {
                                             tablet_id_,
                                             kTimeout,
                                             WAIT_FOR_LEADER,
+                                            ANY_REPLICA,
                                             &has_leader,
                                             &tablet_locations));
   // Make sure the replica from the gone-and-back server is part of the config.
@@ -1268,6 +1383,7 @@ TEST_F(RaftConsensusNonVoterITest, FailedTabletCopy) {
                                             tablet_id_,
                                             kTimeout,
                                             WAIT_FOR_LEADER,
+                                            ANY_REPLICA,
                                             &has_leader,
                                             &tablet_locations));
   // Make the second server available for placing a non-voter replica.
@@ -1280,6 +1396,7 @@ TEST_F(RaftConsensusNonVoterITest, FailedTabletCopy) {
                                             tablet_id_,
                                             kTimeout,
                                             WAIT_FOR_LEADER,
+                                            ANY_REPLICA,
                                             &has_leader,
                                             &tablet_locations));
   consensus::ConsensusStatePB cstate;

http://git-wip-us.apache.org/repos/asf/kudu/blob/aacf05ed/src/kudu/integration-tests/registration-test.cc
----------------------------------------------------------------------
diff --git a/src/kudu/integration-tests/registration-test.cc b/src/kudu/integration-tests/registration-test.cc
index d330da8..bbd0834 100644
--- a/src/kudu/integration-tests/registration-test.cc
+++ b/src/kudu/integration-tests/registration-test.cc
@@ -194,7 +194,7 @@ class RegistrationTest : public KuduTest {
           break;  // exiting out of the 'do {...} while (false)' scope
         }
         RETURN_NOT_OK(ls);
-        s = catalog->GetTabletLocations(tablet_id, &loc);
+        s = catalog->GetTabletLocations(tablet_id, master::VOTER_REPLICA, &loc);
       } while (false);
       if (s.ok() && loc.replicas_size() == expected_count) {
         if (locations) {

http://git-wip-us.apache.org/repos/asf/kudu/blob/aacf05ed/src/kudu/integration-tests/table_locations-itest.cc
----------------------------------------------------------------------
diff --git a/src/kudu/integration-tests/table_locations-itest.cc b/src/kudu/integration-tests/table_locations-itest.cc
index 751a109..71fc76d 100644
--- a/src/kudu/integration-tests/table_locations-itest.cc
+++ b/src/kudu/integration-tests/table_locations-itest.cc
@@ -239,6 +239,5 @@ TEST_F(TableLocationsTest, TestGetTableLocations) {
   }
 }
 
-
 } // namespace master
 } // namespace kudu

http://git-wip-us.apache.org/repos/asf/kudu/blob/aacf05ed/src/kudu/integration-tests/tablet_copy-itest.cc
----------------------------------------------------------------------
diff --git a/src/kudu/integration-tests/tablet_copy-itest.cc b/src/kudu/integration-tests/tablet_copy-itest.cc
index 293318e..f977f18 100644
--- a/src/kudu/integration-tests/tablet_copy-itest.cc
+++ b/src/kudu/integration-tests/tablet_copy-itest.cc
@@ -1145,7 +1145,7 @@ TEST_P(TabletCopyFailureITest, TestTabletCopyNewReplicaFailureCanVote) {
   ASSERT_OK(inspect_->WaitForReplicaCount(3));
   master::GetTableLocationsResponsePB table_locations;
   ASSERT_OK(itest::GetTableLocations(cluster_->master_proxy(), TestWorkload::kDefaultTableName,
-                                     kTimeout, &table_locations));
+                                     kTimeout, master::VOTER_REPLICA, &table_locations));
   ASSERT_EQ(1, table_locations.tablet_locations_size());
   string tablet_id = table_locations.tablet_locations(0).tablet_id();
   set<string> replica_uuids;

http://git-wip-us.apache.org/repos/asf/kudu/blob/aacf05ed/src/kudu/integration-tests/tombstoned_voting-itest.cc
----------------------------------------------------------------------
diff --git a/src/kudu/integration-tests/tombstoned_voting-itest.cc b/src/kudu/integration-tests/tombstoned_voting-itest.cc
index 69c48e4..951f28f 100644
--- a/src/kudu/integration-tests/tombstoned_voting-itest.cc
+++ b/src/kudu/integration-tests/tombstoned_voting-itest.cc
@@ -90,7 +90,7 @@ TEST_F(TombstonedVotingITest, TestTombstonedReplicaWithoutCMetaCanVote) {
   ASSERT_OK(inspect_->WaitForReplicaCount(3));
   master::GetTableLocationsResponsePB table_locations;
   ASSERT_OK(itest::GetTableLocations(cluster_->master_proxy(), TestWorkload::kDefaultTableName,
-                                     kTimeout, &table_locations));
+                                     kTimeout, master::VOTER_REPLICA, &table_locations));
   ASSERT_EQ(1, table_locations.tablet_locations_size());
   string tablet_id = table_locations.tablet_locations(0).tablet_id();
   set<string> replica_uuids;

http://git-wip-us.apache.org/repos/asf/kudu/blob/aacf05ed/src/kudu/integration-tests/ts_itest-base.cc
----------------------------------------------------------------------
diff --git a/src/kudu/integration-tests/ts_itest-base.cc b/src/kudu/integration-tests/ts_itest-base.cc
index 1e69d12..cb2b61d 100644
--- a/src/kudu/integration-tests/ts_itest-base.cc
+++ b/src/kudu/integration-tests/ts_itest-base.cc
@@ -165,6 +165,7 @@ void TabletServerIntegrationTestBase::WaitForReplicasAndUpdateLocations(
     master::GetTableLocationsResponsePB resp;
     rpc::RpcController controller;
     req.mutable_table()->set_table_name(table_id);
+    req.set_replica_type_filter(master::ANY_REPLICA);
     controller.set_timeout(MonoDelta::FromSeconds(1));
     CHECK_OK(cluster_->master_proxy()->GetTableLocations(req, &resp, &controller));
     CHECK_OK(controller.status());

http://git-wip-us.apache.org/repos/asf/kudu/blob/aacf05ed/src/kudu/master/catalog_manager.cc
----------------------------------------------------------------------
diff --git a/src/kudu/master/catalog_manager.cc b/src/kudu/master/catalog_manager.cc
index a7e123c..beb4302 100644
--- a/src/kudu/master/catalog_manager.cc
+++ b/src/kudu/master/catalog_manager.cc
@@ -4021,8 +4021,10 @@ void CatalogManager::SelectReplicas(const TSDescriptorVector& ts_descs,
   }
 }
 
-Status CatalogManager::BuildLocationsForTablet(const scoped_refptr<TabletInfo>& tablet,
-                                               TabletLocationsPB* locs_pb) {
+Status CatalogManager::BuildLocationsForTablet(
+    const scoped_refptr<TabletInfo>& tablet,
+    master::ReplicaTypeFilter filter,
+    TabletLocationsPB* locs_pb) {
   TabletMetadataLock l_tablet(tablet.get(), LockMode::READ);
   if (PREDICT_FALSE(l_tablet.data().is_deleted())) {
     return Status::NotFound("Tablet deleted", l_tablet.data().pb.state_msg());
@@ -4039,6 +4041,27 @@ Status CatalogManager::BuildLocationsForTablet(const scoped_refptr<TabletInfo>&
   for (const consensus::RaftPeerPB& peer : cstate.committed_config().peers()) {
     // TODO(adar): GetConsensusRole() iterates over all of the peers, making this an
     // O(n^2) loop. If replication counts get high, it should be optimized.
+    switch (filter) {
+      case VOTER_REPLICA:
+        if (!peer.has_member_type() ||
+            peer.member_type() != consensus::RaftPeerPB::VOTER) {
+          // Jump to the next iteration of the outside cycle.
+          continue;
+        }
+        break;
+
+      case ANY_REPLICA:
+        break;
+
+      default:
+        {
+          const string err_msg = Substitute(
+              "$0: unsupported replica type filter", filter);
+          LOG(DFATAL) << err_msg;
+          return Status::InvalidArgument(err_msg);
+        }
+    }
+
     TabletLocationsPB_ReplicaPB* replica_pb = locs_pb->add_replicas();
     replica_pb->set_role(GetConsensusRole(peer.permanent_uuid(), cstate));
 
@@ -4069,6 +4092,7 @@ Status CatalogManager::BuildLocationsForTablet(const scoped_refptr<TabletInfo>&
 }
 
 Status CatalogManager::GetTabletLocations(const string& tablet_id,
+                                          master::ReplicaTypeFilter filter,
                                           TabletLocationsPB* locs_pb) {
   leader_lock_.AssertAcquiredForReading();
   RETURN_NOT_OK(CheckOnline());
@@ -4082,27 +4106,26 @@ Status CatalogManager::GetTabletLocations(const string& tablet_id,
     }
   }
 
-  return BuildLocationsForTablet(tablet_info, locs_pb);
+  return BuildLocationsForTablet(tablet_info, filter, locs_pb);
 }
 
 Status CatalogManager::GetTableLocations(const GetTableLocationsRequestPB* req,
                                          GetTableLocationsResponsePB* resp) {
-  leader_lock_.AssertAcquiredForReading();
-  RETURN_NOT_OK(CheckOnline());
-
   // If start-key is > end-key report an error instead of swap the two
   // since probably there is something wrong app-side.
   if (req->has_partition_key_start() && req->has_partition_key_end()
       && req->partition_key_start() > req->partition_key_end()) {
     return Status::InvalidArgument("start partition key is greater than the end partition key");
   }
-
   if (req->max_returned_locations() <= 0) {
     return Status::InvalidArgument("max_returned_locations must be greater than 0");
   }
 
   // Lookup the table and verify if it exists
   TRACE("Looking up and locking table");
+  leader_lock_.AssertAcquiredForReading();
+  RETURN_NOT_OK(CheckOnline());
+
   scoped_refptr<TableInfo> table;
   TableMetadataLock l;
   RETURN_NOT_OK(FindAndLockTable(req->table(), LockMode::READ, &table, &l));
@@ -4117,10 +4140,12 @@ Status CatalogManager::GetTableLocations(const GetTableLocationsRequestPB* req,
   table->GetTabletsInRange(req, &tablets_in_range);
 
   for (const auto& tablet : tablets_in_range) {
-    Status s = BuildLocationsForTablet(tablet, resp->add_tablet_locations());
+    Status s = BuildLocationsForTablet(
+        tablet, req->replica_type_filter(), resp->add_tablet_locations());
     if (s.ok()) {
       continue;
-    } else if (s.IsNotFound()) {
+    }
+    if (s.IsNotFound()) {
       // The tablet has been deleted; force the client to retry. This is a
       // transient state that only happens with a concurrent drop range
       // partition alter table operation.

http://git-wip-us.apache.org/repos/asf/kudu/blob/aacf05ed/src/kudu/master/catalog_manager.h
----------------------------------------------------------------------
diff --git a/src/kudu/master/catalog_manager.h b/src/kudu/master/catalog_manager.h
index 5f406ad..9261cf0 100644
--- a/src/kudu/master/catalog_manager.h
+++ b/src/kudu/master/catalog_manager.h
@@ -552,13 +552,14 @@ class CatalogManager : public tserver::TabletReplicaLookupIf {
   Status GetTableLocations(const GetTableLocationsRequestPB* req,
                            GetTableLocationsResponsePB* resp);
 
-  // Look up the locations of the given tablet. The locations
-  // vector is overwritten (not appended to).
-  // If the tablet is not found, returns Status::NotFound.
+  // Look up the locations of the given tablet. Adds only information on
+  // replicas which satisfy the 'filter'. The locations vector is overwritten
+  // (not appended to). If the tablet is not found, returns Status::NotFound.
   // If the tablet is not running, returns Status::ServiceUnavailable.
   // Otherwise, returns Status::OK and puts the result in 'locs_pb'.
   // This only returns tablets which are in RUNNING state.
   Status GetTabletLocations(const std::string& tablet_id,
+                            master::ReplicaTypeFilter filter,
                             TabletLocationsPB* locs_pb);
 
   // Handle a tablet report from the given tablet server.
@@ -717,10 +718,12 @@ class CatalogManager : public tserver::TabletReplicaLookupIf {
   scoped_refptr<TabletInfo> CreateTabletInfo(const scoped_refptr<TableInfo>& table,
                                              const PartitionPB& partition);
 
-  // Builds the TabletLocationsPB for a tablet based on the provided TabletInfo.
-  // Populates locs_pb and returns true on success.
-  // Returns Status::ServiceUnavailable if tablet is not running.
+  // Builds the TabletLocationsPB for a tablet based on the provided TabletInfo
+  // and the replica type fiter specified. Populates locs_pb and returns
+  // Status::OK on success. Returns Status::ServiceUnavailable if tablet is
+  // not running.
   Status BuildLocationsForTablet(const scoped_refptr<TabletInfo>& tablet,
+                                 master::ReplicaTypeFilter filter,
                                  TabletLocationsPB* locs_pb);
 
   // Looks up the table and locks it with the provided lock mode. If the table

http://git-wip-us.apache.org/repos/asf/kudu/blob/aacf05ed/src/kudu/master/master.proto
----------------------------------------------------------------------
diff --git a/src/kudu/master/master.proto b/src/kudu/master/master.proto
index 4ec6dd1..5342960 100644
--- a/src/kudu/master/master.proto
+++ b/src/kudu/master/master.proto
@@ -361,9 +361,21 @@ message TSInfoPB {
   repeated HostPortPB rpc_addresses = 2;
 }
 
+// Selector to specify policy for listing tablet replicas in
+// GetTableLocationResponsePB and GetTabletLocationsResponsePB.
+enum ReplicaTypeFilter {
+  UNKNOWN = 999;
+  ANY_REPLICA = 0;
+  VOTER_REPLICA = 1;
+}
+
 message GetTabletLocationsRequestPB {
+
   // The tablet IDs about which to fetch info.
   repeated bytes tablet_ids = 1;
+
+  // What type of tablet replicas to include in the response.
+  optional ReplicaTypeFilter replica_type_filter = 2 [ default = VOTER_REPLICA ];
 }
 
 message GetTabletLocationsResponsePB {
@@ -445,6 +457,10 @@ message GetTableLocationsRequestPB {
   optional bytes partition_key_end = 4 [(kudu.REDACT) = true];
 
   optional uint32 max_returned_locations = 5 [ default = 10 ];
+
+  // What type of tablet replicas to include in the
+  // 'GetTableLocationsResponsePB::tablet_locations' response field.
+  optional ReplicaTypeFilter replica_type_filter = 6 [ default = VOTER_REPLICA ];
 }
 
 // The response to a GetTableLocations RPC. The master guarantees that:

http://git-wip-us.apache.org/repos/asf/kudu/blob/aacf05ed/src/kudu/master/master_service.cc
----------------------------------------------------------------------
diff --git a/src/kudu/master/master_service.cc b/src/kudu/master/master_service.cc
index 0a8e82a..904b93c 100644
--- a/src/kudu/master/master_service.cc
+++ b/src/kudu/master/master_service.cc
@@ -238,9 +238,10 @@ void MasterServiceImpl::GetTabletLocations(const GetTabletLocationsRequestPB* re
   ServerRegistrationPB reg;
   vector<TSDescriptor*> locs;
   for (const string& tablet_id : req->tablet_ids()) {
-    // TODO: once we have catalog data. ACL checks would also go here, probably.
+    // TODO(todd): once we have catalog data. ACL checks would also go here, probably.
     TabletLocationsPB* locs_pb = resp->add_tablet_locations();
-    Status s = server_->catalog_manager()->GetTabletLocations(tablet_id, locs_pb);
+    Status s = server_->catalog_manager()->GetTabletLocations(
+        tablet_id, req->replica_type_filter(), locs_pb);
     if (!s.ok()) {
       resp->mutable_tablet_locations()->RemoveLast();
 

http://git-wip-us.apache.org/repos/asf/kudu/blob/aacf05ed/src/kudu/tools/kudu-admin-test.cc
----------------------------------------------------------------------
diff --git a/src/kudu/tools/kudu-admin-test.cc b/src/kudu/tools/kudu-admin-test.cc
index 7581116..7fb96ed 100644
--- a/src/kudu/tools/kudu-admin-test.cc
+++ b/src/kudu/tools/kudu-admin-test.cc
@@ -83,6 +83,7 @@ using kudu::itest::WaitUntilCommittedConfigNumVotersIs;
 using kudu::itest::WaitUntilCommittedOpIdIndexIs;
 using kudu::itest::WaitUntilTabletInState;
 using kudu::itest::WaitUntilTabletRunning;
+using kudu::master::VOTER_REPLICA;
 using kudu::pb_util::SecureDebugString;
 using std::back_inserter;
 using std::copy;
@@ -363,6 +364,7 @@ TEST_F(AdminCliTest, TestUnsafeChangeConfigOnSingleFollower) {
   ASSERT_OK(WaitForReplicasReportedToMaster(cluster_->master_proxy(),
                                             3, tablet_id, kTimeout,
                                             WAIT_FOR_LEADER,
+                                            VOTER_REPLICA,
                                             &has_leader, &tablet_locations));
   LOG(INFO) << "Tablet locations:\n" << SecureDebugString(tablet_locations);
   ASSERT_TRUE(has_leader) << SecureDebugString(tablet_locations);
@@ -398,7 +400,7 @@ TEST_F(AdminCliTest, TestUnsafeChangeConfigOnSingleFollower) {
   ASSERT_OK(WaitUntilCommittedConfigNumVotersIs(3, followers[0], tablet_id, kTimeout));
   ASSERT_OK(WaitForReplicasReportedToMaster(cluster_->master_proxy(),
                                             3, tablet_id, kTimeout,
-                                            WAIT_FOR_LEADER,
+                                            WAIT_FOR_LEADER, VOTER_REPLICA,
                                             &has_leader, &tablet_locations));
   ASSERT_OK(WaitForOpFromCurrentTerm(followers[0], tablet_id, COMMITTED_OPID, kTimeout, &opid));
 
@@ -451,7 +453,7 @@ TEST_F(AdminCliTest, TestUnsafeChangeConfigOnSingleLeader) {
   bool has_leader;
   ASSERT_OK(WaitForReplicasReportedToMaster(cluster_->master_proxy(),
                                             3, tablet_id_, kTimeout,
-                                            WAIT_FOR_LEADER,
+                                            WAIT_FOR_LEADER, VOTER_REPLICA,
                                             &has_leader, &tablet_locations));
   LOG(INFO) << "Tablet locations:\n" << SecureDebugString(tablet_locations);
   ASSERT_TRUE(has_leader) << SecureDebugString(tablet_locations);
@@ -500,7 +502,7 @@ TEST_F(AdminCliTest, TestUnsafeChangeConfigOnSingleLeader) {
   LOG(INFO) << "Waiting for Master to see new config...";
   ASSERT_OK(WaitForReplicasReportedToMaster(cluster_->master_proxy(),
                                             3, tablet_id_, kTimeout,
-                                            WAIT_FOR_LEADER,
+                                            WAIT_FOR_LEADER, VOTER_REPLICA,
                                             &has_leader, &tablet_locations));
   LOG(INFO) << "Tablet locations:\n" << SecureDebugString(tablet_locations);
   for (const master::TabletLocationsPB_ReplicaPB& replica :
@@ -535,7 +537,7 @@ TEST_F(AdminCliTest, TestUnsafeChangeConfigForConfigWithTwoNodes) {
   bool has_leader;
   ASSERT_OK(WaitForReplicasReportedToMaster(cluster_->master_proxy(),
                                             3, tablet_id_, kTimeout,
-                                            WAIT_FOR_LEADER,
+                                            WAIT_FOR_LEADER, VOTER_REPLICA,
                                             &has_leader, &tablet_locations));
   LOG(INFO) << "Tablet locations:\n" << SecureDebugString(tablet_locations);
   ASSERT_TRUE(has_leader) << SecureDebugString(tablet_locations);
@@ -583,7 +585,7 @@ TEST_F(AdminCliTest, TestUnsafeChangeConfigForConfigWithTwoNodes) {
   LOG(INFO) << "Waiting for Master to see new config...";
   ASSERT_OK(WaitForReplicasReportedToMaster(cluster_->master_proxy(),
                                             3, tablet_id_, kTimeout,
-                                            WAIT_FOR_LEADER,
+                                            WAIT_FOR_LEADER, VOTER_REPLICA,
                                             &has_leader, &tablet_locations));
   LOG(INFO) << "Tablet locations:\n" << SecureDebugString(tablet_locations);
   for (const master::TabletLocationsPB_ReplicaPB& replica :
@@ -627,7 +629,7 @@ TEST_F(AdminCliTest, TestUnsafeChangeConfigWithFiveReplicaConfig) {
   bool has_leader;
   ASSERT_OK(WaitForReplicasReportedToMaster(cluster_->master_proxy(),
                                             5, tablet_id_, kTimeout,
-                                            WAIT_FOR_LEADER,
+                                            WAIT_FOR_LEADER, VOTER_REPLICA,
                                             &has_leader, &tablet_locations));
   LOG(INFO) << "Tablet locations:\n" << SecureDebugString(tablet_locations);
   ASSERT_TRUE(has_leader) << SecureDebugString(tablet_locations);
@@ -676,7 +678,7 @@ TEST_F(AdminCliTest, TestUnsafeChangeConfigWithFiveReplicaConfig) {
   LOG(INFO) << "Waiting for Master to see new config...";
   ASSERT_OK(WaitForReplicasReportedToMaster(cluster_->master_proxy(),
                                             5, tablet_id_, kTimeout,
-                                            WAIT_FOR_LEADER,
+                                            WAIT_FOR_LEADER, VOTER_REPLICA,
                                             &has_leader, &tablet_locations));
   LOG(INFO) << "Tablet locations:\n" << SecureDebugString(tablet_locations);
   for (const master::TabletLocationsPB_ReplicaPB& replica :
@@ -714,7 +716,7 @@ TEST_F(AdminCliTest, TestUnsafeChangeConfigLeaderWithPendingConfig) {
   bool has_leader;
   ASSERT_OK(WaitForReplicasReportedToMaster(cluster_->master_proxy(),
                                             3, tablet_id_, kTimeout,
-                                            WAIT_FOR_LEADER,
+                                            WAIT_FOR_LEADER, VOTER_REPLICA,
                                             &has_leader, &tablet_locations));
   LOG(INFO) << "Tablet locations:\n" << SecureDebugString(tablet_locations);
   ASSERT_TRUE(has_leader) << SecureDebugString(tablet_locations);
@@ -772,7 +774,7 @@ TEST_F(AdminCliTest, TestUnsafeChangeConfigLeaderWithPendingConfig) {
   LOG(INFO) << "Waiting for Master to see new config...";
   ASSERT_OK(WaitForReplicasReportedToMaster(cluster_->master_proxy(),
                                             3, tablet_id_, kTimeout,
-                                            WAIT_FOR_LEADER,
+                                            WAIT_FOR_LEADER, VOTER_REPLICA,
                                             &has_leader, &tablet_locations));
   LOG(INFO) << "Tablet locations:\n" << SecureDebugString(tablet_locations);
   for (const master::TabletLocationsPB_ReplicaPB& replica :
@@ -810,7 +812,7 @@ TEST_F(AdminCliTest, TestUnsafeChangeConfigFollowerWithPendingConfig) {
   bool has_leader;
   ASSERT_OK(WaitForReplicasReportedToMaster(cluster_->master_proxy(),
                                             3, tablet_id_, kTimeout,
-                                            WAIT_FOR_LEADER,
+                                            WAIT_FOR_LEADER, VOTER_REPLICA,
                                             &has_leader, &tablet_locations));
   LOG(INFO) << "Tablet locations:\n" << SecureDebugString(tablet_locations);
   ASSERT_TRUE(has_leader) << SecureDebugString(tablet_locations);
@@ -879,7 +881,7 @@ TEST_F(AdminCliTest, TestUnsafeChangeConfigFollowerWithPendingConfig) {
   LOG(INFO) << "Waiting for Master to see new config...";
   ASSERT_OK(WaitForReplicasReportedToMaster(cluster_->master_proxy(),
                                             3, tablet_id_, kTimeout,
-                                            WAIT_FOR_LEADER,
+                                            WAIT_FOR_LEADER, VOTER_REPLICA,
                                             &has_leader, &tablet_locations));
   LOG(INFO) << "Tablet locations:\n" << SecureDebugString(tablet_locations);
   for (const master::TabletLocationsPB_ReplicaPB& replica :
@@ -917,7 +919,7 @@ TEST_F(AdminCliTest, TestUnsafeChangeConfigWithPendingConfigsOnWAL) {
   bool has_leader;
   ASSERT_OK(WaitForReplicasReportedToMaster(cluster_->master_proxy(),
                                             3, tablet_id_, kTimeout,
-                                            WAIT_FOR_LEADER,
+                                            WAIT_FOR_LEADER, VOTER_REPLICA,
                                             &has_leader, &tablet_locations));
   LOG(INFO) << "Tablet locations:\n" << SecureDebugString(tablet_locations);
   ASSERT_TRUE(has_leader) << SecureDebugString(tablet_locations);
@@ -984,7 +986,7 @@ TEST_F(AdminCliTest, TestUnsafeChangeConfigWithPendingConfigsOnWAL) {
   // Wait for the master to be notified of the config change.
   ASSERT_OK(WaitForReplicasReportedToMaster(cluster_->master_proxy(),
                                             3, tablet_id_, kTimeout,
-                                            WAIT_FOR_LEADER,
+                                            WAIT_FOR_LEADER, VOTER_REPLICA,
                                             &has_leader, &tablet_locations));
   LOG(INFO) << "Tablet locations:\n" << SecureDebugString(tablet_locations);
   for (const master::TabletLocationsPB_ReplicaPB& replica :
@@ -1029,7 +1031,7 @@ TEST_F(AdminCliTest, TestUnsafeChangeConfigWithMultiplePendingConfigs) {
   bool has_leader;
   ASSERT_OK(WaitForReplicasReportedToMaster(cluster_->master_proxy(),
                                             5, tablet_id_, kTimeout,
-                                            WAIT_FOR_LEADER,
+                                            WAIT_FOR_LEADER, VOTER_REPLICA,
                                             &has_leader, &tablet_locations));
   LOG(INFO) << "Tablet locations:\n" << SecureDebugString(tablet_locations);
   ASSERT_TRUE(has_leader) << SecureDebugString(tablet_locations);
@@ -1091,7 +1093,7 @@ TEST_F(AdminCliTest, TestUnsafeChangeConfigWithMultiplePendingConfigs) {
   LOG(INFO) << "Waiting for Master to see new config...";
   ASSERT_OK(WaitForReplicasReportedToMaster(cluster_->master_proxy(),
                                             5, tablet_id_, kTimeout,
-                                            WAIT_FOR_LEADER,
+                                            WAIT_FOR_LEADER, VOTER_REPLICA,
                                             &has_leader, &tablet_locations));
   LOG(INFO) << "Tablet locations:\n" << SecureDebugString(tablet_locations);
   for (const master::TabletLocationsPB_ReplicaPB& replica :


Mime
View raw message