YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/master/yql_peers_vtable.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/master/yql_peers_vtable.h"
15
16
#include "yb/common/ql_protocol.pb.h"
17
#include "yb/common/ql_type.h"
18
#include "yb/common/schema.h"
19
20
#include "yb/master/master.h"
21
#include "yb/master/master_heartbeat.pb.h"
22
#include "yb/master/ts_descriptor.h"
23
24
#include "yb/rpc/messenger.h"
25
26
#include "yb/util/net/dns_resolver.h"
27
#include "yb/util/net/inetaddress.h"
28
#include "yb/util/status_log.h"
29
30
namespace yb {
31
namespace master {
32
33
using std::string;
34
using std::shared_ptr;
35
using std::unique_ptr;
36
using std::map;
37
38
namespace {
39
40
const std::string kPeer = "peer";
41
const std::string kDataCenter = "data_center";
42
const std::string kHostId = "host_id";
43
const std::string kPreferredIp = "preferred_ip";
44
const std::string kRack = "rack";
45
const std::string kReleaseVersion = "release_version";
46
const std::string kRPCAddress = "rpc_address";
47
const std::string kSchemaVersion = "schema_version";
48
const std::string kTokens = "tokens";
49
50
} // namespace
51
52
PeersVTable::PeersVTable(const TableName& table_name,
53
                         const NamespaceName& namespace_name,
54
                         Master* const master)
55
3.00k
    : YQLVirtualTable(table_name, namespace_name, master, CreateSchema()) {
56
3.00k
}
57
58
Result<std::shared_ptr<QLRowBlock>> PeersVTable::RetrieveData(
59
47.4k
    const QLReadRequestPB& request) const {
60
  // Retrieve all lives nodes known by the master.
61
  // TODO: Ideally we would like to populate this table with all valid nodes of the cluster, but
62
  // currently the master just has a list of all nodes it has heard from and which one of those
63
  // are dead. As a result, the master can't distinguish between nodes that are part of the
64
  // cluster and are dead vs nodes that have been removed from the cluster. Since, we might
65
  // change the cluster topology often, for now its safe to just have the live nodes here.
66
47.4k
  vector<shared_ptr<TSDescriptor> > descs;
67
47.4k
  GetSortedLiveDescriptors(&descs);
68
69
47.4k
  auto& resolver = master_->messenger()->resolver();
70
71
  // Collect all unique ip addresses.
72
47.4k
  InetAddress remote_endpoint(VERIFY_RESULT(resolver.Resolve(request.remote_endpoint().host())));
73
74
0
  const auto& proxy_uuid = request.proxy_uuid();
75
76
  // Populate the YQL rows.
77
47.4k
  auto vtable = std::make_shared<QLRowBlock>(schema());
78
79
47.4k
  struct Entry {
80
47.4k
    size_t index;
81
47.4k
    TSInformationPB ts_info;
82
47.4k
    util::PublicPrivateIPFutures ts_ips;
83
47.4k
  };
84
85
47.4k
  std::vector<Entry> entries;
86
47.4k
  entries.reserve(descs.size());
87
88
47.4k
  size_t index = 0;
89
146k
  for (const auto& desc : descs) {
90
146k
    size_t current_index = index++;
91
92
    // This is thread safe since all operations are reads.
93
146k
    TSInformationPB ts_info = *desc->GetTSInformationPB();
94
95
146k
    if (
!proxy_uuid.empty()146k
) {
96
146k
      if (desc->permanent_uuid() == proxy_uuid) {
97
47.3k
        continue;
98
47.3k
      }
99
18.4E
    } else {
100
      // In case of old proxy, fallback to old endpoint based mechanism.
101
18.4E
      if (util::RemoteEndpointMatchesTServer(ts_info, remote_endpoint)) {
102
1
        continue;
103
1
      }
104
18.4E
    }
105
106
99.0k
    entries.push_back({current_index, std::move(ts_info)});
107
99.0k
    auto& entry = entries.back();
108
99.0k
    entry.ts_ips = util::GetPublicPrivateIPFutures(entry.ts_info, &resolver);
109
99.0k
  }
110
111
99.0k
  for (const auto& entry : entries) {
112
    // The system.peers table has one entry for each of its peers, whereas there is no entry for
113
    // the node that the CQL client connects to. In this case, this node is the 'remote_endpoint'
114
    // in QLReadRequestPB since that is address of the CQL proxy which sent this request. As a
115
    // result, skip 'remote_endpoint' in the results.
116
99.0k
    auto private_ip = entry.ts_ips.private_ip_future.get();
117
99.0k
    if (!private_ip.ok()) {
118
0
      LOG(ERROR) << "Failed to get private ip from " << entry.ts_info.ShortDebugString()
119
0
                 << ": " << private_ip.status();
120
0
      continue;
121
0
    }
122
123
99.0k
    auto public_ip = entry.ts_ips.public_ip_future.get();
124
99.0k
    if (!public_ip.ok()) {
125
0
      LOG(ERROR) << "Failed to get public ip from " << entry.ts_info.ShortDebugString()
126
0
                 << ": " << public_ip.status();
127
0
      continue;
128
0
    }
129
130
    // Need to use only 1 rpc address per node since system.peers has only 1 entry for each host,
131
    // so pick the first one.
132
99.0k
    QLRow &row = vtable->Extend();
133
99.0k
    RETURN_NOT_OK(SetColumnValue(kPeer, InetAddress(*public_ip), &row));
134
99.0k
    RETURN_NOT_OK(SetColumnValue(kRPCAddress, InetAddress(*public_ip), &row));
135
99.0k
    RETURN_NOT_OK(SetColumnValue(kPreferredIp, InetAddress(*private_ip), &row));
136
137
    // Datacenter and rack.
138
99.0k
    CloudInfoPB cloud_info = entry.ts_info.registration().common().cloud_info();
139
99.0k
    RETURN_NOT_OK(SetColumnValue(kDataCenter, cloud_info.placement_region(), &row));
140
99.0k
    RETURN_NOT_OK(SetColumnValue(kRack, cloud_info.placement_zone(), &row));
141
142
    // HostId.
143
99.0k
    Uuid host_id;
144
99.0k
    RETURN_NOT_OK(host_id.FromHexString(entry.ts_info.tserver_instance().permanent_uuid()));
145
99.0k
    RETURN_NOT_OK(SetColumnValue(kHostId, host_id, &row));
146
99.0k
    RETURN_NOT_OK(SetColumnValue(yb::master::kSystemTablesReleaseVersionColumn,
147
99.0k
        yb::master::kSystemTablesReleaseVersion, &row));
148
149
    // schema_version.
150
99.0k
    Uuid schema_version = VERIFY_RESULT(Uuid::FromString(master::kDefaultSchemaVersion));
151
99.0k
    RETURN_NOT_OK(SetColumnValue(kSchemaVersion, schema_version, &row));
152
153
    // Tokens.
154
99.0k
    RETURN_NOT_OK(SetColumnValue(
155
99.0k
        kTokens, util::GetTokensValue(entry.index, descs.size()), &row));
156
99.0k
  }
157
158
47.4k
  return vtable;
159
47.4k
}
160
161
3.00k
Schema PeersVTable::CreateSchema() const {
162
3.00k
  SchemaBuilder builder;
163
3.00k
  CHECK_OK(builder.AddHashKeyColumn(kPeer, QLType::Create(DataType::INET)));
164
3.00k
  CHECK_OK(builder.AddColumn(kDataCenter, QLType::Create(DataType::STRING)));
165
3.00k
  CHECK_OK(builder.AddColumn(kHostId, QLType::Create(DataType::UUID)));
166
3.00k
  CHECK_OK(builder.AddColumn(kPreferredIp, QLType::Create(DataType::INET)));
167
3.00k
  CHECK_OK(builder.AddColumn(kRack, QLType::Create(DataType::STRING)));
168
3.00k
  CHECK_OK(builder.AddColumn(kReleaseVersion, QLType::Create(DataType::STRING)));
169
3.00k
  CHECK_OK(builder.AddColumn(kRPCAddress, QLType::Create(DataType::INET)));
170
3.00k
  CHECK_OK(builder.AddColumn(kSchemaVersion, QLType::Create(DataType::UUID)));
171
3.00k
  CHECK_OK(builder.AddColumn(kTokens, QLType::CreateTypeSet(DataType::STRING)));
172
3.00k
  return builder.Build();
173
3.00k
}
174
175
}  // namespace master
176
}  // namespace yb