YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/tools/fs_tool.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/tools/fs_tool.h"
34
35
#include <algorithm>
36
#include <iostream>
37
#include <memory>
38
#include <vector>
39
40
#include <glog/logging.h>
41
42
#include "yb/common/schema.h"
43
44
#include "yb/consensus/log_anchor_registry.h"
45
#include "yb/consensus/log_util.h"
46
47
#include "yb/fs/fs_manager.h"
48
49
#include "yb/gutil/strings/human_readable.h"
50
#include "yb/gutil/strings/substitute.h"
51
#include "yb/gutil/strings/util.h"
52
53
#include "yb/master/sys_catalog_constants.h"
54
55
#include "yb/tablet/tablet.h"
56
#include "yb/tablet/tablet_metadata.h"
57
#include "yb/tablet/tablet_options.h"
58
59
#include "yb/util/env.h"
60
#include "yb/util/status.h"
61
62
namespace yb {
63
namespace tools {
64
65
using log::LogReader;
66
using log::ReadableLogSegment;
67
using std::shared_ptr;
68
using std::string;
69
using std::vector;
70
using strings::Substitute;
71
using tablet::Tablet;
72
using tablet::RaftGroupMetadata;
73
using tablet::RaftGroupMetadataPtr;
74
75
namespace {
76
0
string Indent(int indent) {
77
0
  return string(indent, ' ');
78
0
}
79
80
0
string IndentString(const string& s, int indent) {
81
0
  return Indent(indent) + StringReplace(s, "\n", "\n" + Indent(indent), true);
82
0
}
83
} // anonymous namespace
84
85
FsTool::FsTool(DetailLevel detail_level)
86
    : initialized_(false),
87
0
      detail_level_(detail_level) {
88
0
}
89
90
0
FsTool::~FsTool() {
91
0
}
92
93
0
Status FsTool::Init() {
94
0
  CHECK(!initialized_) << "Already initialized";
95
  // Allow read-only access to live blocks.
96
0
  FsManagerOpts opts;
97
0
  opts.read_only = true;
98
  // TODO(bogdan): do we use this tool? would we use it for more than tservers?
99
0
  opts.server_type = "tserver";
100
0
  fs_manager_.reset(new FsManager(Env::Default(), opts));
101
0
  RETURN_NOT_OK(fs_manager_->Open());
102
103
0
  LOG(INFO) << "Opened file system with uuid: " << fs_manager_->uuid();
104
105
0
  initialized_ = true;
106
0
  return Status::OK();
107
0
}
108
109
0
Status FsTool::FsTree() {
110
0
  DCHECK(initialized_);
111
112
0
  fs_manager_->DumpFileSystemTree(std::cout);
113
0
  return Status::OK();
114
0
}
115
116
0
Status FsTool::ListAllLogSegments() {
117
0
  DCHECK(initialized_);
118
119
0
  auto wal_root_dirs = fs_manager_->GetWalRootDirs();
120
0
  for (auto const& wals_dir : wal_root_dirs) {
121
0
    if (!fs_manager_->Exists(wals_dir)) {
122
0
      return STATUS(Corruption, Substitute(
123
0
          "root log directory '$0' does not exist", wals_dir));
124
0
    }
125
126
0
    std::cout << "Root log directory: " << wals_dir << std::endl;
127
128
0
    vector<string> children;
129
0
    vector<string> tables;
130
0
    RETURN_NOT_OK_PREPEND(fs_manager_->ListDir(wals_dir, &tables),
131
0
                          "Could not list table directories");
132
0
    auto has_dot_prefix = [](const std::string& s) {
133
0
                            return HasPrefixString(s, ".");
134
0
                          };
135
0
    tables.erase(std::remove_if(tables.begin(), tables.end(), has_dot_prefix), tables.end());
136
0
    for (const auto &table : tables) {
137
0
      auto table_wal_dir = JoinPathSegments(wals_dir, table);
138
0
      RETURN_NOT_OK_PREPEND(fs_manager_->ListDir(table_wal_dir, &children),
139
0
                            "Could not list log directories");
140
0
      for (const string &child : children) {
141
0
        if (has_dot_prefix(child)) {
142
          // Hidden files or ./..
143
0
          VLOG(1) << "Ignoring hidden file in root log directory " << child;
144
0
          continue;
145
0
        }
146
0
        string path = JoinPathSegments(table_wal_dir, child);
147
0
        if (HasSuffixString(child, FsManager::kWalsRecoveryDirSuffix)) {
148
0
          std::cout << "Log recovery dir found: " << path << std::endl;
149
0
        } else {
150
0
          std::cout << "Log directory: " << path << std::endl;
151
0
        }
152
0
        RETURN_NOT_OK(ListSegmentsInDir(path));
153
0
      }
154
0
    }
155
0
  }
156
0
  return Status::OK();
157
0
}
158
159
0
Status FsTool::ListLogSegmentsForTablet(const string& tablet_id) {
160
0
  DCHECK(initialized_);
161
162
0
  auto meta = VERIFY_RESULT(RaftGroupMetadata::Load(fs_manager_.get(), tablet_id));
163
164
0
  const string& tablet_wal_dir = meta->wal_dir();
165
0
  if (!fs_manager_->Exists(tablet_wal_dir)) {
166
0
    return STATUS(NotFound, Substitute("tablet '$0' has no logs in wals dir '$1'",
167
0
                                       tablet_id, tablet_wal_dir));
168
0
  }
169
0
  std::cout << "Tablet WAL dir found: " << tablet_wal_dir << std::endl;
170
0
  RETURN_NOT_OK(ListSegmentsInDir(tablet_wal_dir));
171
0
  const string recovery_dir = fs_manager_->GetTabletWalRecoveryDir(tablet_wal_dir);
172
0
  if (fs_manager_->Exists(recovery_dir)) {
173
0
    std::cout << "Recovery dir found: " << recovery_dir << std::endl;
174
0
    RETURN_NOT_OK(ListSegmentsInDir(recovery_dir));
175
0
  }
176
0
  return Status::OK();
177
0
}
178
179
180
0
Status FsTool::ListAllTablets() {
181
0
  DCHECK(initialized_);
182
183
0
  vector<string> tablets;
184
0
  RETURN_NOT_OK(fs_manager_->ListTabletIds(&tablets));
185
0
  for (const string& tablet : tablets) {
186
0
    if (detail_level_ >= HEADERS_ONLY) {
187
0
      std::cout << "Tablet: " << tablet << std::endl;
188
0
      RETURN_NOT_OK(PrintTabletMeta(tablet, 2));
189
0
    } else {
190
0
      std::cout << "\t" << tablet << std::endl;
191
0
    }
192
0
  }
193
0
  return Status::OK();
194
0
}
195
196
0
Status FsTool::ListSegmentsInDir(const string& segments_dir) {
197
0
  vector<string> segments;
198
0
  RETURN_NOT_OK_PREPEND(fs_manager_->ListDir(segments_dir, &segments),
199
0
                        "Unable to list log segments");
200
0
  std::cout << "Segments in " << segments_dir << ":" << std::endl;
201
0
  for (const string& segment : segments) {
202
0
    if (!log::IsLogFileName(segment)) {
203
0
      continue;
204
0
    }
205
0
    if (detail_level_ >= HEADERS_ONLY) {
206
0
      std::cout << "Segment: " << segment << std::endl;
207
0
      string path = JoinPathSegments(segments_dir, segment);
208
0
      RETURN_NOT_OK(PrintLogSegmentHeader(path, 2));
209
0
    } else {
210
0
      std::cout << "\t" << segment << std::endl;
211
0
    }
212
0
  }
213
0
  return Status::OK();
214
0
}
215
216
Status FsTool::PrintLogSegmentHeader(const string& path,
217
0
                                     int indent) {
218
0
  auto segment_result = ReadableLogSegment::Open(fs_manager_->env(), path);
219
0
  if (!segment_result.ok()) {
220
0
    auto s = segment_result.status();
221
0
    if (s.IsUninitialized()) {
222
0
      LOG(ERROR) << path << " is not initialized: " << s.ToString();
223
0
      return Status::OK();
224
0
    }
225
0
    if (s.IsCorruption()) {
226
0
      LOG(ERROR) << path << " is corrupt: " << s.ToString();
227
0
      return Status::OK();
228
0
    }
229
0
    return s.CloneAndPrepend("Unexpected error reading log segment " + path);
230
0
  }
231
0
  const auto& segment = *segment_result;
232
233
0
  std::cout << Indent(indent) << "Size: "
234
0
            << HumanReadableNumBytes::ToStringWithoutRounding(segment->file_size())
235
0
            << std::endl;
236
0
  std::cout << Indent(indent) << "Header: " << std::endl;
237
0
  std::cout << IndentString(segment->header().DebugString(), indent);
238
0
  return Status::OK();
239
0
}
240
241
0
Status FsTool::PrintTabletMeta(const string& tablet_id, int indent) {
242
0
  auto meta = VERIFY_RESULT(RaftGroupMetadata::Load(fs_manager_.get(), tablet_id));
243
244
0
  const SchemaPtr schema = meta->schema();
245
246
0
  std::cout << Indent(indent) << "Partition: "
247
0
            << meta->partition_schema()->PartitionDebugString(*meta->partition(), *schema)
248
0
            << std::endl;
249
0
  std::cout << Indent(indent) << "Table name: " << meta->table_name()
250
0
            << " Table id: " << meta->table_id() << std::endl;
251
0
  std::cout << Indent(indent) << "Schema (version=" << meta->schema_version() << "): "
252
0
            << schema->ToString() << std::endl;
253
254
0
  tablet::RaftGroupReplicaSuperBlockPB pb;
255
0
  meta->ToSuperBlock(&pb);
256
0
  std::cout << "Superblock:\n" << pb.DebugString() << std::endl;
257
258
0
  return Status::OK();
259
0
}
260
261
0
Status FsTool::DumpTabletData(const std::string& tablet_id) {
262
0
  DCHECK(initialized_);
263
264
0
  auto meta = VERIFY_RESULT(RaftGroupMetadata::Load(fs_manager_.get(), tablet_id));
265
266
0
  scoped_refptr<log::LogAnchorRegistry> reg(new log::LogAnchorRegistry());
267
0
  tablet::TabletOptions tablet_options;
268
0
  tablet::TabletInitData tablet_init_data = {
269
0
    .metadata = meta,
270
0
    .client_future = std::shared_future<client::YBClient*>(),
271
0
    .clock = scoped_refptr<server::Clock>(),
272
0
    .parent_mem_tracker = shared_ptr<MemTracker>(),
273
0
    .block_based_table_mem_tracker = shared_ptr<MemTracker>(),
274
0
    .metric_registry = nullptr,
275
0
    .log_anchor_registry = reg.get(),
276
0
    .tablet_options = tablet_options,
277
0
    .log_prefix_suffix = std::string(),
278
0
    .transaction_participant_context = nullptr,
279
0
    .local_tablet_filter = client::LocalTabletFilter(),
280
0
    .transaction_coordinator_context = nullptr,
281
0
    .txns_enabled = tablet::TransactionsEnabled::kTrue,
282
0
    .is_sys_catalog = tablet::IsSysCatalogTablet(tablet_id == master::kSysCatalogTabletId),
283
0
  };
284
0
  Tablet t(tablet_init_data);
285
0
  RETURN_NOT_OK_PREPEND(t.Open(), "Couldn't open tablet");
286
0
  vector<string> lines;
287
0
  RETURN_NOT_OK_PREPEND(t.DebugDump(&lines), "Couldn't dump tablet");
288
0
  for (const string& line : lines) {
289
0
    std::cout << line << std::endl;
290
0
  }
291
0
  return Status::OK();
292
0
}
293
294
0
Status FsTool::PrintUUID(int indent) {
295
0
  std::cout << Indent(indent) << fs_manager_->uuid() << std::endl;
296
0
  return Status::OK();
297
0
}
298
299
} // namespace tools
300
} // namespace yb