You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kudu.apache.org by to...@apache.org on 2016/09/13 02:18:29 UTC
[3/3] kudu git commit: tool: port ts-cli
tool: port ts-cli
I chose to expose common server functionality in new 'master' and 'tserver'
modes rather than consolidating them into a shared 'server' mode; I found
this to be more more intuitive.
I also snuck in a change to ksck to use FLAGS_timeout_ms for RPC timeouts
in client-based operations.
Change-Id: Ifb5a59fd690c2dd09e4e76858469d81f9d501371
Reviewed-on: http://gerrit.cloudera.org:8080/4373
Tested-by: Kudu Jenkins
Reviewed-by: Todd Lipcon <to...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/kudu/repo
Commit: http://git-wip-us.apache.org/repos/asf/kudu/commit/14cd22a1
Tree: http://git-wip-us.apache.org/repos/asf/kudu/tree/14cd22a1
Diff: http://git-wip-us.apache.org/repos/asf/kudu/diff/14cd22a1
Branch: refs/heads/master
Commit: 14cd22a10b33545c5136ad68ebcf5cc0543ac525
Parents: 9cb1bca
Author: Adar Dembo <ad...@cloudera.com>
Authored: Sun Sep 11 15:13:23 2016 -0700
Committer: Todd Lipcon <to...@apache.org>
Committed: Tue Sep 13 02:14:29 2016 +0000
----------------------------------------------------------------------
build-support/dist_test.py | 1 -
docs/release_notes.adoc | 3 +
src/kudu/client/scan_batch.h | 4 +-
src/kudu/client/schema.h | 6 +-
src/kudu/tablet/tablet_peer.h | 4 +-
src/kudu/tools/CMakeLists.txt | 10 +-
src/kudu/tools/ksck_remote.cc | 1 +
src/kudu/tools/kudu-tool-test.cc | 28 ++
src/kudu/tools/kudu-ts-cli-test.cc | 14 +-
src/kudu/tools/tool_action.h | 3 +
src/kudu/tools/tool_action_common.cc | 132 ++++++
src/kudu/tools/tool_action_common.h | 40 ++
src/kudu/tools/tool_action_master.cc | 97 +++++
src/kudu/tools/tool_action_remote_replica.cc | 331 +++++++++++++++
src/kudu/tools/tool_action_tablet.cc | 11 +-
src/kudu/tools/tool_action_tserver.cc | 98 +++++
src/kudu/tools/tool_main.cc | 3 +
src/kudu/tools/ts-cli.cc | 494 ----------------------
18 files changed, 758 insertions(+), 522 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/kudu/blob/14cd22a1/build-support/dist_test.py
----------------------------------------------------------------------
diff --git a/build-support/dist_test.py b/build-support/dist_test.py
index d19a78f..003a5dd 100755
--- a/build-support/dist_test.py
+++ b/build-support/dist_test.py
@@ -69,7 +69,6 @@ DEPS_FOR_ALL = \
# TODO: declare these dependencies per-test.
"build/latest/bin/kudu-tserver",
"build/latest/bin/kudu-master",
- "build/latest/bin/kudu-ts-cli",
# parser-test requires these data files.
# TODO: again, we should do this with some per-test metadata file.
http://git-wip-us.apache.org/repos/asf/kudu/blob/14cd22a1/docs/release_notes.adoc
----------------------------------------------------------------------
diff --git a/docs/release_notes.adoc b/docs/release_notes.adoc
index 9fd83ef..0261d99 100644
--- a/docs/release_notes.adoc
+++ b/docs/release_notes.adoc
@@ -130,6 +130,9 @@ Kudu 1.0.0 are not supported.
- The `kudu-fs_dump` tool has been removed. The same functionality is now
implemented as `kudu fs dump`.
+- The `kudu-ts-cli` tool has been removed. The same functionality is now
+ implemented within `kudu master`, `kudu remote_replica`, and `kudu tserver`.
+
- The `kudu-fs_list` tool has been removed and some similar useful
functionality has been moved under 'kudu local_replica'.
http://git-wip-us.apache.org/repos/asf/kudu/blob/14cd22a1/src/kudu/client/scan_batch.h
----------------------------------------------------------------------
diff --git a/src/kudu/client/scan_batch.h b/src/kudu/client/scan_batch.h
index 9b1433d..b4d91f6 100644
--- a/src/kudu/client/scan_batch.h
+++ b/src/kudu/client/scan_batch.h
@@ -33,7 +33,7 @@ namespace kudu {
class Schema;
namespace tools {
-class TsAdminClient;
+class ReplicaDumper;
} // namespace tools
namespace client {
@@ -119,7 +119,7 @@ class KUDU_EXPORT KuduScanBatch {
private:
class KUDU_NO_EXPORT Data;
friend class KuduScanner;
- friend class kudu::tools::TsAdminClient;
+ friend class tools::ReplicaDumper;
Data* data_;
DISALLOW_COPY_AND_ASSIGN(KuduScanBatch);
http://git-wip-us.apache.org/repos/asf/kudu/blob/14cd22a1/src/kudu/client/schema.h
----------------------------------------------------------------------
diff --git a/src/kudu/client/schema.h b/src/kudu/client/schema.h
index 70ba676..a09a88d 100644
--- a/src/kudu/client/schema.h
+++ b/src/kudu/client/schema.h
@@ -33,7 +33,7 @@ class TestWorkload;
namespace tools {
class RemoteKsckMaster;
-class TsAdminClient;
+class ReplicaDumper;
}
namespace client {
@@ -490,8 +490,8 @@ class KUDU_EXPORT KuduSchema {
friend class internal::LookupRpc;
friend class internal::MetaCacheEntry;
friend class internal::WriteRpc;
- friend class kudu::tools::RemoteKsckMaster;
- friend class kudu::tools::TsAdminClient;
+ friend class tools::RemoteKsckMaster;
+ friend class tools::ReplicaDumper;
friend KuduSchema KuduSchemaFromSchema(const Schema& schema);
http://git-wip-us.apache.org/repos/asf/kudu/blob/14cd22a1/src/kudu/tablet/tablet_peer.h
----------------------------------------------------------------------
diff --git a/src/kudu/tablet/tablet_peer.h b/src/kudu/tablet/tablet_peer.h
index 8d72e72..c43c83a 100644
--- a/src/kudu/tablet/tablet_peer.h
+++ b/src/kudu/tablet/tablet_peer.h
@@ -196,9 +196,7 @@ class TabletPeer : public RefCountedThreadSafe<TabletPeer>,
// etc. For use in places like the Web UI.
std::string HumanReadableState() const;
- // Adds list of transactions in-flight at the time of the call to
- // 'out'. TransactionStatusPB objects are used to allow this method
- // to be used by both the web-UI and ts-cli.
+ // Adds list of transactions in-flight at the time of the call to 'out'.
void GetInFlightTransactions(Transaction::TraceType trace_type,
std::vector<consensus::TransactionStatusPB>* out) const;
http://git-wip-us.apache.org/repos/asf/kudu/blob/14cd22a1/src/kudu/tools/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/src/kudu/tools/CMakeLists.txt b/src/kudu/tools/CMakeLists.txt
index 0ce2899..54159dc 100644
--- a/src/kudu/tools/CMakeLists.txt
+++ b/src/kudu/tools/CMakeLists.txt
@@ -44,10 +44,6 @@ target_link_libraries(insert-generated-rows
kudu_tools_util
${LINK_LIBS})
-add_executable(kudu-ts-cli ts-cli.cc)
-target_link_libraries(kudu-ts-cli
- ${LINK_LIBS})
-
add_library(ksck
ksck.cc
ksck_remote.cc
@@ -68,9 +64,12 @@ add_executable(kudu
tool_action_common.cc
tool_action_fs.cc
tool_action_local_replica.cc
+ tool_action_master.cc
tool_action_pbc.cc
+ tool_action_remote_replica.cc
tool_action_table.cc
tool_action_tablet.cc
+ tool_action_tserver.cc
tool_action_wal.cc
tool_main.cc
)
@@ -79,6 +78,7 @@ target_link_libraries(kudu
gutil
krpc
ksck
+ kudu_client
kudu_common
kudu_fs
kudu_util
@@ -105,5 +105,5 @@ ADD_KUDU_TEST_DEPENDENCIES(kudu-tool-test
kudu)
ADD_KUDU_TEST(kudu-ts-cli-test)
ADD_KUDU_TEST_DEPENDENCIES(kudu-ts-cli-test
- kudu-ts-cli)
+ kudu)
http://git-wip-us.apache.org/repos/asf/kudu/blob/14cd22a1/src/kudu/tools/ksck_remote.cc
----------------------------------------------------------------------
diff --git a/src/kudu/tools/ksck_remote.cc b/src/kudu/tools/ksck_remote.cc
index c2cc85c..1dddfec 100644
--- a/src/kudu/tools/ksck_remote.cc
+++ b/src/kudu/tools/ksck_remote.cc
@@ -262,6 +262,7 @@ void RemoteKsckTabletServer::RunTabletChecksumScanAsync(
Status RemoteKsckMaster::Connect() {
client::sp::shared_ptr<KuduClient> client;
KuduClientBuilder builder;
+ builder.default_rpc_timeout(GetDefaultTimeout());
builder.master_server_addrs(master_addresses_);
return builder.Build(&client_);
}
http://git-wip-us.apache.org/repos/asf/kudu/blob/14cd22a1/src/kudu/tools/kudu-tool-test.cc
----------------------------------------------------------------------
diff --git a/src/kudu/tools/kudu-tool-test.cc b/src/kudu/tools/kudu-tool-test.cc
index 9720d4a..1db59df 100644
--- a/src/kudu/tools/kudu-tool-test.cc
+++ b/src/kudu/tools/kudu-tool-test.cc
@@ -181,9 +181,12 @@ TEST_F(ToolTest, TestTopLevelHelp) {
"cluster.*Kudu cluster",
"fs.*Kudu filesystem",
"local_replica.*Kudu replicas",
+ "master.*Kudu Master",
"pbc.*protobuf container",
+ "remote_replica.*replicas on a Kudu Tablet Server",
"table.*Kudu tables",
"tablet.*Kudu tablets",
+ "tserver.*Kudu Tablet Server",
"wal.*write-ahead log"
};
NO_FATALS(RunTestHelp("", kTopLevelRegexes));
@@ -244,12 +247,29 @@ TEST_F(ToolTest, TestModeHelp) {
NO_FATALS(RunTestHelp("cluster", kClusterModeRegexes));
}
{
+ const vector<string> kMasterModeRegexes = {
+ "set_flag.*Change a gflag value",
+ "status.*Get the status",
+ "timestamp.*Get the current timestamp"
+ };
+ NO_FATALS(RunTestHelp("master", kMasterModeRegexes));
+ }
+ {
const vector<string> kPbcModeRegexes = {
"dump.*Dump a PBC",
};
NO_FATALS(RunTestHelp("pbc", kPbcModeRegexes));
}
{
+ const vector<string> kRemoteReplicaModeRegexes = {
+ "check.*Check if all replicas",
+ "delete.*Delete a replica",
+ "dump.*Dump the data of a replica",
+ "list.*List all replicas"
+ };
+ NO_FATALS(RunTestHelp("remote_replica", kRemoteReplicaModeRegexes));
+ }
+ {
const vector<string> kTableModeRegexes = {
"delete.*Delete a table",
"list.*List all tables",
@@ -271,6 +291,14 @@ TEST_F(ToolTest, TestModeHelp) {
NO_FATALS(RunTestHelp("tablet change_config", kChangeConfigModeRegexes));
}
{
+ const vector<string> kTServerModeRegexes = {
+ "set_flag.*Change a gflag value",
+ "status.*Get the status",
+ "timestamp.*Get the current timestamp"
+ };
+ NO_FATALS(RunTestHelp("tserver", kTServerModeRegexes));
+ }
+ {
const vector<string> kWalModeRegexes = {
"dump.*Dump a WAL",
};
http://git-wip-us.apache.org/repos/asf/kudu/blob/14cd22a1/src/kudu/tools/kudu-ts-cli-test.cc
----------------------------------------------------------------------
diff --git a/src/kudu/tools/kudu-ts-cli-test.cc b/src/kudu/tools/kudu-ts-cli-test.cc
index 6300781..cbcf190 100644
--- a/src/kudu/tools/kudu-ts-cli-test.cc
+++ b/src/kudu/tools/kudu-ts-cli-test.cc
@@ -36,7 +36,7 @@ using strings::Substitute;
namespace kudu {
namespace tools {
-static const char* const kTsCliToolName = "kudu-ts-cli";
+static const char* const kTsCliToolName = "kudu";
class KuduTsCliTest : public ExternalMiniClusterITestBase {
protected:
@@ -78,9 +78,9 @@ TEST_F(KuduTsCliTest, TestDeleteTablet) {
string out;
ASSERT_OK(Subprocess::Call({
GetTsCliToolPath(),
- "--server_address",
+ "remote_replica",
+ "delete",
cluster_->tablet_server(0)->bound_rpc_addr().ToString(),
- "delete_tablet",
tablet_id,
"Deleting for kudu-ts-cli-test"
}, &out));
@@ -117,9 +117,9 @@ TEST_F(KuduTsCliTest, TestDumpTablet) {
// Test for dump_tablet when there is no data in tablet.
ASSERT_OK(Subprocess::Call({
GetTsCliToolPath(),
- "--server_address",
+ "remote_replica",
+ "dump",
cluster_->tablet_server(0)->bound_rpc_addr().ToString(),
- "dump_tablet",
tablet_id
}, &out));
ASSERT_EQ("", out);
@@ -133,9 +133,9 @@ TEST_F(KuduTsCliTest, TestDumpTablet) {
ASSERT_OK(WaitForServersToAgree(timeout, ts_map_, tablet_id, workload.batches_completed()));
ASSERT_OK(Subprocess::Call({
GetTsCliToolPath(),
- "--server_address",
+ "remote_replica",
+ "dump",
cluster_->tablet_server(0)->bound_rpc_addr().ToString(),
- "dump_tablet",
tablet_id
}, &out));
http://git-wip-us.apache.org/repos/asf/kudu/blob/14cd22a1/src/kudu/tools/tool_action.h
----------------------------------------------------------------------
diff --git a/src/kudu/tools/tool_action.h b/src/kudu/tools/tool_action.h
index c03e5d4..95aa162 100644
--- a/src/kudu/tools/tool_action.h
+++ b/src/kudu/tools/tool_action.h
@@ -278,9 +278,12 @@ class Action {
std::unique_ptr<Mode> BuildClusterMode();
std::unique_ptr<Mode> BuildFsMode();
std::unique_ptr<Mode> BuildLocalReplicaMode();
+std::unique_ptr<Mode> BuildMasterMode();
std::unique_ptr<Mode> BuildPbcMode();
+std::unique_ptr<Mode> BuildRemoteReplicaMode();
std::unique_ptr<Mode> BuildTableMode();
std::unique_ptr<Mode> BuildTabletMode();
+std::unique_ptr<Mode> BuildTServerMode();
std::unique_ptr<Mode> BuildWalMode();
} // namespace tools
http://git-wip-us.apache.org/repos/asf/kudu/blob/14cd22a1/src/kudu/tools/tool_action_common.cc
----------------------------------------------------------------------
diff --git a/src/kudu/tools/tool_action_common.cc b/src/kudu/tools/tool_action_common.cc
index 1daa12d..bbcf981 100644
--- a/src/kudu/tools/tool_action_common.cc
+++ b/src/kudu/tools/tool_action_common.cc
@@ -18,6 +18,7 @@
#include "kudu/tools/tool_action_common.h"
#include <iostream>
+#include <memory>
#include <string>
#include <vector>
@@ -29,16 +30,32 @@
#include "kudu/common/row_operations.h"
#include "kudu/common/wire_protocol.h"
#include "kudu/consensus/consensus.pb.h"
+#include "kudu/consensus/consensus.proxy.h"
#include "kudu/consensus/log.pb.h"
#include "kudu/consensus/log_util.h"
#include "kudu/gutil/ref_counted.h"
#include "kudu/gutil/strings/numbers.h"
+#include "kudu/rpc/messenger.h"
+#include "kudu/rpc/rpc_controller.h"
#include "kudu/rpc/rpc_header.pb.h"
+#include "kudu/server/server_base.pb.h"
+#include "kudu/server/server_base.proxy.h"
#include "kudu/tserver/tserver.pb.h"
+#include "kudu/tserver/tserver_admin.proxy.h"
+#include "kudu/tserver/tserver_service.proxy.h"
#include "kudu/util/memory/arena.h"
+#include "kudu/util/monotime.h"
+#include "kudu/util/net/net_util.h"
+#include "kudu/util/net/sockaddr.h"
#include "kudu/util/pb_util.h"
#include "kudu/util/status.h"
+DECLARE_int64(timeout_ms); // defined in ksck
+
+DEFINE_bool(force, false, "If true, allows the set_flag command to set a flag "
+ "which is not explicitly marked as runtime-settable. Such flag "
+ "changes may be simply ignored on the server, or may cause the "
+ "server to crash.");
DEFINE_bool(print_meta, true, "Include metadata in output");
DEFINE_string(print_entries, "decoded",
"How to print entries:\n"
@@ -53,16 +70,32 @@ DEFINE_int32(truncate_data, 100,
namespace kudu {
namespace tools {
+using consensus::ConsensusServiceProxy;
using consensus::ReplicateMsg;
using log::LogEntryPB;
using log::LogEntryReader;
using log::ReadableLogSegment;
+using rpc::Messenger;
+using rpc::MessengerBuilder;
using rpc::RequestIdPB;
+using rpc::RpcController;
+using server::GenericServiceProxy;
+using server::GetStatusRequestPB;
+using server::GetStatusResponsePB;
+using server::ServerClockRequestPB;
+using server::ServerClockResponsePB;
+using server::ServerStatusPB;
+using server::SetFlagRequestPB;
+using server::SetFlagResponsePB;
using std::cout;
using std::cerr;
using std::endl;
+using std::shared_ptr;
using std::string;
+using std::unique_ptr;
using std::vector;
+using tserver::TabletServerAdminServiceProxy;
+using tserver::TabletServerServiceProxy;
using tserver::WriteRequestPB;
namespace {
@@ -170,6 +203,55 @@ Status PrintDecoded(const LogEntryPB& entry, const Schema& tablet_schema) {
} // anonymous namespace
+template<class ProxyClass>
+Status BuildProxy(const string& address,
+ uint16_t default_port,
+ unique_ptr<ProxyClass>* proxy) {
+ HostPort hp;
+ RETURN_NOT_OK(hp.ParseString(address, default_port));
+ shared_ptr<Messenger> messenger;
+ RETURN_NOT_OK(MessengerBuilder("tool").Build(&messenger));
+
+ vector<Sockaddr> resolved;
+ RETURN_NOT_OK(hp.ResolveAddresses(&resolved));
+
+ proxy->reset(new ProxyClass(messenger, resolved[0]));
+ return Status::OK();
+}
+
+// Explicit specialization for callers outside this compilation unit.
+template
+Status BuildProxy(const string& address,
+ uint16_t default_port,
+ unique_ptr<ConsensusServiceProxy>* proxy);
+template
+Status BuildProxy(const string& address,
+ uint16_t default_port,
+ unique_ptr<TabletServerServiceProxy>* proxy);
+template
+Status BuildProxy(const string& address,
+ uint16_t default_port,
+ unique_ptr<TabletServerAdminServiceProxy>* proxy);
+
+Status GetServerStatus(const string& address, uint16_t default_port,
+ ServerStatusPB* status) {
+ unique_ptr<GenericServiceProxy> proxy;
+ RETURN_NOT_OK(BuildProxy(address, default_port, &proxy));
+
+ GetStatusRequestPB req;
+ GetStatusResponsePB resp;
+ RpcController rpc;
+ rpc.set_timeout(MonoDelta::FromMilliseconds(FLAGS_timeout_ms));
+
+ RETURN_NOT_OK(proxy->GetStatus(req, &resp, &rpc));
+ if (!resp.has_status()) {
+ return Status::Incomplete("Server response did not contain status",
+ proxy->ToString());
+ }
+ *status = resp.status();
+ return Status::OK();
+}
+
Status PrintSegment(const scoped_refptr<ReadableLogSegment>& segment) {
PrintEntryType print_type = ParsePrintType();
if (FLAGS_print_meta) {
@@ -206,5 +288,55 @@ Status PrintSegment(const scoped_refptr<ReadableLogSegment>& segment) {
return Status::OK();
}
+Status SetServerFlag(const string& address, uint16_t default_port,
+ const string& flag, const string& value) {
+ unique_ptr<GenericServiceProxy> proxy;
+ RETURN_NOT_OK(BuildProxy(address, default_port, &proxy));
+
+ SetFlagRequestPB req;
+ SetFlagResponsePB resp;
+ RpcController rpc;
+ rpc.set_timeout(MonoDelta::FromMilliseconds(FLAGS_timeout_ms));
+
+ req.set_flag(flag);
+ req.set_value(value);
+ req.set_force(FLAGS_force);
+
+ RETURN_NOT_OK(proxy->SetFlag(req, &resp, &rpc));
+ switch (resp.result()) {
+ case server::SetFlagResponsePB::SUCCESS:
+ return Status::OK();
+ case server::SetFlagResponsePB::NOT_SAFE:
+ return Status::RemoteError(resp.msg() +
+ " (use --force flag to allow anyway)");
+ default:
+ return Status::RemoteError(resp.ShortDebugString());
+ }
+}
+
+Status PrintServerStatus(const string& address, uint16_t default_port) {
+ ServerStatusPB status;
+ RETURN_NOT_OK(GetServerStatus(address, default_port, &status));
+ cout << status.DebugString() << endl;
+ return Status::OK();
+}
+
+Status PrintServerTimestamp(const string& address, uint16_t default_port) {
+ unique_ptr<GenericServiceProxy> proxy;
+ RETURN_NOT_OK(BuildProxy(address, default_port, &proxy));
+
+ ServerClockRequestPB req;
+ ServerClockResponsePB resp;
+ RpcController rpc;
+ rpc.set_timeout(MonoDelta::FromMilliseconds(FLAGS_timeout_ms));
+ RETURN_NOT_OK(proxy->ServerClock(req, &resp, &rpc));
+ if (!resp.has_timestamp()) {
+ return Status::Incomplete("Server response did not contain timestamp",
+ proxy->ToString());
+ }
+ cout << resp.timestamp() << endl;
+ return Status::OK();
+}
+
} // namespace tools
} // namespace kudu
http://git-wip-us.apache.org/repos/asf/kudu/blob/14cd22a1/src/kudu/tools/tool_action_common.h
----------------------------------------------------------------------
diff --git a/src/kudu/tools/tool_action_common.h b/src/kudu/tools/tool_action_common.h
index 0391bb3..d51f656 100644
--- a/src/kudu/tools/tool_action_common.h
+++ b/src/kudu/tools/tool_action_common.h
@@ -17,6 +17,9 @@
#pragma once
+#include <memory>
+#include <string>
+
#include "kudu/gutil/ref_counted.h"
#include "kudu/util/status.h"
@@ -26,10 +29,30 @@ namespace log {
class ReadableLogSegment;
} // namespace log
+namespace server {
+class ServerStatusPB;
+} // namespace server
+
namespace tools {
// Utility methods used by multiple actions across different modes.
+// Builds a proxy to a Kudu server running at 'address', returning it in
+// 'proxy'.
+//
+// If 'address' does not contain a port, 'default_port' is used instead.
+template<class ProxyClass>
+Status BuildProxy(const std::string& address,
+ uint16_t default_port,
+ std::unique_ptr<ProxyClass>* proxy);
+
+// Get the current status of the Kudu server running at 'address', storing it
+// in 'status'.
+//
+// If 'address' does not contain a port, 'default_port' is used instead.
+Status GetServerStatus(const std::string& address, uint16_t default_port,
+ server::ServerStatusPB* status);
+
// Prints the contents of a WAL segment to stdout.
//
// The following gflags affect the output:
@@ -38,5 +61,22 @@ namespace tools {
// - truncate_data: how many bytes to print for each data field.
Status PrintSegment(const scoped_refptr<log::ReadableLogSegment>& segment);
+// Print the current status of the Kudu server running at 'address'.
+//
+// If 'address' does not contain a port, 'default_port' is used instead.
+Status PrintServerStatus(const std::string& address, uint16_t default_port);
+
+// Print the current timestamp of the Kudu server running at 'address'.
+//
+// If 'address' does not contain a port, 'default_port' is used instead.
+Status PrintServerTimestamp(const std::string& address, uint16_t default_port);
+
+// Changes the value of the gflag given by 'flag' to the value in 'value' on
+// the Kudu server running at 'address'.
+//
+// If 'address' does not contain a port, 'default_port' is used instead.
+Status SetServerFlag(const std::string& address, uint16_t default_port,
+ const std::string& flag, const std::string& value);
+
} // namespace tools
} // namespace kudu
http://git-wip-us.apache.org/repos/asf/kudu/blob/14cd22a1/src/kudu/tools/tool_action_master.cc
----------------------------------------------------------------------
diff --git a/src/kudu/tools/tool_action_master.cc b/src/kudu/tools/tool_action_master.cc
new file mode 100644
index 0000000..aea53d1
--- /dev/null
+++ b/src/kudu/tools/tool_action_master.cc
@@ -0,0 +1,97 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "kudu/tools/tool_action.h"
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include <gflags/gflags.h>
+
+#include "kudu/gutil/map-util.h"
+#include "kudu/master/master.h"
+#include "kudu/tools/tool_action_common.h"
+#include "kudu/util/status.h"
+
+namespace kudu {
+namespace tools {
+
+using std::string;
+using std::unique_ptr;
+
+namespace {
+
+const char* const kMasterAddressArg = "master_address";
+const char* const kMasterAddressDesc = "Address of a Kudu Master of form "
+ "'hostname:port'. Port may be omitted if the Master is bound to the "
+ "default port.";
+const char* const kFlagArg = "flag";
+const char* const kValueArg = "value";
+
+Status MasterSetFlag(const RunnerContext& context) {
+ string address = FindOrDie(context.required_args, kMasterAddressArg);
+ string flag = FindOrDie(context.required_args, kFlagArg);
+ string value = FindOrDie(context.required_args, kValueArg);
+ return SetServerFlag(address, master::Master::kDefaultPort, flag, value);
+}
+
+Status MasterStatus(const RunnerContext& context) {
+ string address = FindOrDie(context.required_args, kMasterAddressArg);
+ return PrintServerStatus(address, master::Master::kDefaultPort);
+}
+
+Status MasterTimestamp(const RunnerContext& context) {
+ string address = FindOrDie(context.required_args, kMasterAddressArg);
+ return PrintServerTimestamp(address, master::Master::kDefaultPort);
+}
+
+} // anonymous namespace
+
+unique_ptr<Mode> BuildMasterMode() {
+ unique_ptr<Action> set_flag =
+ ActionBuilder("set_flag", &MasterSetFlag)
+ .Description("Change a gflag value on a Kudu Master")
+ .AddRequiredParameter({ kMasterAddressArg, kMasterAddressDesc })
+ .AddRequiredParameter({ kFlagArg, "Name of the gflag" })
+ .AddRequiredParameter({ kValueArg, "New value for the gflag" })
+ .AddOptionalParameter("force")
+ .Build();
+
+ unique_ptr<Action> status =
+ ActionBuilder("status", &MasterStatus)
+ .Description("Get the status of a Kudu Master")
+ .AddRequiredParameter({ kMasterAddressArg, kMasterAddressDesc })
+ .Build();
+
+ unique_ptr<Action> timestamp =
+ ActionBuilder("timestamp", &MasterTimestamp)
+ .Description("Get the current timestamp of a Kudu Master")
+ .AddRequiredParameter({ kMasterAddressArg, kMasterAddressDesc })
+ .Build();
+
+ return ModeBuilder("master")
+ .Description("Operate on a Kudu Master")
+ .AddAction(std::move(set_flag))
+ .AddAction(std::move(status))
+ .AddAction(std::move(timestamp))
+ .Build();
+}
+
+} // namespace tools
+} // namespace kudu
+
http://git-wip-us.apache.org/repos/asf/kudu/blob/14cd22a1/src/kudu/tools/tool_action_remote_replica.cc
----------------------------------------------------------------------
diff --git a/src/kudu/tools/tool_action_remote_replica.cc b/src/kudu/tools/tool_action_remote_replica.cc
new file mode 100644
index 0000000..8ee7cb9
--- /dev/null
+++ b/src/kudu/tools/tool_action_remote_replica.cc
@@ -0,0 +1,331 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "kudu/tools/tool_action.h"
+
+#include <iostream>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <gflags/gflags.h>
+
+#include "kudu/client/client.h"
+#include "kudu/client/row_result.h"
+#include "kudu/client/scan_batch.h"
+#include "kudu/client/scanner-internal.h"
+#include "kudu/common/partition.h"
+#include "kudu/common/schema.h"
+#include "kudu/common/wire_protocol.h"
+#include "kudu/gutil/gscoped_ptr.h"
+#include "kudu/gutil/map-util.h"
+#include "kudu/gutil/strings/human_readable.h"
+#include "kudu/server/server_base.pb.h"
+#include "kudu/tablet/tablet.pb.h"
+#include "kudu/tools/tool_action_common.h"
+#include "kudu/tserver/tablet_server.h"
+#include "kudu/tserver/tserver.pb.h"
+#include "kudu/tserver/tserver_admin.proxy.h"
+#include "kudu/tserver/tserver_service.proxy.h"
+#include "kudu/rpc/messenger.h"
+#include "kudu/rpc/rpc_controller.h"
+#include "kudu/util/net/net_util.h"
+#include "kudu/util/net/sockaddr.h"
+#include "kudu/util/status.h"
+
+DECLARE_int64(timeout_ms); // defined in ksck
+
+namespace kudu {
+namespace tools {
+
+using client::KuduRowResult;
+using client::KuduScanBatch;
+using client::KuduSchema;
+using rpc::Messenger;
+using rpc::MessengerBuilder;
+using rpc::RpcController;
+using server::ServerStatusPB;
+using std::cerr;
+using std::cout;
+using std::endl;
+using std::shared_ptr;
+using std::string;
+using std::unique_ptr;
+using std::vector;
+using tablet::TabletStatusPB;
+using tserver::DeleteTabletRequestPB;
+using tserver::DeleteTabletResponsePB;
+using tserver::ListTabletsRequestPB;
+using tserver::ListTabletsResponsePB;
+using tserver::NewScanRequestPB;
+using tserver::ScanRequestPB;
+using tserver::ScanResponsePB;
+using tserver::TabletServerAdminServiceProxy;
+using tserver::TabletServerServiceProxy;
+
+// This class only exists so that Dump() can easily be friended with
+// KuduSchema and KuduScanBatch.
+class ReplicaDumper {
+ public:
+ static Status Dump(const Schema& schema,
+ const string& tablet_id,
+ TabletServerServiceProxy* proxy) {
+ KuduSchema client_schema(schema);
+
+ ScanRequestPB req;
+ ScanResponsePB resp;
+
+ NewScanRequestPB* new_req = req.mutable_new_scan_request();
+ RETURN_NOT_OK(SchemaToColumnPBs(
+ schema, new_req->mutable_projected_columns(),
+ SCHEMA_PB_WITHOUT_IDS | SCHEMA_PB_WITHOUT_STORAGE_ATTRIBUTES));
+ new_req->set_tablet_id(tablet_id);
+ new_req->set_cache_blocks(false);
+ new_req->set_order_mode(ORDERED);
+ new_req->set_read_mode(READ_AT_SNAPSHOT);
+
+ do {
+ RpcController rpc;
+ rpc.set_timeout(MonoDelta::FromMilliseconds(FLAGS_timeout_ms));
+ RETURN_NOT_OK_PREPEND(proxy->Scan(req, &resp, &rpc), "Scan() failed");
+
+ if (resp.has_error()) {
+ return Status::IOError("Failed to read: ",
+ resp.error().ShortDebugString());
+ }
+
+ // The first response has a scanner ID. We use this for all subsequent
+ // responses.
+ if (resp.has_scanner_id()) {
+ req.set_scanner_id(resp.scanner_id());
+ req.clear_new_scan_request();
+ }
+ req.set_call_seq_id(req.call_seq_id() + 1);
+
+ // Nothing to process from this scan result.
+ if (!resp.has_data()) {
+ continue;
+ }
+
+ KuduScanBatch::Data results;
+ RETURN_NOT_OK(results.Reset(&rpc,
+ &schema,
+ &client_schema,
+ make_gscoped_ptr(resp.release_data())));
+ vector<KuduRowResult> rows;
+ results.ExtractRows(&rows);
+ for (const auto& r : rows) {
+ cout << r.ToString() << endl;
+ }
+ } while (resp.has_more_results());
+ return Status::OK();
+ }
+};
+
+namespace {
+
+const char* const kReasonArg = "reason";
+const char* const kTabletArg = "tablet_id";
+const char* const kTabletDesc = "Tablet identifier";
+const char* const kTServerAddressArg = "tserver_address";
+const char* const kTServerAddressDesc = "Address of a Kudu Tablet Server of "
+ "form 'hostname:port'. Port may be omitted if the Tablet Server is bound "
+ "to the default port.";
+
+Status GetReplicas(TabletServerServiceProxy* proxy,
+ vector<ListTabletsResponsePB::StatusAndSchemaPB>* replicas) {
+ ListTabletsRequestPB req;
+ ListTabletsResponsePB resp;
+ RpcController rpc;
+ rpc.set_timeout(MonoDelta::FromMilliseconds(FLAGS_timeout_ms));
+
+ RETURN_NOT_OK(proxy->ListTablets(req, &resp, &rpc));
+ if (resp.has_error()) {
+ return StatusFromPB(resp.error().status());
+ }
+
+ replicas->assign(resp.status_and_schema().begin(),
+ resp.status_and_schema().end());
+ return Status::OK();
+}
+
+Status CheckReplicas(const RunnerContext& context) {
+ string address = FindOrDie(context.required_args, kTServerAddressArg);
+
+ unique_ptr<TabletServerServiceProxy> proxy;
+ RETURN_NOT_OK(BuildProxy(address, tserver::TabletServer::kDefaultPort,
+ &proxy));
+
+ vector<ListTabletsResponsePB::StatusAndSchemaPB> replicas;
+ RETURN_NOT_OK(GetReplicas(proxy.get(), &replicas));
+
+ bool all_running = true;
+ for (const auto& r : replicas) {
+ TabletStatusPB rs = r.tablet_status();
+ if (rs.state() != tablet::RUNNING) {
+ cerr << "Tablet id: " << rs.tablet_id() << " is "
+ << tablet::TabletStatePB_Name(rs.state()) << endl;
+ all_running = false;
+ }
+ }
+
+ if (all_running) {
+ cout << "All tablets are running" << endl;
+ return Status::OK();
+ } else {
+ return Status::IllegalState("Not all tablets are running");
+ }
+}
+
+Status DeleteReplica(const RunnerContext& context) {
+ string address = FindOrDie(context.required_args, kTServerAddressArg);
+ string tablet_id = FindOrDie(context.required_args, kTabletArg);
+ string reason = FindOrDie(context.required_args, kReasonArg);
+
+ ServerStatusPB status;
+ RETURN_NOT_OK(GetServerStatus(address, tserver::TabletServer::kDefaultPort,
+ &status));
+
+ unique_ptr<TabletServerAdminServiceProxy> proxy;
+ RETURN_NOT_OK(BuildProxy(address, tserver::TabletServer::kDefaultPort,
+ &proxy));
+
+ DeleteTabletRequestPB req;
+ DeleteTabletResponsePB resp;
+ RpcController rpc;
+ rpc.set_timeout(MonoDelta::FromMilliseconds(FLAGS_timeout_ms));
+
+ req.set_tablet_id(tablet_id);
+ req.set_dest_uuid(status.node_instance().permanent_uuid());
+ req.set_reason(reason);
+ req.set_delete_type(tablet::TABLET_DATA_TOMBSTONED);
+ RETURN_NOT_OK_PREPEND(proxy->DeleteTablet(req, &resp, &rpc),
+ "DeleteTablet() failed");
+ if (resp.has_error()) {
+ return Status::IOError("Failed to delete tablet: ",
+ resp.error().ShortDebugString());
+ }
+ return Status::OK();
+}
+
+Status DumpReplica(const RunnerContext& context) {
+ string address = FindOrDie(context.required_args, kTServerAddressArg);
+ string tablet_id = FindOrDie(context.required_args, kTabletArg);
+
+ unique_ptr<TabletServerServiceProxy> proxy;
+ RETURN_NOT_OK(BuildProxy(address, tserver::TabletServer::kDefaultPort,
+ &proxy));
+
+ vector<ListTabletsResponsePB::StatusAndSchemaPB> replicas;
+ RETURN_NOT_OK(GetReplicas(proxy.get(), &replicas));
+
+ Schema schema;
+ for (const auto& r : replicas) {
+ if (r.tablet_status().tablet_id() == tablet_id) {
+ RETURN_NOT_OK(SchemaFromPB(r.schema(), &schema));
+ break;
+ }
+ }
+ if (!schema.initialized()) {
+ return Status::NotFound("cannot find replica", tablet_id);
+ }
+ return ReplicaDumper::Dump(schema, tablet_id, proxy.get());
+}
+
+Status ListReplicas(const RunnerContext& context) {
+ string address = FindOrDie(context.required_args, kTServerAddressArg);
+ unique_ptr<TabletServerServiceProxy> proxy;
+ RETURN_NOT_OK(BuildProxy(address, tserver::TabletServer::kDefaultPort,
+ &proxy));
+
+ vector<ListTabletsResponsePB::StatusAndSchemaPB> replicas;
+ RETURN_NOT_OK(GetReplicas(proxy.get(), &replicas));
+
+ for (const auto& r : replicas) {
+ Schema schema;
+ RETURN_NOT_OK_PREPEND(
+ SchemaFromPB(r.schema(), &schema),
+ "Unable to deserialize schema from " + address);
+ PartitionSchema partition_schema;
+ RETURN_NOT_OK_PREPEND(
+ PartitionSchema::FromPB(r.partition_schema(), schema, &partition_schema),
+ "Unable to deserialize partition schema from " + address);
+
+ const TabletStatusPB& rs = r.tablet_status();
+
+ Partition partition;
+ Partition::FromPB(rs.partition(), &partition);
+
+ string state = tablet::TabletStatePB_Name(rs.state());
+ cout << "Tablet id: " << rs.tablet_id() << endl;
+ cout << "State: " << state << endl;
+ cout << "Table name: " << rs.table_name() << endl;
+ cout << "Partition: "
+ << partition_schema.PartitionDebugString(partition, schema) << endl;
+ if (rs.has_estimated_on_disk_size()) {
+ cout << "Estimated on disk size: "
+ << HumanReadableNumBytes::ToString(rs.estimated_on_disk_size()) << endl;
+ }
+ cout << "Schema: " << schema.ToString() << endl;
+ }
+
+ return Status::OK();
+}
+
+} // anonymous namespace
+
+unique_ptr<Mode> BuildRemoteReplicaMode() {
+ unique_ptr<Action> check_replicas =
+ ActionBuilder("check", &CheckReplicas)
+ .Description("Check if all replicas on a Kudu Tablet Server are running")
+ .AddRequiredParameter({ kTServerAddressArg, kTServerAddressDesc })
+ .Build();
+
+ unique_ptr<Action> delete_replica =
+ ActionBuilder("delete", &DeleteReplica)
+ .Description("Delete a replica from a Kudu Tablet Server")
+ .AddRequiredParameter({ kTServerAddressArg, kTServerAddressDesc })
+ .AddRequiredParameter({ kTabletArg, kTabletDesc })
+ .AddRequiredParameter({ kReasonArg, "Reason for deleting the replica" })
+ .Build();
+
+ unique_ptr<Action> dump_replica =
+ ActionBuilder("dump", &DumpReplica)
+ .Description("Dump the data of a replica on a Kudu Tablet Server")
+ .AddRequiredParameter({ kTServerAddressArg, kTServerAddressDesc })
+ .AddRequiredParameter({ kTabletArg, kTabletDesc })
+ .Build();
+
+ unique_ptr<Action> list =
+ ActionBuilder("list", &ListReplicas)
+ .Description("List all replicas on a Kudu Tablet Server")
+ .AddRequiredParameter({ kTServerAddressArg, kTServerAddressDesc })
+ .Build();
+
+ return ModeBuilder("remote_replica")
+ .Description("Operate on replicas on a Kudu Tablet Server")
+ .AddAction(std::move(check_replicas))
+ .AddAction(std::move(delete_replica))
+ .AddAction(std::move(dump_replica))
+ .AddAction(std::move(list))
+ .Build();
+}
+
+} // namespace tools
+} // namespace kudu
+
http://git-wip-us.apache.org/repos/asf/kudu/blob/14cd22a1/src/kudu/tools/tool_action_tablet.cc
----------------------------------------------------------------------
diff --git a/src/kudu/tools/tool_action_tablet.cc b/src/kudu/tools/tool_action_tablet.cc
index 8ed0039..86e3df7 100644
--- a/src/kudu/tools/tool_action_tablet.cc
+++ b/src/kudu/tools/tool_action_tablet.cc
@@ -30,8 +30,8 @@
#include "kudu/gutil/stl_util.h"
#include "kudu/gutil/strings/split.h"
#include "kudu/gutil/strings/substitute.h"
-#include "kudu/rpc/messenger.h"
#include "kudu/rpc/rpc_controller.h"
+#include "kudu/tools/tool_action_common.h"
#include "kudu/util/net/net_util.h"
#include "kudu/util/status.h"
#include "kudu/util/string_case.h"
@@ -46,8 +46,6 @@ using client::KuduTabletServer;
using consensus::ChangeConfigType;
using consensus::ConsensusServiceProxy;
using consensus::RaftPeerPB;
-using rpc::Messenger;
-using rpc::MessengerBuilder;
using rpc::RpcController;
using std::shared_ptr;
using std::string;
@@ -145,9 +143,8 @@ Status ChangeConfig(const RunnerContext& context, ChangeConfigType cc_type) {
leader_hp.ToString());
}
- shared_ptr<Messenger> messenger;
- RETURN_NOT_OK(MessengerBuilder("kudu").Build(&messenger));
- ConsensusServiceProxy proxy(messenger, leader_addrs[0]);
+ unique_ptr<ConsensusServiceProxy> proxy;
+ RETURN_NOT_OK(BuildProxy(leader_hp.host(), leader_hp.port(), &proxy));
consensus::ChangeConfigRequestPB req;
consensus::ChangeConfigResponsePB resp;
@@ -157,7 +154,7 @@ Status ChangeConfig(const RunnerContext& context, ChangeConfigType cc_type) {
req.set_tablet_id(tablet_id);
req.set_type(cc_type);
*req.mutable_server() = peer_pb;
- RETURN_NOT_OK(proxy.ChangeConfig(req, &resp, &rpc));
+ RETURN_NOT_OK(proxy->ChangeConfig(req, &resp, &rpc));
if (resp.has_error()) {
return StatusFromPB(resp.error().status());
}
http://git-wip-us.apache.org/repos/asf/kudu/blob/14cd22a1/src/kudu/tools/tool_action_tserver.cc
----------------------------------------------------------------------
diff --git a/src/kudu/tools/tool_action_tserver.cc b/src/kudu/tools/tool_action_tserver.cc
new file mode 100644
index 0000000..145ec1b
--- /dev/null
+++ b/src/kudu/tools/tool_action_tserver.cc
@@ -0,0 +1,98 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "kudu/tools/tool_action.h"
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include <gflags/gflags.h>
+
+#include "kudu/gutil/map-util.h"
+#include "kudu/tools/tool_action_common.h"
+#include "kudu/tserver/tablet_server.h"
+#include "kudu/util/status.h"
+
+namespace kudu {
+namespace tools {
+
+using std::string;
+using std::unique_ptr;
+
+namespace {
+
+const char* const kTServerAddressArg = "tserver_address";
+const char* const kTServerAddressDesc = "Address of a Kudu Tablet Server of "
+ "form 'hostname:port'. Port may be omitted if the Tablet Server is bound "
+ "to the default port.";
+const char* const kFlagArg = "flag";
+const char* const kValueArg = "value";
+
+Status TServerSetFlag(const RunnerContext& context) {
+ string address = FindOrDie(context.required_args, kTServerAddressArg);
+ string flag = FindOrDie(context.required_args, kFlagArg);
+ string value = FindOrDie(context.required_args, kValueArg);
+ return SetServerFlag(address, tserver::TabletServer::kDefaultPort,
+ flag, value);
+}
+
+Status TServerStatus(const RunnerContext& context) {
+ string address = FindOrDie(context.required_args, kTServerAddressArg);
+ return PrintServerStatus(address, tserver::TabletServer::kDefaultPort);
+}
+
+Status TServerTimestamp(const RunnerContext& context) {
+ string address = FindOrDie(context.required_args, kTServerAddressArg);
+ return PrintServerTimestamp(address, tserver::TabletServer::kDefaultPort);
+}
+
+} // anonymous namespace
+
+unique_ptr<Mode> BuildTServerMode() {
+ unique_ptr<Action> set_flag =
+ ActionBuilder("set_flag", &TServerSetFlag)
+ .Description("Change a gflag value on a Kudu Tablet Server")
+ .AddRequiredParameter({ kTServerAddressArg, kTServerAddressDesc })
+ .AddRequiredParameter({ kFlagArg, "Name of the gflag" })
+ .AddRequiredParameter({ kValueArg, "New value for the gflag" })
+ .AddOptionalParameter("force")
+ .Build();
+
+ unique_ptr<Action> status =
+ ActionBuilder("status", &TServerStatus)
+ .Description("Get the status of a Kudu Tablet Server")
+ .AddRequiredParameter({ kTServerAddressArg, kTServerAddressDesc })
+ .Build();
+
+ unique_ptr<Action> timestamp =
+ ActionBuilder("timestamp", &TServerTimestamp)
+ .Description("Get the current timestamp of a Kudu Tablet Server")
+ .AddRequiredParameter({ kTServerAddressArg, kTServerAddressDesc })
+ .Build();
+
+ return ModeBuilder("tserver")
+ .Description("Operate on a Kudu Tablet Server")
+ .AddAction(std::move(set_flag))
+ .AddAction(std::move(status))
+ .AddAction(std::move(timestamp))
+ .Build();
+}
+
+} // namespace tools
+} // namespace kudu
+
http://git-wip-us.apache.org/repos/asf/kudu/blob/14cd22a1/src/kudu/tools/tool_main.cc
----------------------------------------------------------------------
diff --git a/src/kudu/tools/tool_main.cc b/src/kudu/tools/tool_main.cc
index 3c8bb63..caf3bde 100644
--- a/src/kudu/tools/tool_main.cc
+++ b/src/kudu/tools/tool_main.cc
@@ -114,9 +114,12 @@ int RunTool(int argc, char** argv, bool show_help) {
.AddMode(BuildClusterMode())
.AddMode(BuildFsMode())
.AddMode(BuildLocalReplicaMode())
+ .AddMode(BuildMasterMode())
.AddMode(BuildPbcMode())
+ .AddMode(BuildRemoteReplicaMode())
.AddMode(BuildTableMode())
.AddMode(BuildTabletMode())
+ .AddMode(BuildTServerMode())
.AddMode(BuildWalMode())
.Build();
http://git-wip-us.apache.org/repos/asf/kudu/blob/14cd22a1/src/kudu/tools/ts-cli.cc
----------------------------------------------------------------------
diff --git a/src/kudu/tools/ts-cli.cc b/src/kudu/tools/ts-cli.cc
deleted file mode 100644
index f34adbf..0000000
--- a/src/kudu/tools/ts-cli.cc
+++ /dev/null
@@ -1,494 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-//
-// Tool to query tablet server operational data
-
-#include <gflags/gflags.h>
-#include <glog/logging.h>
-#include <iostream>
-#include <memory>
-#include <strstream>
-
-#include "kudu/client/row_result.h"
-#include "kudu/client/scanner-internal.h"
-#include "kudu/common/partition.h"
-#include "kudu/common/schema.h"
-#include "kudu/common/wire_protocol.h"
-#include "kudu/gutil/strings/human_readable.h"
-#include "kudu/server/server_base.proxy.h"
-#include "kudu/tserver/tserver.pb.h"
-#include "kudu/tserver/tserver_admin.proxy.h"
-#include "kudu/tserver/tserver_service.proxy.h"
-#include "kudu/tserver/tablet_server.h"
-#include "kudu/util/env.h"
-#include "kudu/util/faststring.h"
-#include "kudu/util/flags.h"
-#include "kudu/util/logging.h"
-#include "kudu/util/net/net_util.h"
-#include "kudu/util/net/sockaddr.h"
-#include "kudu/rpc/messenger.h"
-#include "kudu/rpc/rpc_controller.h"
-
-using kudu::client::KuduRowResult;
-using kudu::HostPort;
-using kudu::rpc::Messenger;
-using kudu::rpc::MessengerBuilder;
-using kudu::rpc::RpcController;
-using kudu::server::ServerStatusPB;
-using kudu::Sockaddr;
-using kudu::client::KuduScanBatch;
-using kudu::tablet::TabletStatusPB;
-using kudu::tserver::DeleteTabletRequestPB;
-using kudu::tserver::DeleteTabletResponsePB;
-using kudu::tserver::ListTabletsRequestPB;
-using kudu::tserver::ListTabletsResponsePB;
-using kudu::tserver::NewScanRequestPB;
-using kudu::tserver::ScanRequestPB;
-using kudu::tserver::ScanResponsePB;
-using kudu::tserver::TabletServerAdminServiceProxy;
-using kudu::tserver::TabletServerServiceProxy;
-using std::ostringstream;
-using std::shared_ptr;
-using std::string;
-using std::vector;
-
-const char* const kListTabletsOp = "list_tablets";
-const char* const kAreTabletsRunningOp = "are_tablets_running";
-const char* const kSetFlagOp = "set_flag";
-const char* const kDumpTabletOp = "dump_tablet";
-const char* const kDeleteTabletOp = "delete_tablet";
-const char* const kCurrentTimestamp = "current_timestamp";
-const char* const kStatus = "status";
-
-DEFINE_string(server_address, "localhost",
- "Address of server to run against");
-DEFINE_int64(timeout_ms, 1000 * 60, "RPC timeout in milliseconds");
-
-DEFINE_bool(force, false, "If true, allows the set_flag command to set a flag "
- "which is not explicitly marked as runtime-settable. Such flag changes may be "
- "simply ignored on the server, or may cause the server to crash.");
-
-// Check that the value of argc matches what's expected, otherwise return a
-// non-zero exit code. Should be used in main().
-#define CHECK_ARGC_OR_RETURN_WITH_USAGE(op, expected) \
- do { \
- const string& _op = (op); \
- const int _expected = (expected); \
- if (argc != _expected) { \
- /* We substract 2 from _expected because we don't want to count argv[0] or [1]. */ \
- std::cerr << "Invalid number of arguments for " << _op \
- << ": expected " << (_expected - 2) << " arguments" << std::endl; \
- google::ShowUsageWithFlagsRestrict(argv[0], __FILE__); \
- return 2; \
- } \
- } while (0);
-
-// Invoke 'to_call' and check its result. If it failed, print 'to_prepend' and
-// the error to cerr and return a non-zero exit code. Should be used in main().
-#define RETURN_NOT_OK_PREPEND_FROM_MAIN(to_call, to_prepend) \
- do { \
- ::kudu::Status s = (to_call); \
- if (!s.ok()) { \
- std::cerr << (to_prepend) << ": " << s.ToString() << std::endl; \
- return 1; \
- } \
- } while (0);
-
-namespace kudu {
-namespace tools {
-
-typedef ListTabletsResponsePB::StatusAndSchemaPB StatusAndSchemaPB;
-
-class TsAdminClient {
- public:
- // Creates an admin client for host/port combination e.g.,
- // "localhost" or "127.0.0.1:7050".
- TsAdminClient(std::string addr, int64_t timeout_millis);
-
- // Initialized the client and connects to the specified tablet
- // server.
- Status Init();
-
- // Sets 'tablets' a list of status information for all tablets on a
- // given tablet server.
- Status ListTablets(std::vector<StatusAndSchemaPB>* tablets);
-
-
- // Sets the gflag 'flag' to 'val' on the remote server via RPC.
- // If 'force' is true, allows setting flags even if they're not marked as
- // safe to change at runtime.
- Status SetFlag(const string& flag, const string& val,
- bool force);
-
- // Get the schema for the given tablet.
- Status GetTabletSchema(const std::string& tablet_id, SchemaPB* schema);
-
- // Dump the contents of the given tablet, in key order, to the console.
- Status DumpTablet(const std::string& tablet_id);
-
- // Delete a tablet replica from the specified peer.
- // The 'reason' string is passed to the tablet server, used for logging.
- Status DeleteTablet(const std::string& tablet_id,
- const std::string& reason);
-
- // Sets timestamp to the value of the tablet server's current timestamp.
- Status CurrentTimestamp(uint64_t* timestamp);
-
- // Get the server status
- Status GetStatus(ServerStatusPB* pb);
- private:
- std::string addr_;
- vector<Sockaddr> addrs_;
- MonoDelta timeout_;
- bool initted_;
- shared_ptr<server::GenericServiceProxy> generic_proxy_;
- gscoped_ptr<tserver::TabletServerServiceProxy> ts_proxy_;
- gscoped_ptr<tserver::TabletServerAdminServiceProxy> ts_admin_proxy_;
- shared_ptr<rpc::Messenger> messenger_;
-
- DISALLOW_COPY_AND_ASSIGN(TsAdminClient);
-};
-
-TsAdminClient::TsAdminClient(string addr, int64_t timeout_millis)
- : addr_(std::move(addr)),
- timeout_(MonoDelta::FromMilliseconds(timeout_millis)),
- initted_(false) {}
-
-Status TsAdminClient::Init() {
- CHECK(!initted_);
-
- HostPort host_port;
- RETURN_NOT_OK(host_port.ParseString(addr_, tserver::TabletServer::kDefaultPort));
- MessengerBuilder builder("ts-cli");
- RETURN_NOT_OK(builder.Build(&messenger_));
-
- RETURN_NOT_OK(host_port.ResolveAddresses(&addrs_))
-
- generic_proxy_.reset(new server::GenericServiceProxy(messenger_, addrs_[0]));
- ts_proxy_.reset(new TabletServerServiceProxy(messenger_, addrs_[0]));
- ts_admin_proxy_.reset(new TabletServerAdminServiceProxy(messenger_, addrs_[0]));
-
- initted_ = true;
-
- VLOG(1) << "Connected to " << addr_;
-
- return Status::OK();
-}
-
-Status TsAdminClient::ListTablets(vector<StatusAndSchemaPB>* tablets) {
- CHECK(initted_);
-
- ListTabletsRequestPB req;
- ListTabletsResponsePB resp;
- RpcController rpc;
-
- rpc.set_timeout(timeout_);
- RETURN_NOT_OK(ts_proxy_->ListTablets(req, &resp, &rpc));
- if (resp.has_error()) {
- return StatusFromPB(resp.error().status());
- }
-
- tablets->assign(resp.status_and_schema().begin(), resp.status_and_schema().end());
-
- return Status::OK();
-}
-
-Status TsAdminClient::SetFlag(const string& flag, const string& val,
- bool force) {
- server::SetFlagRequestPB req;
- server::SetFlagResponsePB resp;
- RpcController rpc;
-
- rpc.set_timeout(timeout_);
- req.set_flag(flag);
- req.set_value(val);
- req.set_force(force);
-
- RETURN_NOT_OK(generic_proxy_->SetFlag(req, &resp, &rpc));
- switch (resp.result()) {
- case server::SetFlagResponsePB::SUCCESS:
- return Status::OK();
- case server::SetFlagResponsePB::NOT_SAFE:
- return Status::RemoteError(resp.msg() + " (use --force flag to allow anyway)");
- default:
- return Status::RemoteError(resp.ShortDebugString());
- }
-}
-
-Status TsAdminClient::GetTabletSchema(const std::string& tablet_id,
- SchemaPB* schema) {
- VLOG(1) << "Fetching schema for tablet " << tablet_id;
- vector<StatusAndSchemaPB> tablets;
- RETURN_NOT_OK(ListTablets(&tablets));
- for (const StatusAndSchemaPB& pair : tablets) {
- if (pair.tablet_status().tablet_id() == tablet_id) {
- *schema = pair.schema();
- return Status::OK();
- }
- }
- return Status::NotFound("Cannot find tablet", tablet_id);
-}
-
-Status TsAdminClient::DumpTablet(const std::string& tablet_id) {
- SchemaPB schema_pb;
- RETURN_NOT_OK(GetTabletSchema(tablet_id, &schema_pb));
- Schema schema;
- RETURN_NOT_OK(SchemaFromPB(schema_pb, &schema));
- kudu::client::KuduSchema client_schema(schema);
-
- ScanRequestPB req;
- ScanResponsePB resp;
-
- NewScanRequestPB* new_req = req.mutable_new_scan_request();
- RETURN_NOT_OK(SchemaToColumnPBs(
- schema, new_req->mutable_projected_columns(),
- SCHEMA_PB_WITHOUT_IDS | SCHEMA_PB_WITHOUT_STORAGE_ATTRIBUTES));
- new_req->set_tablet_id(tablet_id);
- new_req->set_cache_blocks(false);
- new_req->set_order_mode(ORDERED);
- new_req->set_read_mode(READ_AT_SNAPSHOT);
-
- do {
- RpcController rpc;
- rpc.set_timeout(timeout_);
- RETURN_NOT_OK_PREPEND(ts_proxy_->Scan(req, &resp, &rpc),
- "Scan() failed");
-
- if (resp.has_error()) {
- return Status::IOError("Failed to read: ", resp.error().ShortDebugString());
- }
-
- // The first response has a scanner ID. We use this for all subsequent
- // responses.
- if (resp.has_scanner_id()) {
- req.set_scanner_id(resp.scanner_id());
- req.clear_new_scan_request();
- }
- req.set_call_seq_id(req.call_seq_id() + 1);
-
- // Nothing to process from this scan result.
- if (!resp.has_data()) {
- continue;
- }
-
- KuduScanBatch::Data results;
- RETURN_NOT_OK(results.Reset(&rpc,
- &schema,
- &client_schema,
- make_gscoped_ptr(resp.release_data())));
- vector<KuduRowResult> rows;
- results.ExtractRows(&rows);
- for (const KuduRowResult& r : rows) {
- std::cout << r.ToString() << std::endl;
- }
- } while (resp.has_more_results());
- return Status::OK();
-}
-
-Status TsAdminClient::DeleteTablet(const string& tablet_id,
- const string& reason) {
- ServerStatusPB status_pb;
- RETURN_NOT_OK(GetStatus(&status_pb));
-
- DeleteTabletRequestPB req;
- DeleteTabletResponsePB resp;
- RpcController rpc;
-
- req.set_tablet_id(tablet_id);
- req.set_dest_uuid(status_pb.node_instance().permanent_uuid());
- req.set_reason(reason);
- req.set_delete_type(tablet::TABLET_DATA_TOMBSTONED);
- rpc.set_timeout(timeout_);
- RETURN_NOT_OK_PREPEND(ts_admin_proxy_->DeleteTablet(req, &resp, &rpc),
- "DeleteTablet() failed");
-
- if (resp.has_error()) {
- return Status::IOError("Failed to delete tablet: ",
- resp.error().ShortDebugString());
- }
- return Status::OK();
-}
-
-Status TsAdminClient::CurrentTimestamp(uint64_t* timestamp) {
- server::ServerClockRequestPB req;
- server::ServerClockResponsePB resp;
- RpcController rpc;
- rpc.set_timeout(timeout_);
- RETURN_NOT_OK(generic_proxy_->ServerClock(req, &resp, &rpc));
- CHECK(resp.has_timestamp()) << resp.DebugString();
- *timestamp = resp.timestamp();
- return Status::OK();
-}
-
-Status TsAdminClient::GetStatus(ServerStatusPB* pb) {
- server::GetStatusRequestPB req;
- server::GetStatusResponsePB resp;
- RpcController rpc;
- rpc.set_timeout(timeout_);
- RETURN_NOT_OK(generic_proxy_->GetStatus(req, &resp, &rpc));
- CHECK(resp.has_status()) << resp.DebugString();
- pb->Swap(resp.mutable_status());
- return Status::OK();
-}
-
-namespace {
-
-void SetUsage(const char* argv0) {
- ostringstream str;
-
- str << argv0 << " [--server_address=<addr>] <operation> <flags>\n"
- << "<operation> must be one of:\n"
- << " " << kListTabletsOp << "\n"
- << " " << kAreTabletsRunningOp << "\n"
- << " " << kSetFlagOp << " [-force] <flag> <value>\n"
- << " " << kDumpTabletOp << " <tablet_id>\n"
- << " " << kDeleteTabletOp << " <tablet_id> <reason string>\n"
- << " " << kCurrentTimestamp << "\n"
- << " " << kStatus;
- google::SetUsageMessage(str.str());
-}
-
-string GetOp(int argc, char** argv) {
- if (argc < 2) {
- google::ShowUsageWithFlagsRestrict(argv[0], __FILE__);
- exit(1);
- }
-
- return argv[1];
-}
-
-} // anonymous namespace
-
-static int TsCliMain(int argc, char** argv) {
- FLAGS_logtostderr = 1;
- SetUsage(argv[0]);
- ParseCommandLineFlags(&argc, &argv, true);
- InitGoogleLoggingSafe(argv[0]);
- const string addr = FLAGS_server_address;
-
- string op = GetOp(argc, argv);
-
- TsAdminClient client(addr, FLAGS_timeout_ms);
-
- RETURN_NOT_OK_PREPEND_FROM_MAIN(client.Init(),
- "Unable to establish connection to " + addr);
-
- // TODO add other operations here...
- if (op == kListTabletsOp) {
- CHECK_ARGC_OR_RETURN_WITH_USAGE(op, 2);
-
- vector<StatusAndSchemaPB> tablets;
- RETURN_NOT_OK_PREPEND_FROM_MAIN(client.ListTablets(&tablets),
- "Unable to list tablets on " + addr);
- for (const StatusAndSchemaPB& status_and_schema : tablets) {
- Schema schema;
- RETURN_NOT_OK_PREPEND_FROM_MAIN(SchemaFromPB(status_and_schema.schema(), &schema),
- "Unable to deserialize schema from " + addr);
- PartitionSchema partition_schema;
- RETURN_NOT_OK_PREPEND_FROM_MAIN(PartitionSchema::FromPB(status_and_schema.partition_schema(),
- schema, &partition_schema),
- "Unable to deserialize partition schema from " + addr);
-
-
- TabletStatusPB ts = status_and_schema.tablet_status();
-
- Partition partition;
- Partition::FromPB(ts.partition(), &partition);
-
- string state = tablet::TabletStatePB_Name(ts.state());
- std::cout << "Tablet id: " << ts.tablet_id() << std::endl;
- std::cout << "State: " << state << std::endl;
- std::cout << "Table name: " << ts.table_name() << std::endl;
- std::cout << "Partition: " << partition_schema.PartitionDebugString(partition, schema)
- << std::endl;
- if (ts.has_estimated_on_disk_size()) {
- std::cout << "Estimated on disk size: " <<
- HumanReadableNumBytes::ToString(ts.estimated_on_disk_size()) << std::endl;
- }
- std::cout << "Schema: " << schema.ToString() << std::endl;
- }
- } else if (op == kAreTabletsRunningOp) {
- CHECK_ARGC_OR_RETURN_WITH_USAGE(op, 2);
-
- vector<StatusAndSchemaPB> tablets;
- RETURN_NOT_OK_PREPEND_FROM_MAIN(client.ListTablets(&tablets),
- "Unable to list tablets on " + addr);
- bool all_running = true;
- for (const StatusAndSchemaPB& status_and_schema : tablets) {
- TabletStatusPB ts = status_and_schema.tablet_status();
- if (ts.state() != tablet::RUNNING) {
- std::cout << "Tablet id: " << ts.tablet_id() << " is "
- << tablet::TabletStatePB_Name(ts.state()) << std::endl;
- all_running = false;
- }
- }
-
- if (all_running) {
- std::cout << "All tablets are running" << std::endl;
- } else {
- std::cout << "Not all tablets are running" << std::endl;
- return 1;
- }
- } else if (op == kSetFlagOp) {
- CHECK_ARGC_OR_RETURN_WITH_USAGE(op, 4);
-
- RETURN_NOT_OK_PREPEND_FROM_MAIN(client.SetFlag(argv[2], argv[3], FLAGS_force),
- "Unable to set flag");
-
- } else if (op == kDumpTabletOp) {
- CHECK_ARGC_OR_RETURN_WITH_USAGE(op, 3);
-
- string tablet_id = argv[2];
- RETURN_NOT_OK_PREPEND_FROM_MAIN(client.DumpTablet(tablet_id),
- "Unable to dump tablet");
- } else if (op == kDeleteTabletOp) {
- CHECK_ARGC_OR_RETURN_WITH_USAGE(op, 4);
-
- string tablet_id = argv[2];
- string reason = argv[3];
-
- RETURN_NOT_OK_PREPEND_FROM_MAIN(client.DeleteTablet(tablet_id, reason),
- "Unable to delete tablet");
- } else if (op == kCurrentTimestamp) {
- CHECK_ARGC_OR_RETURN_WITH_USAGE(op, 2);
-
- uint64_t timestamp;
- RETURN_NOT_OK_PREPEND_FROM_MAIN(client.CurrentTimestamp(×tamp),
- "Unable to get timestamp");
- std::cout << timestamp << std::endl;
- } else if (op == kStatus) {
- CHECK_ARGC_OR_RETURN_WITH_USAGE(op, 2);
-
- ServerStatusPB status;
- RETURN_NOT_OK_PREPEND_FROM_MAIN(client.GetStatus(&status),
- "Unable to get status");
- std::cout << status.DebugString() << std::endl;
- } else {
- std::cerr << "Invalid operation: " << op << std::endl;
- google::ShowUsageWithFlagsRestrict(argv[0], __FILE__);
- return 2;
- }
-
- return 0;
-}
-
-} // namespace tools
-} // namespace kudu
-
-int main(int argc, char** argv) {
- return kudu::tools::TsCliMain(argc, argv);
-}