/Users/deen/code/yugabyte-db/src/yb/tools/yb-ysck.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 | | // Command line tool to run Ysck against a cluster. Defaults to running against a local Master |
33 | | // on the default RPC port. It verifies that all the reported Tablet Servers are running and that |
34 | | // the tablets are in a consistent state. |
35 | | |
36 | | #include <gflags/gflags.h> |
37 | | #include <glog/logging.h> |
38 | | |
39 | | #include "yb/gutil/strings/split.h" |
40 | | #include "yb/gutil/strings/substitute.h" |
41 | | |
42 | | #include "yb/master/master_defaults.h" |
43 | | |
44 | | #include "yb/tools/ysck_remote.h" |
45 | | |
46 | | #include "yb/util/flags.h" |
47 | | #include "yb/util/logging.h" |
48 | | |
49 | 0 | #define PUSH_PREPEND_NOT_OK(s, statuses, msg) do { \ |
50 | 0 | ::yb::Status _s = (s); \ |
51 | 0 | if (PREDICT_FALSE(!_s.ok())) { \ |
52 | 0 | statuses->push_back(string(msg) + ": " + _s.ToString()); \ |
53 | 0 | } \ |
54 | 0 | } while (0); |
55 | | |
56 | | using std::cerr; |
57 | | using std::cout; |
58 | | using std::endl; |
59 | | using std::shared_ptr; |
60 | | using std::vector; |
61 | | using strings::Substitute; |
62 | | |
63 | | DEFINE_string(master_address, "", |
64 | | "Address of master server to run against."); |
65 | | |
66 | | DEFINE_bool(checksum_scan, false, |
67 | | "Perform a checksum scan on data in the cluster."); |
68 | | |
69 | | DEFINE_string(tables, "", |
70 | | "Tables to check (comma-separated list of names). " |
71 | | "If not specified, checks all tables."); |
72 | | |
73 | | DEFINE_string(tablets, "", |
74 | | "Tablets to check (comma-separated list of IDs) " |
75 | | "If not specified, checks all tablets."); |
76 | | |
77 | | namespace yb { |
78 | | namespace tools { |
79 | | |
80 | 0 | static string GetYsckUsage(const char* progname) { |
81 | 0 | string msg = Substitute("Usage: $0 --master_address=<addr> <flags>\n\n", progname); |
82 | 0 | msg += "Check the health of a YB cluster.\n\n" |
83 | 0 | "By default, ysck checks that master and tablet server processes are running,\n" |
84 | 0 | "and that table metadata is consistent. Use the 'checksum' flag to check that\n" |
85 | 0 | "tablet data is consistent (also see the 'tables' and 'tablets' flags below).\n" |
86 | 0 | "Use the 'checksum_snapshot' along with 'checksum' if the table or tablets are\n" |
87 | 0 | "actively receiving inserts or updates."; |
88 | 0 | return msg; |
89 | 0 | } |
90 | | |
91 | | // Run ysck. |
92 | | // Error information is appended to the provided vector. |
93 | | // If the vector is empty upon completion, ysck ran successfully. |
94 | 0 | static void RunYsck(vector<string>* error_messages) { |
95 | 0 | std::vector<HostPort> master_addrs; |
96 | 0 | PUSH_PREPEND_NOT_OK( |
97 | 0 | HostPort::ParseStrings(FLAGS_master_address, master::kMasterDefaultPort, &master_addrs), |
98 | 0 | error_messages, "Unable to parse master address"); |
99 | |
|
100 | 0 | shared_ptr<YsckMaster> master; |
101 | 0 | PUSH_PREPEND_NOT_OK(RemoteYsckMaster::Build(master_addrs[0], &master), |
102 | 0 | error_messages, "Unable to build YsckMaster"); |
103 | 0 | if (!error_messages->empty()) return; |
104 | 0 | shared_ptr<YsckCluster> cluster(new YsckCluster(master)); |
105 | 0 | shared_ptr<Ysck> ysck(new Ysck(cluster)); |
106 | | |
107 | | // This is required for everything below. |
108 | 0 | PUSH_PREPEND_NOT_OK(ysck->CheckMasterRunning(), error_messages, |
109 | 0 | "Master aliveness check error"); |
110 | 0 | if (!error_messages->empty()) return; |
111 | | |
112 | | // This is also required for everything below. |
113 | 0 | PUSH_PREPEND_NOT_OK(ysck->FetchTableAndTabletInfo(), error_messages, |
114 | 0 | "Error fetching the cluster metadata from the Master server"); |
115 | 0 | if (!error_messages->empty()) return; |
116 | | |
117 | 0 | PUSH_PREPEND_NOT_OK(ysck->CheckTabletServersRunning(), error_messages, |
118 | 0 | "Tablet server aliveness check error"); |
119 | | |
120 | | // TODO: Add support for tables / tablets filter in the consistency check. |
121 | 0 | PUSH_PREPEND_NOT_OK(ysck->CheckTablesConsistency(), error_messages, |
122 | 0 | "Table consistency check error"); |
123 | |
|
124 | 0 | if (FLAGS_checksum_scan) { |
125 | 0 | vector<string> tables = strings::Split(FLAGS_tables, ",", strings::SkipEmpty()); |
126 | 0 | vector<string> tablets = strings::Split(FLAGS_tablets, ",", strings::SkipEmpty()); |
127 | 0 | PUSH_PREPEND_NOT_OK(ysck->ChecksumData(tables, tablets, ChecksumOptions()), |
128 | 0 | error_messages, "Checksum scan error"); |
129 | 0 | } |
130 | 0 | } |
131 | | |
132 | | } // namespace tools |
133 | | } // namespace yb |
134 | | |
135 | | int main(int argc, char** argv) { |
136 | | google::SetUsageMessage(yb::tools::GetYsckUsage(argv[0])); |
137 | | if (argc < 2) { |
138 | | google::ShowUsageWithFlagsRestrict(argv[0], __FILE__); |
139 | | exit(1); |
140 | | } |
141 | | yb::ParseCommandLineFlags(&argc, &argv, true); |
142 | | FLAGS_logtostderr = true; |
143 | | yb::InitGoogleLoggingSafe(argv[0]); |
144 | | |
145 | | vector<string> error_messages; |
146 | | yb::tools::RunYsck(&error_messages); |
147 | | |
148 | | // All good. |
149 | | if (error_messages.empty()) { |
150 | | cout << "OK" << endl; |
151 | | return 0; |
152 | | } |
153 | | |
154 | | // Something went wrong. |
155 | | cerr << "==================" << endl; |
156 | | cerr << "Errors:" << endl; |
157 | | cerr << "==================" << endl; |
158 | | for (const string& s : error_messages) { |
159 | | cerr << s << endl; |
160 | | } |
161 | | cerr << endl; |
162 | | cerr << "FAILED" << endl; |
163 | | return 1; |
164 | | } |