YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/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
35
YBTableTestBase::~YBTableTestBase() {
57
35
}
58
59
const YBTableName YBTableTestBase::kDefaultTableName(
60
    YQL_DATABASE_CQL, "my_keyspace", "kv-table-test");
61
62
241
size_t YBTableTestBase::num_masters() {
63
241
  return kDefaultNumMasters;
64
241
}
65
66
370
size_t YBTableTestBase::num_tablet_servers() {
67
370
  return kDefaultNumTabletServers;
68
370
}
69
70
154
int YBTableTestBase::num_drives() {
71
154
  return kDefaultNumDrives;
72
154
}
73
74
50
int YBTableTestBase::num_tablets() {
75
50
  return CalcNumTablets(num_tablet_servers());
76
50
}
77
78
40
int YBTableTestBase::session_timeout_ms() {
79
40
  return kDefaultSessionTimeoutMs;
80
40
}
81
82
107
YBTableName YBTableTestBase::table_name() {
83
107
  if (table_names_.empty()) {
84
30
    table_names_.push_back(kDefaultTableName);
85
30
  }
86
107
  return table_names_[0];
87
107
}
88
89
0
bool YBTableTestBase::need_redis_table() {
90
0
  return true;
91
0
}
92
93
206
int YBTableTestBase::client_rpc_timeout_ms() {
94
206
  return kDefaultClientRpcTimeoutMs;
95
206
}
96
97
107
bool YBTableTestBase::use_external_mini_cluster() {
98
107
  return kDefaultUsingExternalMiniCluster;
99
107
}
100
101
36
bool YBTableTestBase::use_yb_admin_client() {
102
36
  return false;
103
36
}
104
105
18
bool YBTableTestBase::enable_ysql() {
106
18
  return kDefaultEnableYSQL;
107
18
}
108
109
166
YBTableTestBase::YBTableTestBase() {
110
166
}
111
112
38
void YBTableTestBase::BeforeCreateTable() {
113
38
}
114
115
112
void YBTableTestBase::BeforeStartCluster() {
116
112
}
117
118
166
void YBTableTestBase::SetUp() {
119
166
  YBTest::SetUp();
120
121
166
  Status mini_cluster_status;
122
166
  if (use_external_mini_cluster()) {
123
49
    auto opts = ExternalMiniClusterOptions {
124
49
        .num_masters = num_masters(),
125
49
        .num_tablet_servers = num_tablet_servers(),
126
49
        .num_drives = num_drives(),
127
49
        .master_rpc_ports = master_rpc_ports(),
128
49
        .enable_ysql = enable_ysql()
129
49
    };
130
49
    CustomizeExternalMiniCluster(&opts);
131
132
49
    external_mini_cluster_.reset(new ExternalMiniCluster(opts));
133
49
    mini_cluster_status = external_mini_cluster_->Start();
134
117
  } else {
135
117
    auto opts = MiniClusterOptions {
136
117
        .num_masters = num_masters(),
137
117
        .num_tablet_servers = num_tablet_servers(),
138
117
        .num_drives = num_drives(),
139
117
        .master_env = env_.get(),
140
117
        .ts_env = ts_env_.get(),
141
117
        .ts_rocksdb_env = ts_rocksdb_env_.get()
142
117
    };
143
117
    SetAtomicFlag(enable_ysql(), &FLAGS_enable_ysql);
144
145
117
    mini_cluster_.reset(new MiniCluster(opts));
146
117
    BeforeStartCluster();
147
117
    mini_cluster_status = mini_cluster_->Start();
148
117
  }
149
166
  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
166
  ASSERT_OK(mini_cluster_status);
155
156
50
  CreateClient();
157
50
  CreateAdminClient();
158
159
50
  BeforeCreateTable();
160
161
50
  CreateTable();
162
50
  OpenTable();
163
50
}
164
165
35
void YBTableTestBase::TearDown() {
166
35
  DeleteTable();
167
168
  // Fetch the tablet server metrics page after we delete the table. [ENG-135].
169
35
  FetchTSMetricsPage();
170
171
35
  client_.reset();
172
35
  if (use_yb_admin_client()) {
173
19
    yb_admin_client_.reset();
174
19
  }
175
35
  if (use_external_mini_cluster()) {
176
32
    external_mini_cluster_->Shutdown();
177
32
  } else {
178
3
    mini_cluster_->Shutdown();
179
3
  }
180
35
  YBTest::TearDown();
181
35
}
182
183
49
vector<uint16_t> YBTableTestBase::master_rpc_ports() {
184
49
  vector<uint16_t> master_rpc_ports;
185
132
  for (size_t i = 0; i < num_masters(); 
++i83
) {
186
83
    master_rpc_ports.push_back(0);
187
83
  }
188
49
  return master_rpc_ports;
189
49
}
190
191
50
void YBTableTestBase::CreateClient() {
192
50
  client_ = CreateYBClient();
193
50
}
194
195
52
std::unique_ptr<YBClient> YBTableTestBase::CreateYBClient() {
196
52
  YBClientBuilder builder;
197
52
  builder.default_rpc_timeout(MonoDelta::FromMilliseconds(client_rpc_timeout_ms()));
198
52
  if (use_external_mini_cluster()) {
199
51
    return CHECK_RESULT(external_mini_cluster_->CreateClient(&builder));
200
51
  } else {
201
1
    return CHECK_RESULT(mini_cluster_->CreateClient(&builder));
202
1
  }
203
52
}
204
205
49
void YBTableTestBase::CreateAdminClient() {
206
49
  if (use_yb_admin_client()) {
207
29
    string addrs;
208
29
    if (use_external_mini_cluster()) {
209
29
      addrs = external_mini_cluster_->GetMasterAddresses();
210
29
    }  else {
211
0
      addrs = mini_cluster_->GetMasterAddresses();
212
0
    }
213
29
    yb_admin_client_ = std::make_unique<tools::enterprise::ClusterAdminClient>(
214
29
        addrs, MonoDelta::FromMilliseconds(client_rpc_timeout_ms()));
215
216
29
    ASSERT_OK(yb_admin_client_->Init());
217
29
  }
218
49
}
219
220
38
void YBTableTestBase::OpenTable() {
221
38
  ASSERT_OK(table_.Open(table_name(), client_.get()));
222
38
  session_ = NewSession();
223
38
}
224
225
12
void YBTableTestBase::CreateRedisTable(const YBTableName& table_name) {
226
12
  CHECK(table_name.namespace_type() == YQLDatabase::YQL_DATABASE_REDIS);
227
228
12
  ASSERT_OK(client_->CreateNamespaceIfNotExists(table_name.namespace_name(),
229
12
                                                table_name.namespace_type()));
230
12
  ASSERT_OK(NewTableCreator()->table_name(table_name)
231
12
                .table_type(YBTableType::REDIS_TABLE_TYPE)
232
12
                .num_tablets(num_tablets())
233
12
                .Create());
234
12
}
235
236
29
void YBTableTestBase::CreateTable() {
237
29
  const auto tn = table_name();
238
29
  if (!table_exists_) {
239
29
    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
29
}
250
251
32
void YBTableTestBase::DeleteTable() {
252
32
  if (table_exists_) {
253
26
    ASSERT_OK(client_->DeleteTable(table_name()));
254
26
    table_exists_ = false;
255
26
  }
256
32
}
257
258
40
shared_ptr<YBSession> YBTableTestBase::NewSession() {
259
40
  shared_ptr<YBSession> session = client_->NewSession();
260
40
  session->SetTimeout(MonoDelta::FromMilliseconds(session_timeout_ms()));
261
40
  return session;
262
40
}
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())125
{
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
35
void YBTableTestBase::FetchTSMetricsPage() {
338
35
  EasyCurl c;
339
35
  faststring buf;
340
341
35
  string addr;
342
  // TODO: unify external and in-process mini cluster interfaces.
343
35
  if (use_external_mini_cluster()) {
344
32
    if (external_mini_cluster_->num_tablet_servers() > 0) {
345
32
      addr = external_mini_cluster_->tablet_server(0)->bound_http_hostport().ToString();
346
32
    }
347
32
  } else {
348
3
    if (mini_cluster_->num_tablet_servers() > 0) {
349
3
      addr = ToString(mini_cluster_->mini_tablet_server(0)->bound_http_addr());
350
3
    }
351
3
  }
352
353
35
  if (!addr.empty()) {
354
35
    LOG(INFO) << "Fetching metrics from " << addr;
355
35
    ASSERT_OK(c.FetchURL(Substitute("http://$0/metrics", addr), &buf));
356
35
  }
357
35
}
358
359
14
void YBTableTestBase::WaitForLoadBalanceCompletion(yb::MonoDelta timeout) {
360
14
  ASSERT_OK(WaitFor([&]() -> Result<bool> {
361
14
    bool is_idle = VERIFY_RESULT(client_->IsLoadBalancerIdle());
362
14
    return !is_idle;
363
14
  }, timeout, "IsLoadBalancerActive"));
364
365
14
  ASSERT_OK(WaitFor([&]() -> Result<bool> {
366
14
    return client_->IsLoadBalancerIdle();
367
14
  }, timeout, "IsLoadBalancerIdle"));
368
14
}
369
370
51
std::unique_ptr<client::YBTableCreator> YBTableTestBase::NewTableCreator() {
371
51
  unique_ptr<YBTableCreator> table_creator(client_->NewTableCreator());
372
51
  if (num_tablets() > 0) {
373
51
    table_creator->num_tablets(num_tablets());
374
51
  }
375
51
  table_creator->table_type(YBTableType::YQL_TABLE_TYPE);
376
51
  return table_creator;
377
51
}
378
379
}  // namespace integration_tests
380
}  // namespace yb