YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/fs/fs_manager.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
33
#include "yb/fs/fs_manager.h"
34
35
#include <map>
36
#include <set>
37
#include <unordered_set>
38
39
#include <boost/algorithm/string/predicate.hpp>
40
#include <boost/preprocessor/cat.hpp>
41
#include <glog/logging.h>
42
#include <glog/stl_logging.h>
43
#include <google/protobuf/message.h>
44
45
#include "yb/fs/fs.pb.h"
46
47
#include "yb/gutil/map-util.h"
48
#include "yb/gutil/strings/join.h"
49
#include "yb/gutil/strings/numbers.h"
50
#include "yb/gutil/strings/split.h"
51
#include "yb/gutil/strings/strip.h"
52
#include "yb/gutil/strings/util.h"
53
#include "yb/gutil/walltime.h"
54
55
#include "yb/util/env_util.h"
56
#include "yb/util/flag_tags.h"
57
#include "yb/util/format.h"
58
#include "yb/util/metric_entity.h"
59
#include "yb/util/net/net_util.h"
60
#include "yb/util/oid_generator.h"
61
#include "yb/util/path_util.h"
62
#include "yb/util/pb_util.h"
63
#include "yb/util/result.h"
64
65
DEFINE_bool(enable_data_block_fsync, true,
66
            "Whether to enable fsync() of data blocks, metadata, and their parent directories. "
67
            "Disabling this flag may cause data loss in the event of a system crash.");
68
TAG_FLAG(enable_data_block_fsync, unsafe);
69
70
DECLARE_string(fs_data_dirs);
71
72
DEFINE_string(fs_wal_dirs, "",
73
              "Comma-separated list of directories for write-ahead logs. This is an optional "
74
                  "argument. If this is not specified, fs_data_dirs is used for write-ahead logs "
75
                  "also and that's a reasonable default for most use cases.");
76
TAG_FLAG(fs_wal_dirs, stable);
77
78
DEFINE_string(instance_uuid_override, "",
79
              "When creating local instance metadata (for master or tserver) in an empty data "
80
              "directory, use this UUID instead of randomly-generated one. Can be used to replace "
81
              "a node that had its disk wiped in some scenarios.");
82
83
DEFINE_test_flag(bool, simulate_fs_create_failure, false,
84
                 "Simulate failure during initial creation of fs during the first time "
85
                 "process creation.");
