YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/integration-tests/ts_tablet_manager-itest.cc
Line
Count
Source (jump to first uncovered line)
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
//
18
// The following only applies to changes made to this file as part of YugaByte development.
19
//
20
// Portions Copyright (c) YugaByte, Inc.
21
//
22
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
23
// in compliance with the License.  You may obtain a copy of the License at
24
//
25
// http://www.apache.org/licenses/LICENSE-2.0
26
//
27
// Unless required by applicable law or agreed to in writing, software distributed under the License
28
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
29
// or implied.  See the License for the specific language governing permissions and limitations
30
// under the License.
31
//
32
33
#include <memory>
34
#include <string>
35
36
#include <gtest/gtest.h>
37
38
#include "yb/client/client.h"
39
#include "yb/client/schema.h"
40
#include "yb/client/table_creator.h"
41
42
#include "yb/common/partition.h"
43
44
#include "yb/consensus/consensus.h"
45
#include "yb/consensus/consensus.proxy.h"
46
#include "yb/consensus/metadata.pb.h"
47
#include "yb/consensus/quorum_util.h"
48
49
#include "yb/fs/fs_manager.h"
50
51
#include "yb/gutil/strings/substitute.h"
52
53
#include "yb/integration-tests/cluster_itest_util.h"
54
#include "yb/integration-tests/mini_cluster.h"
55
56
#include "yb/master/master_cluster.proxy.h"
57
#include "yb/master/master_heartbeat.pb.h"
58
#include "yb/master/mini_master.h"
59
60
#include "yb/rpc/messenger.h"
61
#include "yb/rpc/proxy.h"
62
63
#include "yb/server/server_base.proxy.h"
64
65
#include "yb/tablet/tablet_peer.h"
66
67
#include "yb/tserver/mini_tablet_server.h"
68
#include "yb/tserver/tablet_server.h"
69
#include "yb/tserver/ts_tablet_manager.h"
70
#include "yb/tserver/tserver_admin.proxy.h"
71
#include "yb/tserver/tserver_service.proxy.h"
72
73
#include "yb/util/test_util.h"
74
75
DECLARE_bool(enable_leader_failure_detection);
76
DECLARE_bool(catalog_manager_wait_for_new_tablets_to_elect_leader);
77
DEFINE_int32(num_election_test_loops, 3,
78
             "Number of random EmulateElection() loops to execute in "
79
             "TestReportNewLeaderOnLeaderChange");
