YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/integration-tests/yb_table_test_base.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) YugaByte, Inc.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
4
// in compliance with the License.  You may obtain a copy of the License at
5
//
6
// http://www.apache.org/licenses/LICENSE-2.0
7
//
8
// Unless required by applicable law or agreed to in writing, software distributed under the License
9
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
10
// or implied.  See the License for the specific language governing permissions and limitations
11
// under the License.
12
//
13
14
#include "yb/integration-tests/yb_table_test_base.h"
15
16
#include "yb/client/client.h"
17
#include "yb/client/session.h"
18
#include "yb/client/table.h"
19
#include "yb/client/table_creator.h"
20
#include "yb/client/yb_op.h"
21
22
#include "yb/common/ql_value.h"
23
24
#include "yb/master/master_client.proxy.h"
25
26
#include "yb/tools/yb-admin_client.h"
27
28
#include "yb/tserver/mini_tablet_server.h"
29
#include "yb/tserver/tablet_server.h"
30
31
#include "yb/util/curl_util.h"
32
#include "yb/util/monotime.h"
33
#include "yb/util/result.h"
34
#include "yb/util/status_log.h"
35
#include "yb/util/string_util.h"
36
37
DECLARE_bool(enable_ysql);
38
39
using std::unique_ptr;
40
using std::shared_ptr;
41
42
namespace yb {
43
44
using client::YBClient;
45
using client::YBClientBuilder;
46
using client::YBColumnSchema;
47
using client::YBSchemaBuilder;
48
using client::YBSession;
49
using client::YBTableCreator;
50
using client::YBTableType;
51
using client::YBTableName;
52
using strings::Substitute;
53
54
namespace integration_tests {
55
56
22
YBTableTestBase::~YBTableTestBase() {
57
22
}
58
59
const YBTableName YBTableTestBase::kDefaultTableName(
60
    YQL_DATABASE_CQL, "my_keyspace", "kv-table-test");
61
62
95
size_t YBTableTestBase::num_masters() {
63
95
  return kDefaultNumMasters;
64
95
}
65
66
248
size_t YBTableTestBase::num_tablet_servers() {
67
248
  return kDefaultNumTabletServers;
68
248
}
69
70
33
int YBTableTestBase::num_drives() {
71
33
  return kDefaultNumDrives;
72
33
}
73
74
14
int YBTableTestBase::num_tablets() {
75
14
  return CalcNumTablets(num_tablet_servers());
76
14
}
77
78
28
int YBTableTestBase::session_timeout_ms() {
79
28
  return kDefaultSessionTimeoutMs;
80
28
}
81
82
96
YBTableName YBTableTestBase::table_name() {
83
96
  if (table_names_.empty()) {
84
19
    table_names_.push_back(kDefaultTableName);
85
19
  }
86
96
  return table_names_[0];
87
96
}
88
89
0
bool YBTableTestBase::need_redis_table() {
90
0
  return true;
91
0
}
92
93
172
int YBTableTestBase::client_rpc_timeout_ms() {
94
172
  return kDefaultClientRpcTimeoutMs;
95
172
}
96
97
5
bool YBTableTestBase::use_external_mini_cluster() {
98
5
  return kDefaultUsingExternalMiniCluster;
99
5
}
100
101
13
bool YBTableTestBase::use_yb_admin_client() {
102
13
  return false;
103
13
}
104
105
9
bool YBTableTestBase::enable_ysql() {
106
9
  return kDefaultEnableYSQL;
107
9
}
108
109
45
YBTableTestBase::YBTableTestBase() {
110
45
}
111
112
26
void YBTableTestBase::BeforeCreateTable() {
113
26
}
114
115
14
void YBTableTestBase::BeforeStartCluster() {
116
14
}
117
118
45
void YBTableTestBase::SetUp() {
119
45
  YBTest::SetUp();
120
121
45
  Status mini_cluster_status;
122
45
  if (use_external_mini_cluster()) {
123
26
    auto opts = ExternalMiniClusterOptions {
124
26
        .num_masters = num_masters(),
125
26
        .num_tablet_servers = num_tablet_servers(),
126
26
        .num_drives = num_drives(),
127
26
        .master_rpc_ports = master_rpc_ports(),
128
26
        .enable_ysql = enable_ysql()
129
26
    };
130
26
    CustomizeExternalMiniCluster(&opts);
131
132
26
    external_mini_cluster_.reset(new ExternalMiniCluster(opts));
133
26
    mini_cluster_status = external_mini_cluster_->Start();
134
19
  } else {
135
19
    auto opts = MiniClusterOptions {
136
19
        .num_masters = num_masters(),
137
19
        .num_tablet_servers = num_tablet_servers(),
138
19
        .num_drives = num_drives(),
139
19
        .master_env = env_.get(),
140
19
        .ts_env = ts_env_.get(),
141
19
        .ts_rocksdb_env = ts_rocksdb_env_.get()
142
19
    };
143
19
    SetAtomicFlag(enable_ysql(), &FLAGS_enable_ysql);
144
145
19
    mini_cluster_.reset(new MiniCluster(opts));
146
19
    BeforeStartCluster();
147
19
    mini_cluster_status = mini_cluster_->Start();
148
19
  }
149
45
  if (!mini_cluster_status.ok()) {
150
    // We sometimes crash during cleanup if the cluster creation fails and don't get to report
151
    // the root cause, so log it here just in case.
152
0
    LOG(INFO) << "Failed starting the mini cluster: " << mini_cluster_status.ToString();
153
0
  }
154
45
  ASSERT_OK(mini_cluster_status);
155
156
27
  CreateClient();
157
27
  CreateAdminClient();
158
159
27
  BeforeCreateTable();
160
161
27
  CreateTable();
162
27
  OpenTable();
163
27
}
164
165
22
void YBTableTestBase::TearDown() {
166
22
  DeleteTable();
167
168
  // Fetch the tablet server metrics page after we delete the table. [ENG-135].
169
22
  FetchTSMetricsPage();
170
171
22
  client_.reset();
172
22
  if (use_yb_admin_client()) {
173
17
    yb_admin_client_.reset();
174
17
  }
175
22
  if (use_external_mini_cluster()) {
176
20
    external_mini_cluster_->Shutdown();
177
2
  } else {
178
2
    mini_cluster_->Shutdown();
179
2
  }
180
22
  YBTest::TearDown();
181
22
}
182
183
26
vector<uint16_t> YBTableTestBase::master_rpc_ports() {
184
26
  vector<uint16_t> master_rpc_ports;
185
64
  for (size_t i = 0; i < num_masters(); ++i) {
186
38
    master_rpc_ports.push_back(0);
187
38
  }
188
26
  return master_rpc_ports;
189
26
}
190
191
27
void YBTableTestBase::CreateClient() {
192
27
  client_ = CreateYBClient();
193
27
}
194
195
29
std::unique_ptr<YBClient> YBTableTestBase::CreateYBClient() {
196
29
  YBClientBuilder builder;
197
29
  builder.default_rpc_timeout(MonoDelta::FromMilliseconds(client_rpc_timeout_ms()));
198
29
  if (use_external_mini_cluster()) {
199
28
    return CHECK_RESULT(external_mini_cluster_->CreateClient(&builder));
200
1
  } else {
201
1
    return CHECK_RESULT(mini_cluster_->CreateClient(&builder));
202
1
  }
203
29
}
204
205
26
void YBTableTestBase::CreateAdminClient() {
206
26
  if (use_yb_admin_client()) {
207
18
    string addrs;
208
18
    if (use_external_mini_cluster()) {
209
18
      addrs = external_mini_cluster_->GetMasterAddresses();
210
0
    }  else {
211
0
      addrs = mini_cluster_->GetMasterAddresses();
212
0
    }
213
18
    yb_admin_client_ = std::make_unique<tools::enterprise::ClusterAdminClient>(
214
18
        addrs, MonoDelta::FromMilliseconds(client_rpc_timeout_ms()));
215
216
18
    ASSERT_OK(yb_admin_client_->Init());
217
18
  }
218
26
}
219
220
26
void YBTableTestBase::OpenTable() {
221
26
  ASSERT_OK(table_.Open(table_name(), client_.get()));
222
26
  session_ = NewSession();
223
26
}
224
225
0
void YBTableTestBase::CreateRedisTable(const YBTableName& table_name) {
226
0
  CHECK(table_name.namespace_type() == YQLDatabase::YQL_DATABASE_REDIS);
227
228
0
  ASSERT_OK(client_->CreateNamespaceIfNotExists(table_name.namespace_name(),
229
0
                                                table_name.namespace_type()));
230
0
  ASSERT_OK(NewTableCreator()->table_name(table_name)
231
0
                .table_type(YBTableType::REDIS_TABLE_TYPE)
232
0
                .num_tablets(num_tablets())
233
0
                .Create());
234
0
}
235
236
18
void YBTableTestBase::CreateTable() {
237
18
  const auto tn = table_name();
238
18
  if (!table_exists_) {
239
18
    ASSERT_OK(client_->CreateNamespaceIfNotExists(tn.namespace_name(), tn.namespace_type()));
240
241
18
    YBSchemaBuilder b;
242
18
    b.AddColumn("k")->Type(BINARY)->NotNull()->HashPrimaryKey();
243
18
    b.AddColumn("v")->Type(BINARY)->NotNull();
244
18
    ASSERT_OK(b.Build(&schema_));
245
246
18
    ASSERT_OK(NewTableCreator()->table_name(tn).schema(&schema_).Create());
247
18
    table_exists_ = true;
248
18
  }
249
18
}
250
251
17
void YBTableTestBase::DeleteTable() {
252
17
  if (table_exists_) {
253
14
    ASSERT_OK(client_->DeleteTable(table_name()));
254
14
    table_exists_ = false;
255
14
  }
256
17
}
257
258
28
shared_ptr<YBSession> YBTableTestBase::NewSession() {
259
28
  shared_ptr<YBSession> session = client_->NewSession();
260
28
  session->SetTimeout(MonoDelta::FromMilliseconds(session_timeout_ms()));
261
28
  return session;
262
28
}
263
264
0
void YBTableTestBase::PutKeyValue(YBSession* session, string key, string value) {
265
0
  auto insert = table_.NewInsertOp();
266
0
  QLAddStringHashValue(insert->mutable_request(), key);
267
0
  table_.AddStringColumnValue(insert->mutable_request(), "v", value);
268
0
  ASSERT_OK(session->ApplyAndFlush(insert));
269
0
}
270
271
0
void YBTableTestBase::PutKeyValue(string key, string value) {
272
0
  PutKeyValue(session_.get(), key, value);
273
0
}
274
275
0
void YBTableTestBase::RestartCluster() {
276
0
  DCHECK(!use_external_mini_cluster());
277
0
  CHECK_OK(mini_cluster_->RestartSync());
278
0
  ASSERT_NO_FATALS(CreateClient());
279
0
  ASSERT_NO_FATALS(OpenTable());
280
0
}
281
282
14
Result<std::vector<uint32_t>> YBTableTestBase::GetTserverLoads(const std::vector<int>& ts_idxs) {
283
14
  std::vector<uint32_t> tserver_loads;
284
41
  for (const auto& ts_idx : ts_idxs) {
285
41
    tserver_loads.push_back(
286
41
        VERIFY_RESULT(GetLoadOnTserver(external_mini_cluster_->tablet_server(ts_idx))));
287
41
  }
288
14
  return tserver_loads;
289
14
}
290
291
43
Result<uint32_t> YBTableTestBase::GetLoadOnTserver(ExternalTabletServer* server) {
292
43
  auto proxy = GetMasterLeaderProxy<master::MasterClientProxy>();
293
43
  uint32_t count = 0;
294
43
  std::vector<string> replicas;
295
  // Need to get load from each table.
296
125
  for (const auto& table_name : table_names_) {
297
125
    master::GetTableLocationsRequestPB req;
298
125
    if (table_name.namespace_type() == YQL_DATABASE_PGSQL) {
299
      // Use table_id/namespace_id for SQL tables.
300
9
      req.mutable_table()->set_table_id(table_name.table_id());
301
9
      req.mutable_table()->mutable_namespace_()->set_id(table_name.namespace_id());
302
116
    } else {
303
116
      req.mutable_table()->set_table_name(table_name.table_name());
304
116
      req.mutable_table()->mutable_namespace_()->set_name(table_name.namespace_name());
305
116
    }
306
125
    master::GetTableLocationsResponsePB resp;
307
308
125
    rpc::RpcController rpc;
309
125
    rpc.set_timeout(MonoDelta::FromMilliseconds(client_rpc_timeout_ms()));
310
125
    RETURN_NOT_OK(proxy.GetTableLocations(req, &resp, &rpc));
311
312
587
    for (const auto& loc : resp.tablet_locations()) {
313
1.76k
      for (const auto& replica : loc.replicas()) {
314
1.76k
        if (replica.ts_info().permanent_uuid() == server->instance_id().permanent_uuid()) {
315
367
          replicas.push_back(loc.tablet_id());
316
367
          count++;
317
367
        }
318
1.76k
      }
319
587
    }
320
125
  }
321
322
43
  LOG(INFO) << Format("For ts $0, tablets are $1 with count $2",
323
43
                      server->instance_id().permanent_uuid(), VectorToString(replicas), count);
324
43
  return count;
325
43
}
326
327
std::vector<std::pair<std::string, std::string>> YBTableTestBase::GetScanResults(
328
0
    const client::TableRange& range) {
329
0
  std::vector<std::pair<std::string, std::string>> result;
330
0
  for (const auto& row : range) {
331
0
    result.emplace_back(row.column(0).binary_value(), row.column(1).binary_value());
332
0
  }
333
0
  std::sort(result.begin(), result.end());
334
0
  return result;
335
0
}
336
337
22
void YBTableTestBase::FetchTSMetricsPage() {
338
22
  EasyCurl c;
339
22
  faststring buf;
340
341
22
  string addr;
342
  // TODO: unify external and in-process mini cluster interfaces.
343
22
  if (use_external_mini_cluster()) {
344
20
    if (external_mini_cluster_->num_tablet_servers() > 0) {
345
20
      addr = external_mini_cluster_->tablet_server(0)->bound_http_hostport().ToString();
346
20
    }
347
2
  } else {
348
2
    if (mini_cluster_->num_tablet_servers() > 0) {
349
2
      addr = ToString(mini_cluster_->mini_tablet_server(0)->bound_http_addr());
350
2
    }
351
2
  }
352
353
22
  if (!addr.empty()) {
354
22
    LOG(INFO) << "Fetching metrics from " << addr;
355
22
    ASSERT_OK(c.FetchURL(Substitute("http://$0/metrics", addr), &buf));
356
22
  }
357
22
}
358
359
15
void YBTableTestBase::WaitForLoadBalanceCompletion(yb::MonoDelta timeout) {
360
15
  ASSERT_OK(WaitFor([&]() -> Result<bool> {
361
15
    bool is_idle = VERIFY_RESULT(client_->IsLoadBalancerIdle());
362
15
    return !is_idle;
363
15
  }, timeout, "IsLoadBalancerActive"));
364
365
15
  ASSERT_OK(WaitFor([&]() -> Result<bool> {
366
15
    return client_->IsLoadBalancerIdle();
367
15
  }, timeout, "IsLoadBalancerIdle"));
368
15
}
369
370
39
std::unique_ptr<client::YBTableCreator> YBTableTestBase::NewTableCreator() {
371
39
  unique_ptr<YBTableCreator> table_creator(client_->NewTableCreator());
372
39
  if (num_tablets() > 0) {
373
39
    table_creator->num_tablets(num_tablets());
374
39
  }
375
39
  table_creator->table_type(YBTableType::YQL_TABLE_TYPE);
376
39
  return table_creator;
377
39
}
378
379
}  // namespace integration_tests
380
}  // namespace yb