YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/master/sys_catalog_initialization.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/sys_catalog_initialization.h"
15
16
#include "yb/common/wire_protocol.h"
17
18
#include "yb/master/catalog_entity_info.h"
19
#include "yb/master/sys_catalog.h"
20
21
#include "yb/tablet/operations/change_metadata_operation.h"
22
#include "yb/tablet/operations/snapshot_operation.h"
23
#include "yb/tablet/tablet.h"
24
#include "yb/tablet/tablet_metadata.h"
25
#include "yb/tablet/tablet_peer.h"
26
#include "yb/tablet/tablet_snapshots.h"
27
28
#include "yb/util/countdown_latch.h"
29
#include "yb/util/env_util.h"
30
#include "yb/util/flag_tags.h"
31
32
DEFINE_string(initial_sys_catalog_snapshot_path, "",
33
    "If this is specified, system catalog RocksDB is checkpointed at this location after initdb "
34
    "is done.");
35
36
DEFINE_bool(use_initial_sys_catalog_snapshot, false,
37
    "DEPRECATED: use --enable_ysql instead. "
38
    "Initialize sys catalog tablet from a pre-existing snapshot instead of running initdb. "
39
    "Only takes effect if --initial_sys_catalog_snapshot_path is specified or can be "
40
    "auto-detected.");
41
42
DEFINE_bool(enable_ysql, true,
43
    "Enable YSQL on cluster. This will initialize sys catalog tablet from a pre-existing snapshot "
44
    "and start YSQL proxy. "
45
    "Only takes effect if --initial_sys_catalog_snapshot_path is specified or can be auto-detected."
46
    );
47
48
DEFINE_bool(create_initial_sys_catalog_snapshot, false,
49
    "Run initdb and create an initial sys catalog data snapshot");
50
51
DEFINE_bool(
52
    // TODO: switch the default to true after updating all external callers (yb-ctl, YugaWare)
53
    // and unit tests.
54
    master_auto_run_initdb, false,
55
    "Automatically run initdb on master leader initialization");
