YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/integration-tests/master_replication-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 <functional>
34
#include <memory>
35
#include <string>
36
#include <unordered_map>
37
#include <unordered_set>
38
#include <utility>
39
#include <vector>
40
41
#include <boost/optional/optional.hpp>
42
#include <glog/logging.h>
43
#include <gtest/gtest.h>
44
45
#include "yb/client/client.h"
46
#include "yb/client/schema.h"
47
#include "yb/client/table_creator.h"
48
49
#include "yb/common/column_id.h"
50
#include "yb/common/common.pb.h"
51
#include "yb/common/entity_ids_types.h"
52
#include "yb/common/hybrid_time.h"
53
#include "yb/common/partition.h"
54
55
#include "yb/gutil/algorithm.h"
56
57
#include "yb/integration-tests/mini_cluster.h"
58
#include "yb/integration-tests/yb_mini_cluster_test_base.h"
59
60
#include "yb/master/master.h"
61
#include "yb/master/mini_master.h"
62
63
#include "yb/util/memory/arena_fwd.h"
64
#include "yb/util/status.h"
65
#include "yb/util/status_log.h"
66
#include "yb/util/test_util.h"
67
#include "yb/util/thread.h"
68
#include "yb/util/uuid.h"
69
70
using std::vector;
71
72
namespace yb {
73
namespace master {
74
75
using client::YBClient;
76
using client::YBClientBuilder;
77
using client::YBColumnSchema;
78
using client::YBSchema;
79
using client::YBSchemaBuilder;
80
using client::YBTable;
81
using client::YBTableCreator;
82
using client::YBTableName;
83
using std::shared_ptr;
84
85
const std::string kKeyspaceName("my_keyspace");
86
const YBTableName kTableName1(YQL_DATABASE_CQL, kKeyspaceName, "testMasterReplication-1");
87
const YBTableName kTableName2(YQL_DATABASE_CQL, kKeyspaceName, "testMasterReplication-2");
88
89
const int kNumTabletServerReplicas = 3;
90
91
class MasterReplicationTest : public YBMiniClusterTestBase<MiniCluster> {
92
 public:
93
4
  MasterReplicationTest() {
94
4
    opts_.num_masters = num_masters_ = 3;
95
4
    opts_.num_tablet_servers = kNumTabletServerReplicas;
96
4
  }
97
98
4
  void SetUp() override {
99
4
    YBMiniClusterTestBase::SetUp();
100
4
    cluster_.reset(new MiniCluster(opts_));
101
4
    ASSERT_OK(cluster_->Start());
102
0
    ASSERT_OK(cluster_->WaitForTabletServerCount(kNumTabletServerReplicas));
103
0
  }
104
105
1
  void DoTearDown() override {
106
1
    if (cluster_) {
107
1
      cluster_->Shutdown();
108
1
      cluster_.reset();
109
1
    }
110
1
    YBMiniClusterTestBase::DoTearDown();
111
1
  }
112
113
  // This method is meant to be run in a separate thread.
114
0
  void StartClusterDelayed(int64_t micros) {
115
0
    LOG(INFO) << "Sleeping for "  << micros << " micro seconds...";
116
0
    SleepFor(MonoDelta::FromMicroseconds(micros));
117
0
    LOG(INFO) << "Attempting to start the cluster...";
118
0
    CHECK_OK(cluster_->Start());
119
0
    CHECK_OK(cluster_->WaitForTabletServerCount(kNumTabletServerReplicas));
120
0
  }
121
122
0
  void ListMasterServerAddrs(vector<string>* out) {
123
0
    for (int i = 0; i < num_masters_; i++) {
124
0
      out->push_back(cluster_->mini_master(i)->bound_rpc_addr_str());
125
0
    }
126
0
  }
127
128
0
  Result<std::unique_ptr<client::YBClient>> CreateClient() {
129
0
    YBClientBuilder builder;
130
0
    for (int i = 0; i < num_masters_; i++) {
131
0
      if (!cluster_->mini_master(i)->master()->IsShutdown()) {
132
0
        builder.add_master_server_addr(cluster_->mini_master(i)->bound_rpc_addr_str());
133
0
      }
134
0
    }
135
136
0
    auto client = VERIFY_RESULT(builder.Build());
137
0
    RETURN_NOT_OK(client->CreateNamespaceIfNotExists(kKeyspaceName));
138
0
    return client;
139
0
  }
140
141
  Status CreateTable(YBClient* client,
142
0
                     const YBTableName& table_name) {
143
0
    YBSchema schema;
144
0
    YBSchemaBuilder b;
145
0
    b.AddColumn("key")->Type(INT32)->NotNull()->PrimaryKey();
146
0
    b.AddColumn("int_val")->Type(INT32)->NotNull();
147
0
    b.AddColumn("string_val")->Type(STRING)->NotNull();
148
0
    CHECK_OK(b.Build(&schema));
149
0
    std::unique_ptr<YBTableCreator> table_creator(client->NewTableCreator());
150
0
    return table_creator->table_name(table_name)
151
0
        .schema(&schema)
152
0
        .hash_schema(YBHashSchema::kMultiColumnHash)
153
0
        .Create();
154
0
  }
155
156
  void VerifyTableExists(YBClient* client,
157
0
                         const YBTableName& table_name) {
158
0
    LOG(INFO) << "Verifying that " << table_name.ToString() << " exists on leader..";
159
0
    const auto tables = ASSERT_RESULT(client->ListTables());
160
0
    ASSERT_TRUE(::util::gtl::contains(tables.begin(), tables.end(), table_name));
161
0
  }
162
163
0
  void VerifyMasterRestart() {
164
0
    LOG(INFO) << "Check that all " << num_masters_ << " masters are up first.";
165
0
    for (int i = 0; i < num_masters_; ++i) {
166
0
      LOG(INFO) << "Checking master " << i;
167
0
      auto* master = cluster_->mini_master(i)->master();
168
0
      ASSERT_FALSE(master->IsShutdown());
169
0
      ASSERT_OK(master->WaitForCatalogManagerInit());
170
0
    }
171
172
0
    LOG(INFO) << "Restart the first master -- expected to succeed.";
173
0
    auto* first_master = cluster_->mini_master(0);
174
0
    ASSERT_OK(first_master->Restart());
175
176
0
    LOG(INFO) << "Shutdown the master.";
177
0
    first_master->Shutdown();
178
179
0
    LOG(INFO) << "Normal start call should also work fine (and just reload the sys catalog).";
180
0
    ASSERT_OK(first_master->Start());
181
0
  }
182
183
 protected:
184
  int num_masters_;
185
  MiniClusterOptions opts_;
186
};
187
188
0
TEST_F(MasterReplicationTest, TestMasterClusterCreate) {
189
0
  DontVerifyClusterBeforeNextTearDown();
190
191
  // We want to confirm that the cluster starts properly and fails if you restart it.
192
0
  ASSERT_NO_FATAL_FAILURE(VerifyMasterRestart());
193
0
}
194
195
// Basic test. Verify that:
196
//
197
// 1) We can start multiple masters in a distributed configuration and
198
// that the clients and tablet servers can connect to the leader
199
// master.
200
//
201
// 2) We can create a table (using the standard client APIs) on the
202
// the leader and ensure that the appropriate table/tablet info is
203
// replicated to the newly elected leader.
204
0
TEST_F(MasterReplicationTest, TestSysTablesReplication) {
205
  // Create the first table.
206
0
  auto client = ASSERT_RESULT(CreateClient());
207
0
  ASSERT_OK(CreateTable(client.get(), kTableName1));
208
209
  // TODO: once fault tolerant DDL is in, remove the line below.
210
0
  client = ASSERT_RESULT(CreateClient());
211
212
0
  ASSERT_OK(cluster_->WaitForTabletServerCount(kNumTabletServerReplicas));
213
214
  // Repeat the same for the second table.
215
0
  ASSERT_OK(CreateTable(client.get(), kTableName2));
216
0
  ASSERT_NO_FATALS(VerifyTableExists(client.get(), kTableName2));
217
0
}
218
219
// When all masters are down, test that we can timeout the connection
220
// attempts after a specified deadline.
221
0
TEST_F(MasterReplicationTest, TestTimeoutWhenAllMastersAreDown) {
222
0
  vector<string> master_addrs;
223
0
  ListMasterServerAddrs(&master_addrs);
224
225
0
  cluster_->Shutdown();
226
227
0
  YBClientBuilder builder;
228
0
  builder.master_server_addrs(master_addrs);
229
0
  builder.default_rpc_timeout(MonoDelta::FromMilliseconds(100));
230
0
  auto result = builder.Build();
231
0
  EXPECT_TRUE(!result.ok());
232
0
  EXPECT_TRUE(result.status().IsTimedOut());
233
234
  // We need to reset 'cluster_' so that TearDown() can run correctly.
235
0
  cluster_.reset();
236
0
}
237
238
// Shut the cluster down, start initializing the client, and then
239
// bring the cluster back up during the initialization (but before the
240
// timeout can elapse).
241
0
TEST_F(MasterReplicationTest, TestCycleThroughAllMasters) {
242
0
  DontVerifyClusterBeforeNextTearDown();
243
0
  vector<string> master_addrs;
244
0
  ListMasterServerAddrs(&master_addrs);
245
246
  // Shut the cluster down and ...
247
0
  cluster_->Shutdown();
248
  // ... start the cluster after a delay.
249
0
  scoped_refptr<yb::Thread> start_thread;
250
0
  ASSERT_OK(Thread::Create(
251
0
      "TestCycleThroughAllMasters", "start_thread",
252
0
      &MasterReplicationTest::StartClusterDelayed,
253
0
      this,
254
0
      100 * 1000, // start after 100 millis.
255
0
      &start_thread));
256
257
  // Verify that the client doesn't give up even though the entire
258
  // cluster is down for 100 milliseconds.
259
0
  YBClientBuilder builder;
260
0
  builder.master_server_addrs(master_addrs);
261
  // Bumped up timeout from 15 sec to 30 sec because master election can take longer than 15 sec.
262
  // https://yugabyte.atlassian.net/browse/ENG-51
263
  // Test log: https://gist.githubusercontent.com/mbautin/9f4269292e6ecb5b9a2fc644e2ee4398/raw
264
0
  builder.default_admin_operation_timeout(MonoDelta::FromSeconds(30));
265
0
  EXPECT_OK(builder.Build());
266
267
0
  ASSERT_OK(ThreadJoiner(start_thread.get()).Join());
268
0
}
269
270
}  // namespace master
271
}  // namespace yb