86
87
using google::protobuf::Message;
88
using yb::env_util::ScopedFileDeleter;
89
using std::map;
90
using std::unordered_set;
91
using strings::Substitute;
92
93
namespace yb {
94
// ==========================================================================
95
//  FS Paths
96
// ==========================================================================
97
const char *FsManager::kWalDirName = "wals";
98
const char *FsManager::kWalFileNamePrefix = "wal";
99
const char *FsManager::kWalsRecoveryDirSuffix = ".recovery";
100
const char *FsManager::kRocksDBDirName = "rocksdb";
101
const char *FsManager::kDataDirName = "data";
102
103
namespace {
104
105
static const char kRaftGroupMetadataDirName[] = "tablet-meta";
106
static const char kInstanceMetadataFileName[] = "instance";
107
static const char kFsLockFileName[] = "fs-lock";
108
static const char kConsensusMetadataDirName[] = "consensus-meta";
109
static const char kLogsDirName[] = "logs";
110
static const char kTmpInfix[] = ".tmp";
111
static const char kCheckFileTemplate[] = "check.XXXXXX";
112
static const char kMetricDescription[] = "Tablet Server isn't able to read/write on drive.";
113
114
187k
std::string DataDir(const std::string& root, const std::string& server_type) {
115
187k
  return JoinPathSegments(GetServerTypeDataPath(root, server_type), FsManager::kDataDirName);
116
187k
}
117
118
169k
std::string WalDir(const std::string& root, const std::string& server_type) {
119
169k
  return JoinPathSegments(GetServerTypeDataPath(root, server_type), FsManager::kWalDirName);
120
169k
}
121
122
} // namespace
123
124
FsManagerOpts::FsManagerOpts()
125
58.9k
    : read_only(false) {
126
58.9k
  if (FLAGS_fs_wal_dirs.empty() && 
!FLAGS_fs_data_dirs.empty()13.8k
) {
127
    // It is sufficient if user sets the data dirs. By default we use the same
128
    // directories for WALs as well.
129
8.42k
    FLAGS_fs_wal_dirs = FLAGS_fs_data_dirs;
130
8.42k
  }
131
58.9k
  wal_paths = strings::Split(FLAGS_fs_wal_dirs, ",", strings::SkipEmpty());
132
58.9k
  data_paths = strings::Split(FLAGS_fs_data_dirs, ",", strings::SkipEmpty());
133
58.9k
}
134
135
54.3k
FsManagerOpts::~FsManagerOpts() = default;
136
70.5k
FsManagerOpts::FsManagerOpts(const FsManagerOpts&) = default;
137
3
FsManagerOpts& FsManagerOpts::operator=(const FsManagerOpts&) = default;
138
139
FsManager::FsManager(Env* env, const string& root_path, const std::string& server_type)
140
    : env_(DCHECK_NOTNULL(env)),
141
      read_only_(false),
142
      wal_fs_roots_({ root_path }),
143
      data_fs_roots_({ root_path }),
144
      server_type_(server_type),
145
      metric_entity_(nullptr),
146
155
      initted_(false) {
147
155
}
148
149
FsManager::FsManager(Env* env,
150
                     const FsManagerOpts& opts)
151
    : env_(DCHECK_NOTNULL(env)),
152
      read_only_(opts.read_only),
153
      wal_fs_roots_(opts.wal_paths),
154
      data_fs_roots_(opts.data_paths),
155
      server_type_(opts.server_type),
156
      metric_entity_(opts.metric_entity),
157
      parent_mem_tracker_(opts.parent_mem_tracker),
158
26.4k
      initted_(false) {
159
26.4k
}
160
161
453
FsManager::~FsManager() {
162
453
}
163
164
61.6k
Status FsManager::Init() {
165
61.6k
  if (initted_) {
166
35.0k
    return Status::OK();
167
35.0k
  }
168
169
  // The wal root must be set.
170
26.6k
  if (data_fs_roots_.empty()) {
171
2
    return STATUS(IOError, "List of data directories (fs_data_dirs) not provided");
172
2
  }
173
174
  // Deduplicate all of the roots.
175
26.6k
  set<string> all_roots;
176
26.7k
  for (const string& wal_fs_root : wal_fs_roots_) {
177
26.7k
    all_roots.insert(wal_fs_root);
178
26.7k
  }
179
26.7k
  for (const string& data_fs_root : data_fs_roots_) {
180
26.7k
    all_roots.insert(data_fs_root);
181
26.7k
  }
182
183
  // Build a map of original root --> canonicalized root, sanitizing each
184
  // root a bit as we go.
185
26.6k
  typedef map<string, string> RootMap;
186
26.6k
  RootMap canonicalized_roots;
187
26.7k
  for (const string& root : all_roots) {
188
26.7k
    if (root.empty()) {
189
1
      return STATUS(IOError, "Empty string provided for filesystem root");
190
1
    }
191
26.7k
    if (root[0] != '/') {
192
1
      return STATUS(IOError,
193
1
          Substitute("Relative path $0 provided for filesystem root", root));
194
1
    }
195
26.7k
    {
196
26.7k
      string root_copy = root;
197
26.7k
      StripWhiteSpace(&root_copy);
198
26.7k
      if (root != root_copy) {
199
1
        return STATUS(IOError,
200
1
                  Substitute("Filesystem root $0 contains illegal whitespace", root));
201
1
      }
202
26.7k
    }
203
204
    // Strip the basename when canonicalizing, as it may not exist. The
205
    // dirname, however, must exist.
206
26.7k
    string canonicalized;
207
26.7k
    Status s = env_->Canonicalize(DirName(root), &canonicalized);
208
26.7k
    if (!s.ok()) {
209
0
      return STATUS(
210
0
          InvalidArgument, strings::Substitute(
211
0
          "Cannot create directory for YB data, please check the --fs_data_dirs parameter "
212
0
          "(Passed: $0). Path does not exist: $1\nDetails: $2",
213
0
          FLAGS_fs_data_dirs, root, s.ToString()));
214
0
    }
215
26.7k
    canonicalized = JoinPathSegments(canonicalized, BaseName(root));
216
26.7k
    InsertOrDie(&canonicalized_roots, root, canonicalized);
217
26.7k
  }
218
219
  // All done, use the map to set the canonicalized state.
220
26.7k
  
for (const auto& wal_fs_root : wal_fs_roots_)26.5k
{
221
26.7k
    canonicalized_wal_fs_roots_.insert(FindOrDie(canonicalized_roots, wal_fs_root));
222
26.7k
  }
223
26.5k
  if (!data_fs_roots_.empty()) {
224
26.5k
    canonicalized_metadata_fs_root_ = FindOrDie(canonicalized_roots, data_fs_roots_[0]);
225
26.7k
    for (const string& data_fs_root : data_fs_roots_) {
226
26.7k
      canonicalized_data_fs_roots_.insert(FindOrDie(canonicalized_roots, data_fs_root));
227
26.7k
    }
228
26.5k
  } else {
229
1
    LOG(FATAL) << "Data directories (fs_data_dirs) must be specified";
230
1
  }
231
232
26.7k
  for (const RootMap::value_type& e : canonicalized_roots) {
233
26.7k
    canonicalized_all_fs_roots_.insert(e.second);
234
26.7k
  }
235
236
26.5k
  if (VLOG_IS_ON(1)) {
237
0
    VLOG(1) << "WAL roots: " << canonicalized_wal_fs_roots_;
238
0
    VLOG(1) << "Metadata root: " << canonicalized_metadata_fs_root_;
239
0
    VLOG(1) << "Data roots: " << canonicalized_data_fs_roots_;
240
0
    VLOG(1) << "All roots: " << canonicalized_all_fs_roots_;
241
0
  }
242
243
26.5k
  initted_ = true;
244
26.5k
  return Status::OK();
245
26.6k
}
246
247
43.8k
Status FsManager::CheckAndOpenFileSystemRoots() {
248
43.8k
  RETURN_NOT_OK(Init());
249
250
43.8k
  if (HasAnyLockFiles()) {
251
0
    return STATUS(Corruption, "Lock file is present, filesystem may be in inconsistent state");
252
0
  }
253
254
43.8k
  bool create_roots = false;
255
44.0k
  for (const string& root : canonicalized_all_fs_roots_) {
256
44.0k
    auto pb = std::make_unique<InstanceMetadataPB>();
257
44.0k
    auto read_result = pb_util::ReadPBContainerFromPath(env_, GetInstanceMetadataPath(root),
258
44.0k
                                                        pb.get());
259
44.0k
    auto write_result = CheckWrite(root);
260
44.0k
    if ((!read_result.ok() && 
!read_result.IsNotFound()17.3k
) ||
!write_result.ok()44.0k
) {
261
2
      LOG(WARNING) << "Path: " << root << " Read Result: "<< read_result
262
2
                   << " Write Result: " << write_result;
263
2
      canonicalized_wal_fs_roots_.erase(root);
264
2
      canonicalized_data_fs_roots_.erase(root);
265
2
      CreateAndSetFaultDriveMetric(root);
266
2
      continue;
267
2
    }
268
44.0k
    if (read_result.IsNotFound()) {
269
17.3k
      create_roots = true;
270
17.3k
      continue;
271
17.3k
    }
272
26.7k
    if (!metadata_) {
273
26.5k
      metadata_.reset(pb.release());
274
26.5k
    } else 
if (177
pb->uuid() != metadata_->uuid()177
) {
275
0
      return STATUS(Corruption, Substitute(
276
0
          "Mismatched UUIDs across filesystem roots: $0 vs. $1",
277
0
          metadata_->uuid(), pb->uuid()));
278
0
    }
279
26.7k
  }
280
43.8k
  if (!metadata_) {
281
17.2k
    return STATUS(NotFound, "Metadata wasn't found");
282
17.2k
  }
283
26.5k
  if (create_roots) {
284
1
    RETURN_NOT_OK(CreateFileSystemRoots(/* create_metadata_dir = */ false,
285
1
                                        *metadata_.get()));
286
1
  }
287
288
26.5k
  LOG(INFO) << "Opened local filesystem: " << JoinStrings(canonicalized_all_fs_roots_, ",")
289
26.5k
            << std::endl << metadata_->DebugString();
290
26.5k
  return Status::OK();
291
26.5k
}
292
293
61.0k
bool FsManager::HasAnyLockFiles() {
294
61.3k
  for (const string& root : canonicalized_all_fs_roots_) {
295
61.3k
    if (Exists(GetFsLockFilePath(root))) {
296
0
      LOG(INFO) << "Found lock file in dir " << root;
297
0
      return true;
298
0
    }
299
61.3k
  }
300
301
61.0k
  return false;
302
61.0k
}
303
304
18.2k
Status FsManager::DeleteLockFiles() {
305
18.2k
  CHECK(!read_only_);
306
18.2k
  vector<string> removal_list;
307
18.3k
  for (const string& root : canonicalized_all_fs_roots_) {
308
18.3k
    std::string lock_file_path = GetFsLockFilePath(root);
309
18.3k
    if (Exists(lock_file_path)) {
310
0
      removal_list.push_back(lock_file_path);
311
0
    }
312
18.3k
  }
313
314
18.2k
  for (const string& target : removal_list) {
315
0
    RETURN_NOT_OK_PREPEND(env_->DeleteFile(target), "Lock file delete failed");
316
0
  }
317
318
18.2k
  return Status::OK();
319
18.2k
}
320
321
438
Status FsManager::DeleteFileSystemLayout(ShouldDeleteLogs also_delete_logs) {
322
438
  CHECK(!read_only_);
323
438
  set<string> removal_set;
324
438
  if (also_delete_logs) {
325
401
    removal_set = canonicalized_all_fs_roots_;
326
401
  } else {
327
37
    auto removal_list = GetWalRootDirs();
328
37
    removal_list.push_back(GetRaftGroupMetadataDir());
329
37
    removal_list.push_back(GetConsensusMetadataDir());
330
37
    for (const string& root : canonicalized_all_fs_roots_) {
331
37
      removal_list.push_back(GetInstanceMetadataPath(root));
332
37
    }
333
37
    auto data_dirs = GetDataRootDirs();
334
37
    removal_list.insert(removal_list.begin(), data_dirs.begin(), data_dirs.end());
335
37
    removal_set.insert(removal_list.begin(), removal_list.end());
336
37
  }
337
338
585
  for (const string& target : removal_set) {
339
585
    bool is_dir = false;
340
585
    Status s = env_->IsDirectory(target, &is_dir);
341
585
    if (!s.ok()) {
342
0
      LOG(WARNING) << "Error: " << s.ToString() << " when checking if " << target
343
0
                   << " is a directory.";
344
0
      continue;
345
0
    }
346
585
    if (is_dir) {
347
548
      RETURN_NOT_OK(env_->DeleteRecursively(target));
348
548
    } else {
349
37
      RETURN_NOT_OK(env_->DeleteFile(target));
350
37
    }
351
585
  }
352
353
438
  RETURN_NOT_OK(DeleteLockFiles());
354
355
438
  return Status::OK();
356
438
}
357
358
17.8k
Status FsManager::CreateInitialFileSystemLayout(bool delete_fs_if_lock_found) {
359
17.8k
  CHECK(!read_only_);
360
361
17.8k
  RETURN_NOT_OK(Init());
362
363
17.8k
  bool fs_cleaned = false;
364
365
  // If lock file is present, delete existing filesystem layout before continuing.
366
17.8k
  if (delete_fs_if_lock_found && 
HasAnyLockFiles()17.2k
) {
367
0
    RETURN_NOT_OK(DeleteFileSystemLayout());
368
0
    fs_cleaned = true;
369
0
  }
370
371
  // It's OK if a root already exists as long as there's nothing in it.
372
17.9k
  
for (const string& root : canonicalized_all_fs_roots_)17.8k
{
373
17.9k
    if (!env_->FileExists(GetServerTypeDataPath(root, server_type_))) {
374
      // We'll create the directory below.
375
15.9k
      continue;
376
15.9k
    }
377
1.94k
    bool is_empty;
378
1.94k
    RETURN_NOT_OK_PREPEND(IsDirectoryEmpty(GetServerTypeDataPath(root, server_type_), &is_empty),
379
1.94k
                          "Unable to check if FSManager root is empty");
380
1.94k
    if (!is_empty) {
381
1
      return STATUS(AlreadyPresent, "FSManager root is not empty", root);
382
1
    }
383
1.94k
  }
384
385
  // All roots are either empty or non-existent. Create missing roots and all
386
  // subdirectories.
387
  //
388
389
17.8k
  InstanceMetadataPB metadata;
390
17.8k
  CreateInstanceMetadata(&metadata);
391
17.8k
  RETURN_NOT_OK(CreateFileSystemRoots(/* create_metadata_dir = */ true,
392
17.8k
                                      metadata,
393
17.8k
                                      /* create_lock = */ fs_cleaned));
394
395
17.8k
  if (FLAGS_TEST_simulate_fs_create_failure) {
396
1
    return STATUS(IOError, "Simulated fs creation error");
397
1
  }
398
17.8k
  RETURN_NOT_OK(DeleteLockFiles());
399
17.8k
  return Status::OK();
400
17.8k
}
401
402
Status FsManager::CreateFileSystemRoots(bool create_metadata_dir,
403
                                        const InstanceMetadataPB& metadata,
404
17.8k
                                        bool create_lock) {
405
  // In the event of failure, delete everything we created.
406
17.8k
  std::deque<ScopedFileDeleter> delete_on_failure;
407
17.8k
  unordered_set<string> to_sync;
408
409
17.8k
  std::set<std::string> roots = canonicalized_data_fs_roots_;
410
17.8k
  roots.insert(canonicalized_wal_fs_roots_.begin(), canonicalized_wal_fs_roots_.end());
411
412
  // All roots are either empty or non-existent. Create missing roots and all
413
  // subdirectories.
414
17.9k
  for (const auto& root : roots) {
415
17.9k
    bool created;
416
17.9k
    std::string out_dir;
417
17.9k
    RETURN_NOT_OK(SetupRootDir(env_, root, server_type_, &out_dir, &created));
418
17.9k
    if (created) {
419
15.9k
      delete_on_failure.emplace_front(env_, out_dir);
420
15.9k
      to_sync.insert(DirName(out_dir));
421
15.9k
    }
422
423
17.9k
    const string lock_file_path = GetFsLockFilePath(root);
424
17.9k
    if (create_lock && 
!Exists(lock_file_path)0
) {
425
0
      std::unique_ptr<WritableFile> file;
426
0
      RETURN_NOT_OK_PREPEND(env_->NewWritableFile(lock_file_path, &file),
427
0
                            "Unable to create lock file.");
428
      // Do not delete lock file on error. It is used to detect failed initial create.
429
0
    }
430
17.9k
    const string instance_metadata_path = GetInstanceMetadataPath(root);
431
17.9k
    if (env_->FileExists(instance_metadata_path)) {
432
2
      continue;
433
2
    }
434
17.9k
    RETURN_NOT_OK_PREPEND(WriteInstanceMetadata(metadata, instance_metadata_path),
435
17.9k
                            "Unable to write instance metadata");
436
17.9k
    delete_on_failure.emplace_front(env_, instance_metadata_path);
437
17.9k
  }
438
439
89.3k
  
for (const auto& dir : GetAncillaryDirs(create_metadata_dir))17.8k
{
440
89.3k
    bool created;
441
89.3k
    RETURN_NOT_OK_PREPEND(CreateDirIfMissing(dir, &created),
442
89.3k
                          Substitute("Unable to create directory $0", dir));
443
89.3k
    if (created) {
444
89.3k
      delete_on_failure.emplace_front(env_, dir);
445
89.3k
      to_sync.insert(DirName(dir));
446
89.3k
    }
447
89.3k
  }
448
449
  // Ensure newly created directories are synchronized to disk.
450
17.8k
  if (FLAGS_enable_data_block_fsync) {
451
50.6k
    for (const string& dir : to_sync) {
452
50.6k
      RETURN_NOT_OK_PREPEND(env_->SyncDir(dir),
453
50.6k
                            Substitute("Unable to synchronize directory $0", dir));
454
50.6k
    }
455
17.4k
  }
456
457
  // Success: don't delete any files.
458
123k
  
for (auto& deleter : delete_on_failure)17.8k
{
459
123k
    deleter.Cancel();
460
123k
  }
461
462
17.8k
  return Status::OK();
463
17.8k
}
464
465
17.8k
std::set<std::string> FsManager::GetAncillaryDirs(bool add_metadata_dirs) const {
466
17.8k
  std::set<std::string> ancillary_dirs;
467
17.8k
  if (add_metadata_dirs) {
468
17.8k
    ancillary_dirs.emplace(GetRaftGroupMetadataDir());
469
17.8k
    ancillary_dirs.emplace(GetConsensusMetadataDir());
470
17.8k
  }
471
17.8k
  for (const auto& wal_fs_root : canonicalized_wal_fs_roots_) {
472
17.8k
    ancillary_dirs.emplace(WalDir(wal_fs_root, server_type_));
473
17.8k
  }
474
17.9k
  for (const string& data_fs_root : canonicalized_data_fs_roots_) {
475
17.9k
    const string data_dir = DataDir(data_fs_root, server_type_);
476
17.9k
    ancillary_dirs.emplace(data_dir);
477
17.9k
    ancillary_dirs.emplace(JoinPathSegments(data_dir, kRocksDBDirName));
478
17.9k
  }
479
17.8k
  return ancillary_dirs;
480
17.8k
}
481
482
17.8k
void FsManager::CreateInstanceMetadata(InstanceMetadataPB* metadata) {
483
17.8k
  if (!FLAGS_instance_uuid_override.empty()) {
484
0
    metadata->set_uuid(FLAGS_instance_uuid_override);
485
17.8k
  } else {
486
17.8k
    metadata->set_uuid(GenerateObjectId());
487
17.8k
  }
488
489
17.8k
  string time_str;
490
17.8k
  StringAppendStrftime(&time_str, "%Y-%m-%d %H:%M:%S", time(nullptr), false);
491
17.8k
  string hostname;
492
17.8k
  if (!GetHostname(&hostname).ok()) {
493
0
    hostname = "<unknown host>";
494
0
  }
495
17.8k
  metadata->set_format_stamp(Substitute("Formatted at $0 on $1", time_str, hostname));
496
17.8k
}
497
498
Status FsManager::WriteInstanceMetadata(const InstanceMetadataPB& metadata,
499
17.9k
                                        const string& path) {
500
  // The instance metadata is written effectively once per TS, so the
501
  // durability cost is negligible.
502
17.9k
  RETURN_NOT_OK(pb_util::WritePBContainerToPath(env_, path,
503
17.9k
                                                metadata,
504
17.9k
                                                pb_util::NO_OVERWRITE,
505
17.9k
                                                pb_util::SYNC));
506
17.9k
  LOG(INFO) << "Generated new instance metadata in path " << path << ":\n"
507
17.9k
            << metadata.DebugString();
508
17.9k
  return Status::OK();
509
17.9k
}
510
511
1.94k
Status FsManager::IsDirectoryEmpty(const string& path, bool* is_empty) {
512
1.94k
  vector<string> children;
513
1.94k
  RETURN_NOT_OK(env_->GetChildren(path, &children));
514
5.82k
  
for (const string& child : children)1.94k
{
515
    // Excluding logs directory from the list of things to check for.
516
5.82k
    if (child == "." || 
child == ".."3.88k
||
child == kLogsDirName1.94k
) {
517
5.81k
      continue;
518
5.81k
    } else {
519
1
      LOG(INFO) << "Found data " << child;
520
1
      *is_empty = false;
521
1
      return Status::OK();
522
1
    }
523
5.82k
  }
524
1.93k
  *is_empty = true;
525
1.93k
  return Status::OK();
526
1.94k
}
527
528
44.0k
Status FsManager::CheckWrite(const std::string& root) {
529
44.0k
  RETURN_NOT_OK(env_->CreateDirs(root));
530
44.0k
  const string tmp_file_temp = JoinPathSegments(root, kCheckFileTemplate);
531
44.0k
  string tmp_file;
532
44.0k
  std::unique_ptr<WritableFile> file;
533
44.0k
  Status write_result = env_->NewTempWritableFile(WritableFileOptions(),
534
44.0k
                                                  tmp_file_temp,
535
44.0k
                                                  &tmp_file,
536
44.0k
                                                  &file);
537
44.0k
  if (!write_result.ok()) {
538
2
    return write_result;
539
2
  }
540
44.0k
  ScopedFileDeleter deleter(env_, tmp_file);
541
44.0k
  write_result = file->Append(Slice("0123456789"));
542
44.0k
  if (!write_result.ok()) {
543
0
    return write_result;
544
0
  }
545
44.0k
  write_result = file->Close();
546
44.0k
  if (!write_result.ok()) {
547
0
    return write_result;
548
0
  }
549
44.0k
  return Status::OK();
550
44.0k
}
551
552
2
void FsManager::CreateAndSetFaultDriveMetric(const std::string& path) {
553
2
  std::unique_ptr<CounterPrototype> counter = std::make_unique<OwningCounterPrototype>(
554
2
      "server", Format("drive_fault_$0", counters_.size()), path, yb::MetricUnit::kThreads,
555
2
      kMetricDescription, yb::MetricLevel::kWarn, yb::EXPOSE_AS_COUNTER);
556
2
  auto pointer = metric_entity_->FindOrCreateCounter(std::move(counter));
557
2
  counters_[path] = pointer;
558
2
  pointer->Increment();
559
2
}
560
561
2.30M
Status FsManager::CreateDirIfMissing(const string& path, bool* created) {
562
2.30M
  return env_util::CreateDirIfMissing(env_, path, created);
563
2.30M
}
564
565
1.10M
Status FsManager::CreateDirIfMissingAndSync(const std::string& path, bool* created) {
566
1.10M
  RETURN_NOT_OK_PREPEND(CreateDirIfMissing(path, created),
567
1.10M
                        Substitute("Failed to create directory $0", path));
568
1.10M
  RETURN_NOT_OK_PREPEND(env_->SyncDir(DirName(path)),
569
1.10M
                        Substitute("Failed to sync root directory $0", DirName(path)));
570
1.10M
  return Status::OK();
571
1.10M
}
572
573
240M
const string& FsManager::uuid() const {
574
240M
  return CHECK_NOTNULL(metadata_.get())->uuid();
575
240M
}
576
577
1.07M
set<string> FsManager::GetFsRootDirs() const {
578
1.07M
  return canonicalized_all_fs_roots_;
579
1.07M
}
580
581
168k
vector<string> FsManager::GetDataRootDirs() const {
582
  // Add the data subdirectory to each data root.
583
168k
  vector<string> data_paths;
584
169k
  for (const string& data_fs_root : canonicalized_data_fs_roots_) {
585
169k
    data_paths.push_back(DataDir(data_fs_root, server_type_));
586
169k
  }
587
168k
  return data_paths;
588
168k
}
589
590
150k
vector<string> FsManager::GetWalRootDirs() const {
591
150k
  DCHECK(initted_);
592
150k
  vector<string> wal_dirs;
593
151k
  for (const auto& canonicalized_wal_fs_root : canonicalized_wal_fs_roots_) {
594
151k
    wal_dirs.push_back(WalDir(canonicalized_wal_fs_root, server_type_));
595
151k
  }
596
150k
  return wal_dirs;
597
150k
}
598
599
1.77M
std::string FsManager::GetRaftGroupMetadataDir(const std::string& data_dir) {
600
1.77M
  return JoinPathSegments(data_dir, kRaftGroupMetadataDirName);
601
1.77M
}
602
603
1.77M
string FsManager::GetRaftGroupMetadataDir() const {
604
1.77M
  DCHECK(initted_);
605
1.77M
  return GetRaftGroupMetadataDir(
606
1.77M
      GetServerTypeDataPath(canonicalized_metadata_fs_root_, server_type_));
607
1.77M
}
608
609
1.72M
string FsManager::GetRaftGroupMetadataPath(const string& tablet_id) const {
610
1.72M
  return JoinPathSegments(GetRaftGroupMetadataDir(), tablet_id);
611
1.72M
}
612
613
namespace {
614
// Return true if 'fname' is a valid tablet ID.
615
17.7k
bool IsValidTabletId(const std::string& fname) {
616
17.7k
  if (fname.find(kTmpInfix) != string::npos) {
617
2
    LOG(WARNING) << "Ignoring tmp file in tablet metadata dir: " << fname;
618
2
    return false;
619
2
  }
620
621
17.7k
  if (HasPrefixString(fname, ".")) {
622
    // Hidden file or ./..
623
17.5k
    VLOG
(1) << "Ignoring hidden file in tablet metadata dir: " << fname0
;
624
17.5k
    return false;
625
17.5k
  }
626
627
218
  return true;
628
17.7k
}
629
} // anonymous namespace
630
631
8.75k
Status FsManager::ListTabletIds(vector<string>* tablet_ids) {
632
8.75k
  string dir = GetRaftGroupMetadataDir();
633
8.75k
  vector<string> children;
634
8.75k
  RETURN_NOT_OK_PREPEND(ListDir(dir, &children),
635
8.75k
                        Substitute("Couldn't list tablets in metadata directory $0", dir));
636
637
8.75k
  vector<string> tablets;
638
17.7k
  for (const string& child : children) {
639
17.7k
    if (!IsValidTabletId(child)) {
640
17.5k
      continue;
641
17.5k
    }
642
218
    tablet_ids->push_back(child);
643
218
  }
644
8.75k
  return Status::OK();
645
8.75k
}
646
647
62.0k
std::string FsManager::GetInstanceMetadataPath(const string& root) const {
648
62.0k
  return JoinPathSegments(GetServerTypeDataPath(root, server_type_), kInstanceMetadataFileName);
649
62.0k
}
650
651
97.6k
std::string FsManager::GetFsLockFilePath(const string& root) const {
652
97.6k
  return JoinPathSegments(GetServerTypeDataPath(root, server_type_), kFsLockFileName);
653
97.6k
}
654
655
2.84M
std::string FsManager::GetConsensusMetadataDir() const {
656
2.84M
  DCHECK(initted_);
657
2.84M
  return GetConsensusMetadataDir(
658
2.84M
      GetServerTypeDataPath(canonicalized_metadata_fs_root_, server_type_));
659
2.84M
}
660
661
2.84M
std::string FsManager::GetConsensusMetadataDir(const std::string& data_dir) {
662
2.84M
  return JoinPathSegments(data_dir, kConsensusMetadataDirName);
663
2.84M
}
664
665
std::string FsManager::GetFirstTabletWalDirOrDie(const std::string& table_id,
666
107
                                                 const std::string& tablet_id) const {
667
107
  auto wal_root_dirs = GetWalRootDirs();
668
107
  CHECK
(!wal_root_dirs.empty()) << "No WAL directories specified"0
;
669
107
  auto table_wal_dir = JoinPathSegments(wal_root_dirs[0], Substitute("table-$0", table_id));
670
107
  return JoinPathSegments(table_wal_dir, Substitute("tablet-$0", tablet_id));
671
107
}
672
673
153k
std::string FsManager::GetTabletWalRecoveryDir(const string& tablet_wal_path) {
674
153k
  return tablet_wal_path + kWalsRecoveryDirSuffix;
675
153k
}
676
677
namespace {
678
679
const auto kWalFileNameFullPrefix = std::string(FsManager::kWalFileNamePrefix) + "-";
680
681
} // namespace
682
683
165k
std::string FsManager::GetWalSegmentFileName(uint64_t sequence_number) {
684
165k
  return Format("$0$1", kWalFileNameFullPrefix, StringPrintf("%09" PRIu64, sequence_number));
685
165k
}
686
687
966
bool FsManager::IsWalSegmentFileName(const std::string& file_name) {
688
966
  return boost::starts_with(file_name, kWalFileNameFullPrefix);
689
966
}
690
691
// ==========================================================================
692
//  Dump/Debug utils
693
// ==========================================================================
694
695
0
void FsManager::DumpFileSystemTree(ostream& out) {
696
0
  DCHECK(initted_);
697
698
0
  for (const string& root : canonicalized_all_fs_roots_) {
699
0
    out << "File-System Root: " << root << std::endl;
700
701
0
    std::vector<string> objects;
702
0
    Status s = env_->GetChildren(root, &objects);
703
0
    if (!s.ok()) {
704
0
      LOG(ERROR) << "Unable to list the fs-tree: " << s.ToString();
705
0
      return;
706
0
    }
707
708
0
    DumpFileSystemTree(out, "|-", root, objects);
709
0
  }
710
0
}
711
712
void FsManager::DumpFileSystemTree(ostream& out, const string& prefix,
713
0
                                   const string& path, const vector<string>& objects) {
714
0
  for (const string& name : objects) {
715
0
    if (name == "." || name == "..") continue;
716
717
0
    std::vector<string> sub_objects;
718
0
    string sub_path = JoinPathSegments(path, name);
719
0
    Status s = env_->GetChildren(sub_path, &sub_objects);
720
0
    if (s.ok()) {
721
0
      out << prefix << name << "/" << std::endl;
722
0
      DumpFileSystemTree(out, prefix + "---", sub_path, sub_objects);
723
0
    } else {
724
0
      out << prefix << name << std::endl;
725
0
    }
726
0
  }
727
0
}
728
729
1.67k
Result<std::vector<std::string>> FsManager::ListDir(const std::string& path) const {
730
1.67k
  std::vector<std::string> result;
731
1.67k
  RETURN_NOT_OK(env_->GetChildren(path, ExcludeDots::kTrue, &result));
732
1.67k
  return result;
733
1.67k
}
734
735
8.75k
Status FsManager::ListDir(const std::string& path, std::vector<std::string> *objects) const {
736
8.75k
  return env_->GetChildren(path, objects);
737
8.75k
}
738
739
} // namespace yb