/Users/deen/code/yugabyte-db/src/yb/common/wire_protocol.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  |  | #include "yb/common/wire_protocol.h"  | 
33  |  |  | 
34  |  | #include <string>  | 
35  |  | #include <vector>  | 
36  |  |  | 
37  |  | #include "yb/common/common.pb.h"  | 
38  |  | #include "yb/common/ql_type.h"  | 
39  |  | #include "yb/common/schema.h"  | 
40  |  | #include "yb/common/wire_protocol.pb.h"  | 
41  |  |  | 
42  |  | #include "yb/gutil/port.h"  | 
43  |  | #include "yb/gutil/stl_util.h"  | 
44  |  | #include "yb/gutil/strings/fastmem.h"  | 
45  |  | #include "yb/gutil/strings/substitute.h"  | 
46  |  | #include "yb/util/enums.h"  | 
47  |  | #include "yb/util/errno.h"  | 
48  |  | #include "yb/util/faststring.h"  | 
49  |  | #include "yb/util/logging.h"  | 
50  |  | #include "yb/util/net/net_util.h"  | 
51  |  | #include "yb/util/net/sockaddr.h"  | 
52  |  | #include "yb/util/result.h"  | 
53  |  | #include "yb/util/slice.h"  | 
54  |  | #include "yb/util/status_format.h"  | 
55  |  | #include "yb/yql/cql/ql/util/errcodes.h"  | 
56  |  |  | 
57  |  | using google::protobuf::RepeatedPtrField;  | 
58  |  | using std::vector;  | 
59  |  |  | 
60  |  | DEFINE_string(use_private_ip, "never",  | 
61  |  |               "When to use private IP for connection. "  | 
62  |  |               "cloud - would use private IP if destination node is located in the same cloud. "  | 
63  |  |               "region - would use private IP if destination node is located in the same cloud and "  | 
64  |  |                   "region. "  | 
65  |  |               "zone - would use private IP if destination node is located in the same cloud, "  | 
66  |  |                   "region and zone."  | 
67  |  |               "never - would never use private IP if broadcast address is specified.");  | 
68  |  | namespace yb { | 
69  |  |  | 
70  |  | namespace { | 
71  |  |  | 
72  |  | YB_STRONGLY_TYPED_BOOL(PublicAddressAllowed);  | 
73  |  |  | 
74  |  | template <class Index, class Value>  | 
75  |  | void SetAt(  | 
76  | 872k  |     Index index, const Value& value, const Value& default_value, std::vector<Value>* vector) { | 
77  | 872k  |   size_t int_index = static_cast<size_t>(index);  | 
78  | 872k  |   size_t new_size = vector->size();  | 
79  | 1.04M  |   while (new_size <= int_index) { | 
80  | 168k  |     new_size = std::max<size_t>(1, new_size * 2);  | 
81  | 168k  |   }  | 
82  | 872k  |   vector->resize(new_size, default_value);  | 
83  | 872k  |   (*vector)[int_index] = value;  | 
84  | 872k  | }  | 
85  |  |  | 
86  | 28.1k  | std::vector<AppStatusPB::ErrorCode> CreateStatusToErrorCode() { | 
87  | 28.1k  |   std::vector<AppStatusPB::ErrorCode> result;  | 
88  | 28.1k  |   const auto default_value = AppStatusPB::UNKNOWN_ERROR;  | 
89  | 28.1k  |   #define YB_STATUS_CODE(name, pb_name, value, message) \  | 
90  | 872k  |     SetAt(Status::BOOST_PP_CAT(k, name), AppStatusPB::pb_name, default_value, &result); \  | 
91  | 872k  |     static_assert( \  | 
92  | 872k  |         static_cast<int32_t>(to_underlying(AppStatusPB::pb_name)) == \  | 
93  | 872k  |             to_underlying(Status::BOOST_PP_CAT(k, name)), \  | 
94  | 872k  |         "The numeric value of AppStatusPB::" BOOST_PP_STRINGIZE(pb_name) " defined in" \  | 
95  | 872k  |             " wire_protocol.proto does not match the value of Status::k" BOOST_PP_STRINGIZE(name) \  | 
96  | 872k  |             " defined in status.h.");  | 
97  | 28.1k  |   #include "yb/util/status_codes.h"  | 
98  | 28.1k  |   #undef YB_STATUS_CODE  | 
99  | 28.1k  |   return result;  | 
100  | 28.1k  | }  | 
101  |  |  | 
102  |  | const std::vector<AppStatusPB::ErrorCode> kStatusToErrorCode = CreateStatusToErrorCode();  | 
103  |  |  | 
104  | 28.1k  | std::vector<Status::Code> CreateErrorCodeToStatus() { | 
105  | 28.1k  |   size_t max_index = 0;  | 
106  | 901k  |   for (const auto error_code : kStatusToErrorCode) { | 
107  | 901k  |     if (error_code == AppStatusPB::UNKNOWN_ERROR) { | 
108  | 28.1k  |       continue;  | 
109  | 28.1k  |     }  | 
110  | 872k  |     max_index = std::max(max_index, static_cast<size_t>(error_code));  | 
111  | 872k  |   }  | 
112  |  |  | 
113  | 28.1k  |   std::vector<Status::Code> result(max_index + 1);  | 
114  | 929k  |   for (size_t int_code = 0; int_code != kStatusToErrorCode.size(); ++int_code901k ) {  | 
115  | 901k  |     if (kStatusToErrorCode[int_code] == AppStatusPB::UNKNOWN_ERROR) { | 
116  | 28.1k  |       continue;  | 
117  | 28.1k  |     }  | 
118  | 872k  |     result[static_cast<size_t>(kStatusToErrorCode[int_code])] = static_cast<Status::Code>(int_code);  | 
119  | 872k  |   }  | 
120  |  |  | 
121  | 28.1k  |   return result;  | 
122  | 28.1k  | }  | 
123  |  |  | 
124  |  | const std::vector<Status::Code> kErrorCodeToStatus = CreateErrorCodeToStatus();  | 
125  |  |  | 
126  |  | const HostPortPB& GetHostPort(  | 
127  |  |     const google::protobuf::RepeatedPtrField<HostPortPB>& broadcast_addresses,  | 
128  |  |     const google::protobuf::RepeatedPtrField<HostPortPB>& private_host_ports,  | 
129  | 2.17M  |     PublicAddressAllowed public_address_allowed) { | 
130  | 2.17M  |   if (!broadcast_addresses.empty() && public_address_allowed11.4k ) {  | 
131  | 10.9k  |     return broadcast_addresses[0];  | 
132  | 10.9k  |   }  | 
133  | 2.16M  |   if (!private_host_ports.empty()) { | 
134  | 2.16M  |     return private_host_ports[0];  | 
135  | 2.16M  |   }  | 
136  | 100  |   static const HostPortPB empty_host_port;  | 
137  | 100  |   return empty_host_port;  | 
138  | 2.16M  | }  | 
139  |  |  | 
140  |  | } // namespace  | 
141  |  |  | 
142  | 1.86M  | void StatusToPB(const Status& status, AppStatusPB* pb) { | 
143  | 1.86M  |   pb->Clear();  | 
144  |  |  | 
145  | 1.86M  |   if (status.ok()) { | 
146  | 1  |     pb->set_code(AppStatusPB::OK);  | 
147  |  |     // OK statuses don't have any message or posix code.  | 
148  | 1  |     return;  | 
149  | 1  |   }  | 
150  |  |  | 
151  | 1.86M  |   auto code = static_cast<size_t>(status.code()) < kStatusToErrorCode.size()  | 
152  | 1.86M  |       ? kStatusToErrorCode[status.code()]1.85M  : AppStatusPB::UNKNOWN_ERROR3.22k ;  | 
153  | 1.86M  |   pb->set_code(code);  | 
154  | 1.86M  |   if (code == AppStatusPB::UNKNOWN_ERROR) { | 
155  | 0  |     LOG(WARNING) << "Unknown error code translation connect_from internal error "  | 
156  | 0  |                  << status << ": sending UNKNOWN_ERROR";  | 
157  |  |     // For unknown status codes, include the original stringified error  | 
158  |  |     // code.  | 
159  | 0  |     pb->set_message(status.CodeAsString() + ": " + status.message().ToBuffer());  | 
160  | 1.86M  |   } else { | 
161  |  |     // Otherwise, just encode the message itself, since the other end  | 
162  |  |     // will reconstruct the other parts of the ToString() response.  | 
163  | 1.86M  |     pb->set_message(status.message().cdata(), status.message().size());  | 
164  | 1.86M  |   }  | 
165  |  |  | 
166  | 1.86M  |   auto error_codes = status.ErrorCodesSlice();  | 
167  | 1.86M  |   pb->set_errors(error_codes.data(), error_codes.size());  | 
168  |  |   // We always has 0 as terminating byte for error codes, so non empty error codes would have  | 
169  |  |   // more than one bytes.  | 
170  | 1.86M  |   if (error_codes.size() > 1) { | 
171  |  |     // Set old protobuf fields for backward compatibility.  | 
172  | 531k  |     Errno err(status);  | 
173  | 531k  |     if (err != 0) { | 
174  | 18  |       pb->set_posix_code(err.value());  | 
175  | 18  |     }  | 
176  | 531k  |     const auto* ql_error_data = status.ErrorData(ql::QLError::kCategory);  | 
177  | 531k  |     if (ql_error_data) { | 
178  | 0  |       pb->set_ql_error_code(static_cast<int64_t>(ql::QLErrorTag::Decode(ql_error_data)));  | 
179  | 0  |     }  | 
180  | 531k  |   }  | 
181  |  |  | 
182  | 1.86M  |   pb->set_source_file(status.file_name());  | 
183  | 1.86M  |   pb->set_source_line(status.line_number());  | 
184  | 1.86M  | }  | 
185  |  |  | 
186  |  | struct WireProtocolTabletServerErrorTag { | 
187  |  |   static constexpr uint8_t kCategory = 5;  | 
188  |  |  | 
189  |  |   enum Value {}; | 
190  |  |  | 
191  | 0  |   static size_t EncodedSize(Value value) { | 
192  | 0  |     return sizeof(Value);  | 
193  | 0  |   }  | 
194  |  |  | 
195  | 0  |   static uint8_t* Encode(Value value, uint8_t* out) { | 
196  | 0  |     Store<Value, LittleEndian>(out, value);  | 
197  | 0  |     return out + sizeof(Value);  | 
198  | 0  |   }  | 
199  |  | };  | 
200  |  |  | 
201  |  | // Backward compatibility.  | 
202  | 0  | Status StatusFromOldPB(const AppStatusPB& pb) { | 
203  | 0  |   auto code = kErrorCodeToStatus[pb.code()];  | 
204  |  | 
  | 
205  | 0  |   auto status_factory = [code, &pb](const Slice& errors) { | 
206  | 0  |     return Status(  | 
207  | 0  |         code, pb.source_file().c_str(), pb.source_line(), pb.message(), errors, DupFileName::kTrue);  | 
208  | 0  |   };  | 
209  |  | 
  | 
210  | 0  |   #define ENCODE_ERROR_AND_RETURN_STATUS(Tag, value) \  | 
211  | 0  |     auto error_code = static_cast<Tag::Value>((value)); \  | 
212  | 0  |     auto size = 2 + Tag::EncodedSize(error_code); \  | 
213  | 0  |     uint8_t* buffer = static_cast<uint8_t*>(alloca(size)); \  | 
214  | 0  |     buffer[0] = Tag::kCategory; \  | 
215  | 0  |     Tag::Encode(error_code, buffer + 1); \  | 
216  | 0  |     buffer[size - 1] = 0; \  | 
217  | 0  |     return status_factory(Slice(buffer, size)); \  | 
218  |  |     /**/  | 
219  |  | 
  | 
220  | 0  |   if (code == Status::kQLError) { | 
221  | 0  |     if (!pb.has_ql_error_code()) { | 
222  | 0  |       return STATUS(InternalError, "Query error code missing");  | 
223  | 0  |     }  | 
224  |  |  | 
225  | 0  |     ENCODE_ERROR_AND_RETURN_STATUS(ql::QLErrorTag, pb.ql_error_code())  | 
226  | 0  |   } else if (pb.has_posix_code()) { | 
227  | 0  |     if (code == Status::kIllegalState || code == Status::kLeaderNotReadyToServe ||  | 
228  | 0  |         code == Status::kLeaderHasNoLease) { | 
229  |  | 
  | 
230  | 0  |       ENCODE_ERROR_AND_RETURN_STATUS(WireProtocolTabletServerErrorTag, pb.posix_code())  | 
231  | 0  |     } else { | 
232  | 0  |       ENCODE_ERROR_AND_RETURN_STATUS(ErrnoTag, pb.posix_code())  | 
233  | 0  |     }  | 
234  | 0  |   }  | 
235  |  |  | 
236  | 0  |   return Status(code, pb.source_file().c_str(), pb.source_line(), pb.message(), "",  | 
237  | 0  |                 nullptr /* error */, DupFileName::kTrue);  | 
238  | 0  |   #undef ENCODE_ERROR_AND_RETURN_STATUS  | 
239  | 0  | }  | 
240  |  |  | 
241  | 631k  | Status StatusFromPB(const AppStatusPB& pb) { | 
242  | 631k  |   if (pb.code() == AppStatusPB::OK) { | 
243  | 1  |     return Status::OK();  | 
244  | 631k  |   } else if (pb.code() == AppStatusPB::UNKNOWN_ERROR ||  | 
245  | 631k  |              static_cast<size_t>(pb.code()) >= kErrorCodeToStatus.size()631k ) {  | 
246  | 0  |     LOG(WARNING) << "Unknown error code in status: " << pb.ShortDebugString();  | 
247  | 0  |     return STATUS_FORMAT(  | 
248  | 0  |         RuntimeError, "($0 unknown): $1", pb.code(), pb.message());  | 
249  | 0  |   }  | 
250  |  |  | 
251  | 631k  |   if (pb.has_errors()) { | 
252  | 630k  |     return Status(kErrorCodeToStatus[pb.code()], pb.source_file().c_str(), pb.source_line(),  | 
253  | 630k  |                   pb.message(), pb.errors(), DupFileName::kTrue);  | 
254  | 630k  |   }  | 
255  |  |  | 
256  | 460  |   return StatusFromOldPB(pb);  | 
257  | 631k  | }  | 
258  |  |  | 
259  | 97.2k  | void HostPortToPB(const HostPort& host_port, HostPortPB* host_port_pb) { | 
260  | 97.2k  |   host_port_pb->set_host(host_port.host());  | 
261  | 97.2k  |   host_port_pb->set_port(host_port.port());  | 
262  | 97.2k  | }  | 
263  |  |  | 
264  | 2.49M  | HostPort HostPortFromPB(const HostPortPB& host_port_pb) { | 
265  | 2.49M  |   HostPort host_port;  | 
266  | 2.49M  |   host_port.set_host(host_port_pb.host());  | 
267  | 2.49M  |   host_port.set_port(host_port_pb.port());  | 
268  | 2.49M  |   return host_port;  | 
269  | 2.49M  | }  | 
270  |  |  | 
271  |  | bool HasHostPortPB(  | 
272  | 25  |     const google::protobuf::RepeatedPtrField<HostPortPB>& list, const HostPortPB& hp) { | 
273  | 25  |   for (const auto& i : list) { | 
274  | 15  |     if (i.host() == hp.host() && i.port() == hp.port()9 ) {  | 
275  | 5  |       return true;  | 
276  | 5  |     }  | 
277  | 15  |   }  | 
278  | 20  |   return false;  | 
279  | 25  | }  | 
280  |  |  | 
281  | 0  | Status EndpointFromHostPortPB(const HostPortPB& host_portpb, Endpoint* endpoint) { | 
282  | 0  |   HostPort host_port = HostPortFromPB(host_portpb);  | 
283  | 0  |   return EndpointFromHostPort(host_port, endpoint);  | 
284  | 0  | }  | 
285  |  |  | 
286  | 161k  | void HostPortsToPBs(const std::vector<HostPort>& addrs, RepeatedPtrField<HostPortPB>* pbs) { | 
287  | 161k  |   for (const auto& addr : addrs) { | 
288  | 97.1k  |     HostPortToPB(addr, pbs->Add());  | 
289  | 97.1k  |   }  | 
290  | 161k  | }  | 
291  |  |  | 
292  | 2  | void HostPortsFromPBs(const RepeatedPtrField<HostPortPB>& pbs, std::vector<HostPort>* addrs) { | 
293  | 2  |   addrs->reserve(pbs.size());  | 
294  | 2  |   for (const auto& pb : pbs) { | 
295  | 2  |     addrs->push_back(HostPortFromPB(pb));  | 
296  | 2  |   }  | 
297  | 2  | }  | 
298  |  |  | 
299  |  | Status AddHostPortPBs(const std::vector<Endpoint>& addrs,  | 
300  | 107  |                       RepeatedPtrField<HostPortPB>* pbs) { | 
301  | 108  |   for (const auto& addr : addrs) { | 
302  | 108  |     HostPortPB* pb = pbs->Add();  | 
303  | 108  |     pb->set_port(addr.port());  | 
304  | 108  |     if (addr.address().is_unspecified()) { | 
305  | 2  |       VLOG(4) << " Asked to add unspecified address: " << addr.address()0 ;  | 
306  | 2  |       auto status = GetFQDN(pb->mutable_host());  | 
307  | 2  |       if (!status.ok()) { | 
308  | 0  |         std::vector<IpAddress> locals;  | 
309  | 0  |         if (!GetLocalAddresses(FLAGS_net_address_filter, &locals).ok() ||  | 
310  | 0  |             locals.empty()) { | 
311  | 0  |           return status;  | 
312  | 0  |         }  | 
313  | 0  |         for (auto& address : locals) { | 
314  | 0  |           if (pb == nullptr) { | 
315  | 0  |             pb = pbs->Add();  | 
316  | 0  |             pb->set_port(addr.port());  | 
317  | 0  |           }  | 
318  | 0  |           pb->set_host(address.to_string());  | 
319  | 0  |           VLOG(4) << "Adding local address: " << pb->host();  | 
320  | 0  |           pb = nullptr;  | 
321  | 0  |         }  | 
322  | 2  |       } else { | 
323  | 2  |         VLOG(4) << "Adding FQDN " << pb->host()0 ;  | 
324  | 2  |       }  | 
325  | 106  |     } else { | 
326  | 106  |       pb->set_host(addr.address().to_string());  | 
327  | 106  |       VLOG(4) << "Adding specific address: " << pb->host()0 ;  | 
328  | 106  |     }  | 
329  | 108  |   }  | 
330  | 107  |   return Status::OK();  | 
331  | 107  | }  | 
332  |  |  | 
333  |  | void SchemaToColocatedTableIdentifierPB(  | 
334  | 301M  |     const Schema& schema, ColocatedTableIdentifierPB* colocated_pb) { | 
335  | 301M  |   if (schema.has_colocation_id()) { | 
336  | 3.02k  |     colocated_pb->set_colocation_id(schema.colocation_id());  | 
337  | 301M  |   } else if (schema.has_cotable_id()) { | 
338  | 299M  |     colocated_pb->set_cotable_id(schema.cotable_id().ToString());  | 
339  | 299M  |   }  | 
340  |  |  | 
341  | 301M  | }  | 
342  |  |  | 
343  | 301M  | void SchemaToPB(const Schema& schema, SchemaPB *pb, int flags) { | 
344  | 301M  |   pb->Clear();  | 
345  | 301M  |   SchemaToColocatedTableIdentifierPB(schema, pb->mutable_colocated_table_id());  | 
346  | 301M  |   SchemaToColumnPBs(schema, pb->mutable_columns(), flags);  | 
347  | 301M  |   schema.table_properties().ToTablePropertiesPB(pb->mutable_table_properties());  | 
348  | 301M  |   pb->set_pgschema_name(schema.SchemaName());  | 
349  | 301M  | }  | 
350  |  |  | 
351  | 0  | void SchemaToPBWithoutIds(const Schema& schema, SchemaPB *pb) { | 
352  | 0  |   pb->Clear();  | 
353  | 0  |   SchemaToColumnPBs(schema, pb->mutable_columns(), SCHEMA_PB_WITHOUT_IDS);  | 
354  | 0  | }  | 
355  |  |  | 
356  | 5.68M  | Status SchemaFromPB(const SchemaPB& pb, Schema *schema) { | 
357  |  |   // Conver the columns.  | 
358  | 5.68M  |   vector<ColumnSchema> columns;  | 
359  | 5.68M  |   vector<ColumnId> column_ids;  | 
360  | 5.68M  |   int num_key_columns = 0;  | 
361  | 5.68M  |   RETURN_NOT_OK(ColumnPBsToColumnTuple(pb.columns(), &columns, &column_ids, &num_key_columns));  | 
362  |  |  | 
363  |  |   // Convert the table properties.  | 
364  | 5.68M  |   TableProperties table_properties = TableProperties::FromTablePropertiesPB(pb.table_properties());  | 
365  | 5.68M  |   RETURN_NOT_OK(schema->Reset(columns, column_ids, num_key_columns, table_properties));  | 
366  |  |  | 
367  | 5.68M  |   if(pb.has_pgschema_name()) { | 
368  | 5.67M  |     schema->SetSchemaName(pb.pgschema_name());  | 
369  | 5.67M  |   }  | 
370  |  |  | 
371  | 5.68M  |   if (pb.has_colocated_table_id()) { | 
372  | 5.67M  |     switch (pb.colocated_table_id().value_case()) { | 
373  | 1.22k  |       case ColocatedTableIdentifierPB::kCotableId: { | 
374  | 1.22k  |         schema->set_cotable_id(  | 
375  | 1.22k  |             VERIFY_RESULT(Uuid::FromString(pb.colocated_table_id().cotable_id())));  | 
376  | 0  |         break;  | 
377  | 1.22k  |       }  | 
378  | 1.46k  |       case ColocatedTableIdentifierPB::kColocationId:  | 
379  | 1.46k  |         schema->set_colocation_id(pb.colocated_table_id().colocation_id());  | 
380  | 1.46k  |         break;  | 
381  | 5.67M  |       case ColocatedTableIdentifierPB::VALUE_NOT_SET:  | 
382  | 5.67M  |         break;  | 
383  | 5.67M  |     }  | 
384  | 5.67M  |   }  | 
385  | 5.69M  |   return Status::OK();  | 
386  | 5.68M  | }  | 
387  |  |  | 
388  | 2.06G  | void ColumnSchemaToPB(const ColumnSchema& col_schema, ColumnSchemaPB *pb, int flags) { | 
389  | 2.06G  |   pb->Clear();  | 
390  | 2.06G  |   pb->set_name(col_schema.name());  | 
391  | 2.06G  |   col_schema.type()->ToQLTypePB(pb->mutable_type());  | 
392  | 2.06G  |   pb->set_is_nullable(col_schema.is_nullable());  | 
393  | 2.06G  |   pb->set_is_static(col_schema.is_static());  | 
394  | 2.06G  |   pb->set_is_counter(col_schema.is_counter());  | 
395  | 2.06G  |   pb->set_order(col_schema.order());  | 
396  | 2.06G  |   pb->set_sorting_type(col_schema.sorting_type());  | 
397  | 2.06G  |   pb->set_pg_type_oid(col_schema.pg_type_oid());  | 
398  |  |   // We only need to process the *hash* primary key here. The regular primary key is set by the  | 
399  |  |   // conversion for SchemaPB. The reason is that ColumnSchema and ColumnSchemaPB are not matching  | 
400  |  |   // 1 to 1 as ColumnSchema doesn't have "is_key" field. That was Kudu's code, and we keep it that  | 
401  |  |   // way for now.  | 
402  | 2.06G  |   if (col_schema.is_hash_key()) { | 
403  | 793k  |     pb->set_is_key(true);  | 
404  | 793k  |     pb->set_is_hash_key(true);  | 
405  | 793k  |   }  | 
406  | 2.06G  | }  | 
407  |  |  | 
408  |  |  | 
409  | 25.5M  | ColumnSchema ColumnSchemaFromPB(const ColumnSchemaPB& pb) { | 
410  |  |   // Only "is_hash_key" is used to construct ColumnSchema. The field "is_key" will be read when  | 
411  |  |   // processing SchemaPB.  | 
412  | 25.5M  |   return ColumnSchema(pb.name(), QLType::FromQLTypePB(pb.type()), pb.is_nullable(),  | 
413  | 25.5M  |                       pb.is_hash_key(), pb.is_static(), pb.is_counter(), pb.order(),  | 
414  | 25.5M  |                       SortingType(pb.sorting_type()), pb.pg_type_oid());  | 
415  | 25.5M  | }  | 
416  |  |  | 
417  |  | CHECKED_STATUS ColumnPBsToColumnTuple(  | 
418  |  |     const RepeatedPtrField<ColumnSchemaPB>& column_pbs,  | 
419  | 5.68M  |     vector<ColumnSchema>* columns , vector<ColumnId>* column_ids, int* num_key_columns) { | 
420  | 5.68M  |   columns->reserve(column_pbs.size());  | 
421  | 5.68M  |   bool is_handling_key = true;  | 
422  | 25.5M  |   for (const ColumnSchemaPB& pb : column_pbs) { | 
423  | 25.5M  |     columns->push_back(ColumnSchemaFromPB(pb));  | 
424  | 25.5M  |     if (pb.is_key()) { | 
425  | 9.04M  |       if (!is_handling_key) { | 
426  | 1  |         return STATUS(InvalidArgument,  | 
427  | 1  |                       "Got out-of-order key column", pb.ShortDebugString());  | 
428  | 1  |       }  | 
429  | 9.04M  |       (*num_key_columns)++;  | 
430  | 16.4M  |     } else { | 
431  | 16.4M  |       is_handling_key = false;  | 
432  | 16.4M  |     }  | 
433  | 25.5M  |     if (pb.has_id()) { | 
434  | 25.5M  |       column_ids->push_back(ColumnId(pb.id()));  | 
435  | 25.5M  |     }  | 
436  | 25.5M  |   }  | 
437  |  |  | 
438  | 5.68M  |   DCHECK_LE((*num_key_columns), columns->size());  | 
439  | 5.68M  |   return Status::OK();  | 
440  | 5.68M  | }  | 
441  |  |  | 
442  |  | Status ColumnPBsToSchema(const RepeatedPtrField<ColumnSchemaPB>& column_pbs,  | 
443  | 3  |                          Schema* schema) { | 
444  |  |  | 
445  | 3  |   vector<ColumnSchema> columns;  | 
446  | 3  |   vector<ColumnId> column_ids;  | 
447  | 3  |   int num_key_columns = 0;  | 
448  | 3  |   RETURN_NOT_OK(ColumnPBsToColumnTuple(column_pbs, &columns, &column_ids, &num_key_columns));  | 
449  |  |  | 
450  |  |   // TODO(perf): could make the following faster by adding a  | 
451  |  |   // Reset() variant which actually takes ownership of the column  | 
452  |  |   // vector.  | 
453  | 2  |   return schema->Reset(columns, column_ids, num_key_columns);  | 
454  | 3  | }  | 
455  |  |  | 
456  |  | void SchemaToColumnPBs(const Schema& schema,  | 
457  |  |                        RepeatedPtrField<ColumnSchemaPB>* cols,  | 
458  | 301M  |                        int flags) { | 
459  | 301M  |   cols->Clear();  | 
460  | 301M  |   size_t idx = 0;  | 
461  | 2.06G  |   for (const ColumnSchema& col : schema.columns()) { | 
462  | 2.06G  |     ColumnSchemaPB* col_pb = cols->Add();  | 
463  | 2.06G  |     ColumnSchemaToPB(col, col_pb);  | 
464  | 2.06G  |     col_pb->set_is_key(idx < schema.num_key_columns());  | 
465  |  |  | 
466  | 2.06G  |     if (schema.has_column_ids() && !(flags & SCHEMA_PB_WITHOUT_IDS)2.06G ) {  | 
467  | 2.06G  |       col_pb->set_id(schema.column_id(idx));  | 
468  | 2.06G  |     }  | 
469  |  |  | 
470  | 2.06G  |     idx++;  | 
471  | 2.06G  |   }  | 
472  | 301M  | }  | 
473  |  |  | 
474  | 2.18M  | Result<UsePrivateIpMode> GetPrivateIpMode() { | 
475  | 8.70M  |   for (auto i : kUsePrivateIpModeList) { | 
476  | 8.70M  |     if (FLAGS_use_private_ip == ToCString(i)) { | 
477  | 2.18M  |       return i;  | 
478  | 2.18M  |     }  | 
479  | 8.70M  |   }  | 
480  | 18.4E  |   return STATUS_FORMAT(  | 
481  | 2.18M  |       IllegalState,  | 
482  | 2.18M  |       "Invalid value of FLAGS_use_private_ip: $0, using private ip everywhere",  | 
483  | 2.18M  |       FLAGS_use_private_ip);  | 
484  | 2.18M  | }  | 
485  |  |  | 
486  | 2.16M  | UsePrivateIpMode GetMode() { | 
487  | 2.16M  |   auto result = GetPrivateIpMode();  | 
488  | 2.16M  |   if (result.ok()) { | 
489  | 2.16M  |     return *result;  | 
490  | 2.16M  |   }  | 
491  | 388  |   YB_LOG_EVERY_N_SECS(WARNING, 300) << result.status()0 ;  | 
492  | 388  |   return UsePrivateIpMode::never;  | 
493  | 2.16M  | }  | 
494  |  |  | 
495  | 2.16M  | PublicAddressAllowed UsePublicIp(const CloudInfoPB& connect_to, const CloudInfoPB& connect_from) { | 
496  | 2.16M  |   auto mode = GetMode();  | 
497  |  |  | 
498  | 2.16M  |   if (mode == UsePrivateIpMode::never) { | 
499  | 2.15M  |     return PublicAddressAllowed::kTrue;  | 
500  | 2.15M  |   }  | 
501  | 9.50k  |   if (connect_to.placement_cloud() != connect_from.placement_cloud()) { | 
502  | 8.16k  |     return PublicAddressAllowed::kTrue;  | 
503  | 8.16k  |   }  | 
504  | 1.34k  |   if (mode == UsePrivateIpMode::cloud) { | 
505  | 485  |     return PublicAddressAllowed::kFalse;  | 
506  | 485  |   }  | 
507  | 864  |   if (connect_to.placement_region() != connect_from.placement_region()) { | 
508  | 0  |     return PublicAddressAllowed::kTrue;  | 
509  | 0  |   }  | 
510  | 864  |   if (mode == UsePrivateIpMode::region) { | 
511  | 0  |     return PublicAddressAllowed::kFalse;  | 
512  | 0  |   }  | 
513  | 864  |   if (connect_to.placement_zone() != connect_from.placement_zone()) { | 
514  | 0  |     return PublicAddressAllowed::kTrue;  | 
515  | 0  |   }  | 
516  | 864  |   return mode == UsePrivateIpMode::zone  | 
517  | 864  |       ? PublicAddressAllowed::kFalse0   | 
518  | 864  |       : PublicAddressAllowed::kTrue;  | 
519  | 864  | }  | 
520  |  |  | 
521  | 8.74k  | const HostPortPB& PublicHostPort(const ServerRegistrationPB& registration) { | 
522  | 8.74k  |   return GetHostPort(registration.broadcast_addresses(),  | 
523  | 8.74k  |                      registration.private_rpc_addresses(),  | 
524  | 8.74k  |                      PublicAddressAllowed::kTrue);  | 
525  | 8.74k  | }  | 
526  |  |  | 
527  |  | const HostPortPB& DesiredHostPort(  | 
528  |  |     const google::protobuf::RepeatedPtrField<HostPortPB>& broadcast_addresses,  | 
529  |  |     const google::protobuf::RepeatedPtrField<HostPortPB>& private_host_ports,  | 
530  |  |     const CloudInfoPB& connect_to,  | 
531  | 2.16M  |     const CloudInfoPB& connect_from) { | 
532  | 2.16M  |   return GetHostPort(broadcast_addresses,  | 
533  | 2.16M  |                      private_host_ports,  | 
534  | 2.16M  |                      UsePublicIp(connect_to, connect_from));  | 
535  | 2.16M  | }  | 
536  |  |  | 
537  |  | const HostPortPB& DesiredHostPort(const ServerRegistrationPB& registration,  | 
538  | 171k  |                                   const CloudInfoPB& connect_from) { | 
539  | 171k  |   return DesiredHostPort(  | 
540  | 171k  |       registration.broadcast_addresses(), registration.private_rpc_addresses(),  | 
541  | 171k  |       registration.cloud_info(), connect_from);  | 
542  | 171k  | }  | 
543  |  |  | 
544  |  | static const std::string kSplitChildTabletIdsCategoryName = "split child tablet IDs";  | 
545  |  |  | 
546  |  | StatusCategoryRegisterer split_child_tablet_ids_category_registerer(  | 
547  |  |     StatusCategoryDescription::Make<SplitChildTabletIdsTag>(&kSplitChildTabletIdsCategoryName));  | 
548  |  |  | 
549  | 0  | std::string SplitChildTabletIdsTag::ToMessage(Value value) { | 
550  | 0  |   return Format("Split child tablet IDs: $0", value); | 
551  | 0  | }  | 
552  |  |  | 
553  |  | } // namespace yb  |