80
DECLARE_bool(enable_ysql);
81
DECLARE_bool(use_create_table_leader_hint);
82
83
namespace yb {
84
namespace tserver {
85
86
using client::YBClient;
87
using client::YBSchema;
88
using client::YBTable;
89
using client::YBTableCreator;
90
using client::YBTableName;
91
using consensus::GetConsensusRole;
92
using consensus::RaftPeerPB;
93
using itest::SimpleIntKeyYBSchema;
94
using master::ReportedTabletPB;
95
using master::TabletReportPB;
96
using rpc::Messenger;
97
using rpc::MessengerBuilder;
98
using strings::Substitute;
99
using tablet::TabletPeer;
100
using tserver::MiniTabletServer;
101
using tserver::TSTabletManager;
102
103
static const YBTableName kTableName(YQL_DATABASE_CQL, "my_keyspace", "test-table");
104
static const int kNumReplicas = 3;
105
106
class TsTabletManagerITest : public YBTest {
107
 public:
108
  TsTabletManagerITest()
109
1
      : schema_(SimpleIntKeyYBSchema()) {
110
1
  }
111
  void SetUp() override;
112
  void TearDown() override;
113
114
 protected:
115
  const YBSchema schema_;
116
117
  std::unique_ptr<MiniCluster> cluster_;
118
  std::unique_ptr<Messenger> client_messenger_;
119
  std::unique_ptr<YBClient> client_;
120
};
121
122
1
void TsTabletManagerITest::SetUp() {
123
  // We don't need the transaction status table to be created.
124
1
  SetAtomicFlag(false, &FLAGS_enable_ysql);
125
1
  YBTest::SetUp();
126
127
1
  MessengerBuilder bld("client");
128
1
  client_messenger_ = ASSERT_RESULT(bld.Build());
129
1
  client_messenger_->TEST_SetOutboundIpBase(ASSERT_RESULT(HostToAddress("127.0.0.1")));
130
131
1
  MiniClusterOptions opts;
132
1
  opts.num_tablet_servers = kNumReplicas;
133
1
  cluster_.reset(new MiniCluster(opts));
134
1
  ASSERT_OK(cluster_->Start());
135
0
  client_ = ASSERT_RESULT(cluster_->CreateClient(client_messenger_.get()));
136
0
}
137
138
1
void TsTabletManagerITest::TearDown() {
139
1
  client_.reset();
140
1
  client_messenger_->Shutdown();
141
1
  cluster_->Shutdown();
142
1
  YBTest::TearDown();
143
1
}
144
145
// Test that when the leader changes, the tablet manager gets notified and
146
// includes that information in the next tablet report.
147
0
TEST_F(TsTabletManagerITest, TestReportNewLeaderOnLeaderChange) {
148
  // We need to control elections precisely for this test since we're using
149
  // EmulateElection() with a distributed consensus configuration.
150
0
  FLAGS_enable_leader_failure_detection = false;
151
0
  FLAGS_catalog_manager_wait_for_new_tablets_to_elect_leader = false;
152
0
  FLAGS_use_create_table_leader_hint = false;
153
154
  // Run a few more iters in slow-test mode.
155
0
  OverrideFlagForSlowTests("num_election_test_loops", "10");
156
157
0
  ASSERT_OK(client_->CreateNamespaceIfNotExists(kTableName.namespace_name(),
158
0
                                                kTableName.namespace_type()));
159
  // Create the table.
160
0
  std::shared_ptr<YBTable> table;
161
0
  std::unique_ptr<YBTableCreator> table_creator(client_->NewTableCreator());
162
0
  ASSERT_OK(table_creator->table_name(kTableName)
163
0
            .schema(&schema_)
164
0
            .hash_schema(YBHashSchema::kMultiColumnHash)
165
0
            .num_tablets(1)
166
0
            .Create());
167
0
  ASSERT_OK(client_->OpenTable(kTableName, &table));
168
169
0
  rpc::ProxyCache proxy_cache(client_messenger_.get());
170
171
  // Build a TServerDetails map so we can check for convergence.
172
0
  master::MasterClusterProxy master_proxy(&proxy_cache, cluster_->mini_master()->bound_rpc_addr());
173
174
0
  auto ts_map = ASSERT_RESULT(itest::CreateTabletServerMap(master_proxy, &proxy_cache));
175
176
  // Collect the tablet peers so we get direct access to consensus.
177
0
  vector<std::shared_ptr<TabletPeer> > tablet_peers;
178
0
  for (int replica = 0; replica < kNumReplicas; replica++) {
179
0
    MiniTabletServer* ts = cluster_->mini_tablet_server(replica);
180
0
    ts->FailHeartbeats(); // Stop heartbeating we don't race against the Master.
181
0
    vector<std::shared_ptr<TabletPeer> > cur_ts_tablet_peers;
182
    // The replicas may not have been created yet, so loop until we see them.
183
0
    while (true) {
184
0
      cur_ts_tablet_peers = ts->server()->tablet_manager()->GetTabletPeers();
185
0
      if (!cur_ts_tablet_peers.empty()) break;
186
0
      SleepFor(MonoDelta::FromMilliseconds(10));
187
0
    }
188
0
    ASSERT_EQ(1, cur_ts_tablet_peers.size());
189
0
    ASSERT_OK(cur_ts_tablet_peers[0]->WaitUntilConsensusRunning(MonoDelta::FromSeconds(10)));
190
0
    tablet_peers.push_back(cur_ts_tablet_peers[0]);
191
0
  }
192
193
  // Loop and cause elections and term changes from different servers.
194
  // TSTabletManager should acknowledge the role changes via tablet reports.
195
0
  unsigned int seed = SeedRandom();
196
0
  for (int i = 0; i < FLAGS_num_election_test_loops; i++) {
197
0
    SCOPED_TRACE(Substitute("Iter: $0", i));
198
0
    int new_leader_idx = rand_r(&seed) % 2;
199
0
    LOG(INFO) << "Electing peer " << new_leader_idx << "...";
200
0
    consensus::Consensus* con = CHECK_NOTNULL(tablet_peers[new_leader_idx]->consensus());
201
0
    ASSERT_OK(con->EmulateElection());
202
0
    LOG(INFO) << "Waiting for servers to agree...";
203
0
    ASSERT_OK(WaitForServersToAgree(MonoDelta::FromSeconds(5),
204
0
                                    ts_map, tablet_peers[0]->tablet_id(), i + 1));
205
206
    // Now check that the tablet report reports the correct role for both servers.
207
0
    for (int replica = 0; replica < kNumReplicas; replica++) {
208
      // The MarkDirty() callback is on an async thread so it might take the
209
      // follower a few milliseconds to execute it. Wait for that to happen.
210
0
      TSTabletManager* tablet_manager =
211
0
          cluster_->mini_tablet_server(replica)->server()->tablet_manager();
212
0
      for (int retry = 0; retry <= 12; retry++) {
213
0
        if (tablet_manager->TEST_GetNumDirtyTablets() > 0) break;
214
0
        SleepFor(MonoDelta::FromMilliseconds(1 << retry));
215
0
      }
216
217
      // Ensure that our tablet reports are consistent.
218
0
      TabletReportPB report;
219
0
      tablet_manager->GenerateTabletReport(&report);
220
0
      ASSERT_EQ(1, report.updated_tablets_size()) << "Wrong report size:\n" << report.DebugString();
221
0
      ReportedTabletPB reported_tablet = report.updated_tablets(0);
222
0
      ASSERT_TRUE(reported_tablet.has_committed_consensus_state());
223
224
0
      string uuid = tablet_peers[replica]->permanent_uuid();
225
0
      PeerRole role = GetConsensusRole(uuid, reported_tablet.committed_consensus_state());
226
0
      if (replica == new_leader_idx) {
227
0
        ASSERT_EQ(PeerRole::LEADER, role)
228
0
            << "Tablet report: " << report.ShortDebugString();
229
0
      } else {
230
0
        ASSERT_EQ(PeerRole::FOLLOWER, role)
231
0
            << "Tablet report: " << report.ShortDebugString();
232
0
      }
233
0
    }
234
0
  }
235
0
}
236
237
}  // namespace tserver
238
}  // namespace yb