56
57
TAG_FLAG(create_initial_sys_catalog_snapshot, advanced);
58
TAG_FLAG(create_initial_sys_catalog_snapshot, hidden);
59
60
using yb::CountDownLatch;
61
using yb::tserver::TabletSnapshotOpRequestPB;
62
using yb::tserver::TabletSnapshotOpResponsePB;
63
using yb::tablet::SnapshotOperation;
64
using yb::pb_util::ReadPBContainerFromPath;
65
66
namespace yb {
67
namespace master {
68
69
namespace {
70
71
const char* kDefaultInitialSysCatalogSnapshotDir = "initial_sys_catalog_snapshot";
72
const char* kSysCatalogSnapshotRocksDbSubDir = "rocksdb";
73
const char* kSysCatalogSnapshotTabletMetadataChangesFile =
74
    "exported_tablet_metadata_changes";
75
const char* kUseInitialSysCatalogSnapshotEnvVar = "YB_USE_INITIAL_SYS_CATALOG_SNAPSHOT";
76
}  // anonymous namespace
77
78
// ------------------------------------------------------------------------------------------------
79
// InitialSysCatalogSnapshotWriter
80
// ------------------------------------------------------------------------------------------------
81
82
2
InitialSysCatalogSnapshotWriter::InitialSysCatalogSnapshotWriter() = default;
83
0
InitialSysCatalogSnapshotWriter::~InitialSysCatalogSnapshotWriter() = default;
84
85
void InitialSysCatalogSnapshotWriter::AddMetadataChange(
86
1.12k
    tablet::ChangeMetadataRequestPB metadata_change) {
87
1.12k
  initdb_metadata_changes_.push_back(std::move(metadata_change));
88
1.12k
}
89
90
Status InitialSysCatalogSnapshotWriter::WriteSnapshot(
91
    tablet::Tablet* sys_catalog_tablet,
92
2
    const std::string& dest_path) {
93
2
  RETURN_NOT_OK(sys_catalog_tablet->Flush(yb::tablet::FlushMode::kSync));
94
2
  RETURN_NOT_OK(Env::Default()->CreateDir(dest_path));
95
2
  RETURN_NOT_OK(sys_catalog_tablet->snapshots().CreateCheckpoint(
96
2
      JoinPathSegments(dest_path, kSysCatalogSnapshotRocksDbSubDir)));
97
98
2
  tserver::ExportedTabletMetadataChanges exported_tablet_metadata_changes;
99
1.12k
  for (size_t i = 0; i < initdb_metadata_changes_.size(); 
++i1.12k
) {
100
1.12k
    *exported_tablet_metadata_changes.add_metadata_changes() = std::move(
101
1.12k
        initdb_metadata_changes_[i]);
102
1.12k
  }
103
104
2
  const string metadata_changes_file = JoinPathSegments(
105
2
      dest_path,
106
2
      kSysCatalogSnapshotTabletMetadataChangesFile);
107
2
  RETURN_NOT_OK(WritePBContainerToPath(
108
2
      Env::Default(),
109
2
      metadata_changes_file,
110
2
      exported_tablet_metadata_changes,
111
2
      pb_util::CreateMode::NO_OVERWRITE,
112
2
      pb_util::SyncMode::NO_SYNC));
113
2
  LOG(INFO) << "Wrote " << initdb_metadata_changes_.size() << " tablet metadata changes to file "
114
2
            << metadata_changes_file;
115
116
2
  LOG(INFO) << "Created initial sys catalog snapshot at " << dest_path;
117
2
  return Status::OK();
118
2
}
119
120
// ------------------------------------------------------------------------------------------------
121
// End of InitialSysCatalogSnapshotWriter
122
// ------------------------------------------------------------------------------------------------
123
124
Status RestoreInitialSysCatalogSnapshot(
125
    const std::string& initial_snapshot_path,
126
    tablet::TabletPeer* sys_catalog_tablet_peer,
127
746
    int64_t term) {
128
746
  TabletSnapshotOpRequestPB tablet_snapshot_req;
129
746
  tablet_snapshot_req.set_operation(yb::tserver::TabletSnapshotOpRequestPB::RESTORE_ON_TABLET);
130
746
  tablet_snapshot_req.add_tablet_id(kSysCatalogTabletId);
131
746
  tablet_snapshot_req.set_snapshot_dir_override(
132
746
      JoinPathSegments(initial_snapshot_path, kSysCatalogSnapshotRocksDbSubDir));
133
134
746
  TabletSnapshotOpResponsePB tablet_snapshot_resp;
135
746
  auto operation = std::make_unique<SnapshotOperation>(
136
746
      sys_catalog_tablet_peer->tablet(), &tablet_snapshot_req);
137
138
746
  CountDownLatch latch(1);
139
746
  operation->set_completion_callback(
140
746
      tablet::MakeLatchOperationCompletionCallback(&latch, &tablet_snapshot_resp));
141
142
746
  sys_catalog_tablet_peer->Submit(std::move(operation), term);
143
144
  // Now restore tablet metadata.
145
746
  tserver::ExportedTabletMetadataChanges tablet_metadata_changes;
146
746
  RETURN_NOT_OK(ReadPBContainerFromPath(
147
746
      Env::Default(),
148
746
      JoinPathSegments(initial_snapshot_path, kSysCatalogSnapshotTabletMetadataChangesFile),
149
746
      &tablet_metadata_changes));
150
417k
  
for (const auto& change_metadata_req : tablet_metadata_changes.metadata_changes())746
{
151
417k
    RETURN_NOT_OK(tablet::SyncReplicateChangeMetadataOperation(
152
417k
        &change_metadata_req,
153
417k
        sys_catalog_tablet_peer,
154
417k
        term));
155
417k
  }
156
746
  LOG(INFO) << "Imported " << tablet_metadata_changes.metadata_changes_size()
157
746
            << " tablet metadata changes";
158
159
746
  latch.Wait();
160
746
  return Status::OK();
161
746
}
162
163
7.09k
void SetDefaultInitialSysCatalogSnapshotFlags() {
164
  // Allowing to turn off the use of initial catalog snapshot with an env variable -- useful in
165
  // tests.
166
7.09k
  const char* env_var_value = getenv(kUseInitialSysCatalogSnapshotEnvVar);
167
7.09k
  if (env_var_value && 
strcmp(env_var_value, "0") == 00
) {
168
0
    LOG(INFO) << "Disabling the use of initial sys catalog snapshot: env var "
169
0
              << kUseInitialSysCatalogSnapshotEnvVar << " is set to 0";
170
0
    FLAGS_use_initial_sys_catalog_snapshot = 0;
171
0
    FLAGS_enable_ysql = 0;
172
0
  }
173
174
7.09k
  if (FLAGS_initial_sys_catalog_snapshot_path.empty() &&
175
7.09k
      
!FLAGS_create_initial_sys_catalog_snapshot7.08k
&&
176
7.09k
      
(7.08k
FLAGS_use_initial_sys_catalog_snapshot7.08k
||
FLAGS_enable_ysql7.08k
)) {
177
1.91k
    const char* kStaticDataParentDir = "share";
178
1.91k
    const std::string search_for_dir = JoinPathSegments(
179
1.91k
        kStaticDataParentDir, kDefaultInitialSysCatalogSnapshotDir,
180
1.91k
        kSysCatalogSnapshotRocksDbSubDir);
181
1.91k
    VLOG
(1) << "Searching for directory containing subdirectory " << search_for_dir0
;
182
1.91k
    const string candidate_dir =
183
1.91k
        JoinPathSegments(
184
1.91k
            env_util::GetRootDir(search_for_dir),
185
1.91k
            kStaticDataParentDir,
186
1.91k
            kDefaultInitialSysCatalogSnapshotDir);
187
1.91k
    VLOG
(1) << "candidate_dir=" << candidate_dir0
;
188
189
    // The metadata changes file is written last, so its presence indicates that the snapshot
190
    // was successful.
191
1.91k
    const string candidate_metadata_changes_path =
192
1.91k
        JoinPathSegments(candidate_dir, kSysCatalogSnapshotTabletMetadataChangesFile);
193
1.91k
    VLOG
(1) << "candidate_metadata_changes_path=" << candidate_metadata_changes_path0
;
194
195
1.91k
    if (Env::Default()->FileExists(candidate_metadata_changes_path)) {
196
1.91k
      VLOG
(1) << "Found initial sys catalog snapshot directory: " << candidate_dir0
;
197
1.91k
      FLAGS_initial_sys_catalog_snapshot_path = candidate_dir;
198
1.91k
      return;
199
1.91k
    } else {
200
0
      VLOG(1) << "File " << candidate_metadata_changes_path << " does not exist";
201
0
    }
202
5.18k
  } else {
203
5.18k
    VLOG(1)
204
0
        << "Not attempting initial sys catalog snapshot auto-detection: "
205
0
        << "FLAGS_initial_sys_catalog_snapshot_path="
206
0
        << FLAGS_initial_sys_catalog_snapshot_path << ", "
207
0
        << "FLAGS_create_initial_sys_catalog_snapshot="
208
0
        << FLAGS_create_initial_sys_catalog_snapshot << ", "
209
0
        << "FLAGS_use_initial_sys_catalog_snapshot="
210
0
        << FLAGS_use_initial_sys_catalog_snapshot << ", "
211
0
        << "FLAGS_enable_ysql="
212
0
        << FLAGS_enable_ysql;
213
5.18k
  }
214
7.09k
}
215
216
3.00k
bool ShouldAutoRunInitDb(SysConfigInfo* ysql_catalog_config, bool pg_proc_exists) {
217
3.00k
  if (pg_proc_exists) {
218
761
    LOG(INFO) << "Table pg_proc exists, assuming initdb has already been run";
219
761
    return false;
220
761
  }
221
222
2.24k
  if (!FLAGS_master_auto_run_initdb) {
223
2.24k
    LOG(INFO) << "--master_auto_run_initdb is set to false, not running initdb";
224
2.24k
    return false;
225
2.24k
  }
226
227
2
  {
228
2
    auto l = ysql_catalog_config->LockForRead();
229
2
    if (l->pb.ysql_catalog_config().initdb_done()) {
230
0
      LOG(INFO) << "Cluster configuration indicates that initdb has already completed";
231
0
      return false;
232
0
    }
233
2
  }
234
235
2
  LOG(INFO) << "initdb has never been run on this cluster, running it";
236
2
  return true;
237
2
}
238
239
Status MakeYsqlSysCatalogTablesTransactional(
240
    TableInfoMap* table_ids_map,
241
    SysCatalogTable* sys_catalog,
242
    SysConfigInfo* ysql_catalog_config,
243
3.00k
    int64_t term) {
244
3.00k
  {
245
3.00k
    auto ysql_catalog_config_lock = ysql_catalog_config->LockForRead();
246
3.00k
    const auto& ysql_catalog_config_pb = ysql_catalog_config_lock->pb.ysql_catalog_config();
247
3.00k
    if (ysql_catalog_config_pb.transactional_sys_catalog_enabled()) {
248
101
      LOG(INFO) << "YSQL catalog tables are already transactional";
249
101
      return Status::OK();
250
101
    }
251
3.00k
  }
252
253
2.90k
  int num_updated_tables = 0;
254
465k
  for (const auto& iter : *table_ids_map) {
255
465k
    const auto& table_id = iter.first;
256
465k
    auto& table_info = *iter.second;
257
258
465k
    if (!IsPgsqlId(table_id)) {
259
49.3k
      continue;
260
49.3k
    }
261
262
416k
    {
263
416k
      TabletInfos tablet_infos = table_info.GetTablets();
264
416k
      if (tablet_infos.size() != 1 || tablet_infos.front()->tablet_id() != kSysCatalogTabletId) {
265
0
        continue;
266
0
      }
267
416k
     }
268
269
416k
    auto table_lock = table_info.LockForWrite();
270
416k
    auto& schema = *table_lock.mutable_data()->mutable_schema();
271
416k
    auto& table_properties = *schema.mutable_table_properties();
272
273
416k
    bool should_modify = false;
274
416k
    if (!table_properties.is_ysql_catalog_table()) {
275
0
      table_properties.set_is_ysql_catalog_table(true);
276
0
      should_modify = true;
277
0
    }
278
416k
    if (!table_properties.is_transactional()) {
279
0
      table_properties.set_is_transactional(true);
280
0
      should_modify = true;
281
0
    }
282
416k
    if (!should_modify) {
283
416k
      continue;
284
416k
    }
285
286
0
    num_updated_tables++;
287
0
    LOG(INFO) << "Making YSQL system catalog table transactional: " << table_info.ToString();
288
289
    // Change table properties in tablet metadata.
290
0
    tablet::ChangeMetadataRequestPB change_req;
291
0
    change_req.set_tablet_id(kSysCatalogTabletId);
292
0
    auto& add_table = *change_req.mutable_add_table();
293
0
    VERIFY_RESULT(sys_catalog->tablet_peer()->tablet_metadata()->GetTableInfo(table_id))->ToPB(
294
0
        &add_table);
295
0
    auto& metadata_table_properties = *add_table.mutable_schema()->mutable_table_properties();
296
0
    metadata_table_properties.set_is_ysql_catalog_table(true);
297
0
    metadata_table_properties.set_is_transactional(true);
298
299
0
    RETURN_NOT_OK(tablet::SyncReplicateChangeMetadataOperation(
300
0
        &change_req, sys_catalog->tablet_peer().get(), term));
301
302
    // Change table properties in the sys catalog. We do this after updating tablet metadata, so
303
    // that if a restart happens before this step succeeds, we'll retry updating both next time.
304
0
    RETURN_NOT_OK(sys_catalog->Upsert(term, &table_info));
305
0
    table_lock.Commit();
306
0
  }
307
308
2.90k
  if (num_updated_tables > 0) {
309
0
    LOG(INFO) << "Made " << num_updated_tables << " YSQL sys catalog tables transactional";
310
0
  }
311
312
2.90k
  LOG(INFO) << "Marking YSQL system catalog as transactional in YSQL catalog config";
313
2.90k
  {
314
2.90k
    auto ysql_catalog_lock = ysql_catalog_config->LockForWrite();
315
2.90k
    auto* ysql_catalog_config_pb =
316
2.90k
        ysql_catalog_lock.mutable_data()->pb.mutable_ysql_catalog_config();
317
2.90k
    ysql_catalog_config_pb->set_transactional_sys_catalog_enabled(true);
318
2.90k
    RETURN_NOT_OK(sys_catalog->Upsert(term, ysql_catalog_config));
319
2.90k
    ysql_catalog_lock.Commit();
320
2.90k
  }
321
322
0
  return Status::OK();
323
2.90k
}
324
325
}  // namespace master
326
}  // namespace yb