You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kudu.apache.org by mp...@apache.org on 2017/07/11 19:32:17 UTC
kudu git commit: mini_cluster: support multiple data dirs
Repository: kudu
Updated Branches:
refs/heads/master 5b18be1a7 -> af39a2aa0
mini_cluster: support multiple data dirs
This patch gives MiniTabletServers and MiniMasters the ability to
start with multiple data dirs. A number of dirs is specified and
directory names are generated for the specified number. A WAL dir will
be generated with an appropriate suffix.
The setup for MiniMaster is also changed to more closely resemble
MiniTabletServer. MasterOptions are generated in the constructor and a
single Start() call will create the Master.
The original directory structure is kept as a default.
E.g. if the number of data dirs is 3, the following directories will
be generated for tservers (a similar one is created for masters):
/test_dir/test_tserver/wal
/test_dir/test_tserver/data-0
/test_dir/test_tserver/data-1
/test_dir/test_tserver/data-2
Original:
/test_dir/test_tserver
Tests are added to the new mini_tablet_server-test and mini_master-test
to exercise this.
Change-Id: I52c9352f1a3565d58149cf2c63d37246c6b39c23
Reviewed-on: http://gerrit.cloudera.org:8080/7211
Reviewed-by: Mike Percy <mp...@apache.org>
Tested-by: Mike Percy <mp...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/kudu/repo
Commit: http://git-wip-us.apache.org/repos/asf/kudu/commit/af39a2aa
Tree: http://git-wip-us.apache.org/repos/asf/kudu/tree/af39a2aa
Diff: http://git-wip-us.apache.org/repos/asf/kudu/diff/af39a2aa
Branch: refs/heads/master
Commit: af39a2aa0d1506856d763033b13675d347a7cb15
Parents: 5b18be1
Author: Andrew Wong <aw...@cloudera.com>
Authored: Fri Jun 16 09:25:37 2017 -0700
Committer: Mike Percy <mp...@apache.org>
Committed: Tue Jul 11 19:31:58 2017 +0000
----------------------------------------------------------------------
.../integration-tests/internal_mini_cluster.cc | 69 ++++++++-------
.../integration-tests/internal_mini_cluster.h | 16 ++--
.../master_replication-itest.cc | 3 +-
src/kudu/master/CMakeLists.txt | 1 +
src/kudu/master/master-test.cc | 1 +
src/kudu/master/mini_master-test.cc | 47 ++++++++++
src/kudu/master/mini_master.cc | 93 ++++++++++----------
src/kudu/master/mini_master.h | 28 ++----
src/kudu/tserver/CMakeLists.txt | 1 +
src/kudu/tserver/mini_tablet_server-test.cc | 48 ++++++++++
src/kudu/tserver/mini_tablet_server.cc | 27 ++++--
src/kudu/tserver/mini_tablet_server.h | 5 +-
src/kudu/tserver/tablet_copy-test-base.h | 2 +-
src/kudu/tserver/tablet_server-stress-test.cc | 2 +-
src/kudu/tserver/tablet_server-test-base.h | 10 ++-
src/kudu/tserver/tablet_server-test.cc | 2 +-
16 files changed, 233 insertions(+), 122 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/kudu/blob/af39a2aa/src/kudu/integration-tests/internal_mini_cluster.cc
----------------------------------------------------------------------
diff --git a/src/kudu/integration-tests/internal_mini_cluster.cc b/src/kudu/integration-tests/internal_mini_cluster.cc
index 64c5d06..ec8ff70 100644
--- a/src/kudu/integration-tests/internal_mini_cluster.cc
+++ b/src/kudu/integration-tests/internal_mini_cluster.cc
@@ -51,18 +51,17 @@ using tserver::TabletServer;
InternalMiniClusterOptions::InternalMiniClusterOptions()
: num_masters(1),
num_tablet_servers(1),
+ num_data_dirs(1),
bind_mode(MiniCluster::kDefaultBindMode) {
}
-InternalMiniCluster::InternalMiniCluster(Env* env, const InternalMiniClusterOptions& options)
+InternalMiniCluster::InternalMiniCluster(Env* env, InternalMiniClusterOptions options)
: env_(env),
- fs_root_(!options.data_root.empty() ? options.data_root :
- JoinPathSegments(GetTestDataDirectory(), "minicluster-data")),
- num_masters_initial_(options.num_masters),
- num_ts_initial_(options.num_tablet_servers),
- master_rpc_ports_(options.master_rpc_ports),
- tserver_rpc_ports_(options.tserver_rpc_ports),
+ opts_(std::move(options)),
running_(false) {
+ if (opts_.data_root.empty()) {
+ opts_.data_root = JoinPathSegments(GetTestDataDirectory(), "minicluster-data");
+ }
}
InternalMiniCluster::~InternalMiniCluster() {
@@ -70,31 +69,31 @@ InternalMiniCluster::~InternalMiniCluster() {
}
Status InternalMiniCluster::Start() {
- CHECK(!fs_root_.empty()) << "No Fs root was provided";
+ CHECK(!opts_.data_root.empty()) << "No Fs root was provided";
CHECK(!running_);
- if (num_masters_initial_ > 1) {
- CHECK_GE(master_rpc_ports_.size(), num_masters_initial_);
+ if (opts_.num_masters > 1) {
+ CHECK_GE(opts_.master_rpc_ports.size(), opts_.num_masters);
}
- if (!env_->FileExists(fs_root_)) {
- RETURN_NOT_OK(env_->CreateDir(fs_root_));
+ if (!env_->FileExists(opts_.data_root)) {
+ RETURN_NOT_OK(env_->CreateDir(opts_.data_root));
}
// start the masters
- if (num_masters_initial_ > 1) {
+ if (opts_.num_masters > 1) {
RETURN_NOT_OK_PREPEND(StartDistributedMasters(),
"Couldn't start distributed masters");
} else {
RETURN_NOT_OK_PREPEND(StartSingleMaster(), "Couldn't start the single master");
}
- for (int i = 0; i < num_ts_initial_; i++) {
+ for (int i = 0; i < opts_.num_tablet_servers; i++) {
RETURN_NOT_OK_PREPEND(AddTabletServer(),
Substitute("Error adding TS $0", i));
}
- RETURN_NOT_OK_PREPEND(WaitForTabletServerCount(num_ts_initial_),
+ RETURN_NOT_OK_PREPEND(WaitForTabletServerCount(opts_.num_tablet_servers),
"Waiting for tablet servers to start");
RETURN_NOT_OK_PREPEND(rpc::MessengerBuilder("minicluster-messenger")
@@ -108,17 +107,18 @@ Status InternalMiniCluster::Start() {
}
Status InternalMiniCluster::StartDistributedMasters() {
- CHECK_GE(master_rpc_ports_.size(), num_masters_initial_);
- CHECK_GT(master_rpc_ports_.size(), 1);
+ CHECK_GT(opts_.num_data_dirs, 0);
+ CHECK_GE(opts_.master_rpc_ports.size(), opts_.num_masters);
+ CHECK_GT(opts_.master_rpc_ports.size(), 1);
vector<HostPort> master_rpc_addrs = this->master_rpc_addrs();
LOG(INFO) << "Creating distributed mini masters. Addrs: "
<< HostPort::ToCommaSeparatedString(master_rpc_addrs);
- for (int i = 0; i < num_masters_initial_; i++) {
+ for (int i = 0; i < opts_.num_masters; i++) {
shared_ptr<MiniMaster> mini_master(new MiniMaster(GetMasterFsRoot(i), master_rpc_addrs[i]));
- RETURN_NOT_OK_PREPEND(mini_master->StartDistributedMaster(master_rpc_addrs),
- Substitute("Couldn't start follower $0", i));
+ mini_master->SetMasterAddresses(master_rpc_addrs);
+ RETURN_NOT_OK_PREPEND(mini_master->Start(), Substitute("Couldn't start follower $0", i));
VLOG(1) << "Started MiniMaster with UUID " << mini_master->permanent_uuid()
<< " at index " << i;
mini_masters_.push_back(std::move(mini_master));
@@ -144,17 +144,18 @@ Status InternalMiniCluster::StartSync() {
}
Status InternalMiniCluster::StartSingleMaster() {
- CHECK_EQ(1, num_masters_initial_);
- CHECK_LE(master_rpc_ports_.size(), 1);
+ CHECK_GT(opts_.num_data_dirs, 0);
+ CHECK_EQ(1, opts_.num_masters);
+ CHECK_LE(opts_.master_rpc_ports.size(), 1);
uint16_t master_rpc_port = 0;
- if (master_rpc_ports_.size() == 1) {
- master_rpc_port = master_rpc_ports_[0];
+ if (opts_.master_rpc_ports.size() == 1) {
+ master_rpc_port = opts_.master_rpc_ports[0];
}
// start the master (we need the port to set on the servers).
string bind_ip = GetBindIpForDaemon(MiniCluster::MASTER, /*index=*/ 0, opts_.bind_mode);
- shared_ptr<MiniMaster> mini_master(
- new MiniMaster(GetMasterFsRoot(0), HostPort(std::move(bind_ip), master_rpc_port)));
+ shared_ptr<MiniMaster> mini_master(new MiniMaster(GetMasterFsRoot(0),
+ HostPort(std::move(bind_ip), master_rpc_port), opts_.num_data_dirs));
RETURN_NOT_OK_PREPEND(mini_master->Start(), "Couldn't start master");
RETURN_NOT_OK(mini_master->master()->WaitUntilCatalogManagerIsLeaderAndReadyForTests(
MonoDelta::FromSeconds(kMasterStartupWaitTimeSeconds)));
@@ -169,13 +170,13 @@ Status InternalMiniCluster::AddTabletServer() {
int new_idx = mini_tablet_servers_.size();
uint16_t ts_rpc_port = 0;
- if (tserver_rpc_ports_.size() > new_idx) {
- ts_rpc_port = tserver_rpc_ports_[new_idx];
+ if (opts_.tserver_rpc_ports.size() > new_idx) {
+ ts_rpc_port = opts_.tserver_rpc_ports[new_idx];
}
string bind_ip = GetBindIpForDaemon(MiniCluster::TSERVER, new_idx, opts_.bind_mode);
- gscoped_ptr<MiniTabletServer> tablet_server(
- new MiniTabletServer(GetTabletServerFsRoot(new_idx), HostPort(bind_ip, ts_rpc_port)));
+ gscoped_ptr<MiniTabletServer> tablet_server(new MiniTabletServer(GetTabletServerFsRoot(new_idx),
+ HostPort(bind_ip, ts_rpc_port), opts_.num_data_dirs));
// set the master addresses
tablet_server->options()->master_addresses.clear();
@@ -217,20 +218,20 @@ MiniTabletServer* InternalMiniCluster::mini_tablet_server(int idx) const {
vector<HostPort> InternalMiniCluster::master_rpc_addrs() const {
vector<HostPort> master_rpc_addrs;
- for (int i = 0; i < master_rpc_ports_.size(); i++) {
+ for (int i = 0; i < opts_.master_rpc_ports.size(); i++) {
master_rpc_addrs.emplace_back(
GetBindIpForDaemon(MiniCluster::MASTER, i, opts_.bind_mode),
- master_rpc_ports_[i]);
+ opts_.master_rpc_ports[i]);
}
return master_rpc_addrs;
}
string InternalMiniCluster::GetMasterFsRoot(int idx) const {
- return JoinPathSegments(fs_root_, Substitute("master-$0-root", idx));
+ return JoinPathSegments(opts_.data_root, Substitute("master-$0-root", idx));
}
string InternalMiniCluster::GetTabletServerFsRoot(int idx) const {
- return JoinPathSegments(fs_root_, Substitute("ts-$0-root", idx));
+ return JoinPathSegments(opts_.data_root, Substitute("ts-$0-root", idx));
}
Status InternalMiniCluster::WaitForTabletServerCount(int count) const {
http://git-wip-us.apache.org/repos/asf/kudu/blob/af39a2aa/src/kudu/integration-tests/internal_mini_cluster.h
----------------------------------------------------------------------
diff --git a/src/kudu/integration-tests/internal_mini_cluster.h b/src/kudu/integration-tests/internal_mini_cluster.h
index ec11fbc..29d655c 100644
--- a/src/kudu/integration-tests/internal_mini_cluster.h
+++ b/src/kudu/integration-tests/internal_mini_cluster.h
@@ -54,6 +54,10 @@ struct InternalMiniClusterOptions {
// Default: 1
int num_tablet_servers;
+ // Number of data dirs for each daemon.
+ // Default: 1 (this will place the wals in the same dir)
+ int num_data_dirs;
+
// Directory in which to store data.
// Default: "", which auto-generates a unique path for this cluster.
// The default may only be used from a gtest unit test.
@@ -79,7 +83,7 @@ struct InternalMiniClusterOptions {
// number of MiniTabletServers for use in tests.
class InternalMiniCluster : public MiniCluster {
public:
- InternalMiniCluster(Env* env, const InternalMiniClusterOptions& options);
+ InternalMiniCluster(Env* env, InternalMiniClusterOptions options);
virtual ~InternalMiniCluster();
// Start a cluster with a Master and 'num_tablet_servers' TabletServers.
@@ -134,7 +138,7 @@ class InternalMiniCluster : public MiniCluster {
}
std::vector<uint16_t> master_rpc_ports() const override {
- return master_rpc_ports_;
+ return opts_.master_rpc_ports;
}
std::vector<HostPort> master_rpc_addrs() const override;
@@ -188,15 +192,9 @@ class InternalMiniCluster : public MiniCluster {
kMasterStartupWaitTimeSeconds = 30,
};
- const InternalMiniClusterOptions opts_;
-
Env* const env_;
- const std::string fs_root_;
- const int num_masters_initial_;
- const int num_ts_initial_;
- const std::vector<uint16_t> master_rpc_ports_;
- const std::vector<uint16_t> tserver_rpc_ports_;
+ InternalMiniClusterOptions opts_;
bool running_;
http://git-wip-us.apache.org/repos/asf/kudu/blob/af39a2aa/src/kudu/integration-tests/master_replication-itest.cc
----------------------------------------------------------------------
diff --git a/src/kudu/integration-tests/master_replication-itest.cc b/src/kudu/integration-tests/master_replication-itest.cc
index 86f0616..0f3e22e 100644
--- a/src/kudu/integration-tests/master_replication-itest.cc
+++ b/src/kudu/integration-tests/master_replication-itest.cc
@@ -261,7 +261,8 @@ TEST_F(MasterReplicationTest, TestMasterPeerSetsDontMatch) {
cluster_->mini_master(0)->Shutdown();
vector<HostPort> master_rpc_addrs = cluster_->master_rpc_addrs();
master_rpc_addrs.emplace_back("127.0.0.1", 55555);
- ASSERT_OK(cluster_->mini_master(0)->StartDistributedMaster(master_rpc_addrs));
+ cluster_->mini_master(0)->SetMasterAddresses(master_rpc_addrs);
+ ASSERT_OK(cluster_->mini_master(0)->Start());
Status s = cluster_->mini_master(0)->WaitForCatalogManagerInit();
SCOPED_TRACE(s.ToString());
ASSERT_TRUE(s.IsInvalidArgument());
http://git-wip-us.apache.org/repos/asf/kudu/blob/af39a2aa/src/kudu/master/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/src/kudu/master/CMakeLists.txt b/src/kudu/master/CMakeLists.txt
index 029e5c1..ed72f58 100644
--- a/src/kudu/master/CMakeLists.txt
+++ b/src/kudu/master/CMakeLists.txt
@@ -72,6 +72,7 @@ set(KUDU_TEST_LINK_LIBS
ADD_KUDU_TEST(catalog_manager-test)
ADD_KUDU_TEST(master-test RESOURCE_LOCK "master-web-port")
+ADD_KUDU_TEST(mini_master-test RESOURCE_LOCK "master-web-port")
ADD_KUDU_TEST(sys_catalog-test RESOURCE_LOCK "master-web-port")
# Actual master executable
http://git-wip-us.apache.org/repos/asf/kudu/blob/af39a2aa/src/kudu/master/master-test.cc
----------------------------------------------------------------------
diff --git a/src/kudu/master/master-test.cc b/src/kudu/master/master-test.cc
index 9a6324f..a3585f1 100644
--- a/src/kudu/master/master-test.cc
+++ b/src/kudu/master/master-test.cc
@@ -40,6 +40,7 @@
#include "kudu/security/token_verifier.h"
#include "kudu/server/rpc_server.h"
#include "kudu/util/curl_util.h"
+#include "kudu/util/path_util.h"
#include "kudu/util/pb_util.h"
#include "kudu/util/status.h"
#include "kudu/util/test_util.h"
http://git-wip-us.apache.org/repos/asf/kudu/blob/af39a2aa/src/kudu/master/mini_master-test.cc
----------------------------------------------------------------------
diff --git a/src/kudu/master/mini_master-test.cc b/src/kudu/master/mini_master-test.cc
new file mode 100644
index 0000000..4cc708c
--- /dev/null
+++ b/src/kudu/master/mini_master-test.cc
@@ -0,0 +1,47 @@
+// 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 <gtest/gtest.h>
+
+#include "kudu/fs/fs_manager.h"
+#include "kudu/master/master.h"
+#include "kudu/master/mini_master.h"
+#include "kudu/util/path_util.h"
+#include "kudu/util/test_util.h"
+
+namespace kudu {
+namespace master {
+
+using std::unique_ptr;
+
+class MiniMasterTest : public KuduTest {};
+
+TEST_F(MiniMasterTest, TestMultiDirMaster) {
+ // Specifying the number of data directories will create subdirectories under the test root.
+ unique_ptr<MiniMaster> mini_master;
+ FsManager* fs_manager;
+
+ int kNumDataDirs = 3;
+ mini_master.reset(new MiniMaster(GetTestPath("Master"), HostPort("127.0.0.1", 0), kNumDataDirs));
+ ASSERT_OK(mini_master->Start());
+ fs_manager = mini_master->master()->fs_manager();
+ ASSERT_STR_CONTAINS(DirName(fs_manager->GetWalsRootDir()), "wal");
+ ASSERT_EQ(kNumDataDirs, fs_manager->GetDataRootDirs().size());
+}
+
+} // namespace master
+} // namespace kudu
http://git-wip-us.apache.org/repos/asf/kudu/blob/af39a2aa/src/kudu/master/mini_master.cc
----------------------------------------------------------------------
diff --git a/src/kudu/master/mini_master.cc b/src/kudu/master/mini_master.cc
index f8d1328..7a64f1d 100644
--- a/src/kudu/master/mini_master.cc
+++ b/src/kudu/master/mini_master.cc
@@ -1,3 +1,4 @@
+// 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
@@ -23,12 +24,12 @@
#include <glog/logging.h>
#include "kudu/fs/fs_manager.h"
-#include "kudu/gutil/gscoped_ptr.h"
#include "kudu/gutil/strings/substitute.h"
-#include "kudu/master/master.h"
#include "kudu/server/rpc_server.h"
#include "kudu/server/webserver.h"
+#include "kudu/util/env_util.h"
#include "kudu/util/net/sockaddr.h"
+#include "kudu/util/path_util.h"
#include "kudu/util/status.h"
using std::string;
@@ -42,35 +43,64 @@ DECLARE_bool(rpc_server_allow_ephemeral_ports);
namespace kudu {
namespace master {
-MiniMaster::MiniMaster(string fs_root, HostPort rpc_bind_addr)
- : rpc_bind_addr_(std::move(rpc_bind_addr)),
- fs_root_(std::move(fs_root)) {
+MiniMaster::MiniMaster(string fs_root, HostPort rpc_bind_addr, int num_data_dirs)
+ : fs_root_(std::move(fs_root)),
+ rpc_bind_addr_(std::move(rpc_bind_addr)) {
// Disable minidump handler (we allow only one per process).
FLAGS_enable_minidumps = false;
+ HostPort web_bind_addr(rpc_bind_addr_.host(), /*port=*/ 0);
+ opts_.rpc_opts.rpc_bind_addresses = rpc_bind_addr_.ToString();
+ opts_.webserver_opts.bind_interface = web_bind_addr.host();
+ opts_.webserver_opts.port = web_bind_addr.port();
+ if (num_data_dirs == 1) {
+ opts_.fs_opts.wal_path = fs_root_;
+ opts_.fs_opts.data_paths = { fs_root_ };
+ } else {
+ vector<string> fs_data_dirs;
+ for (int dir = 0; dir < num_data_dirs; dir++) {
+ fs_data_dirs.emplace_back(JoinPathSegments(fs_root_, Substitute("data-$0", dir)));
+ }
+ opts_.fs_opts.wal_path = JoinPathSegments(fs_root_, "wal");
+ opts_.fs_opts.data_paths = fs_data_dirs;
+ }
}
MiniMaster::~MiniMaster() {
Shutdown();
}
-Status MiniMaster::Start() {
- FLAGS_rpc_server_allow_ephemeral_ports = true;
- MasterOptions opts;
- HostPort web_bind_addr(rpc_bind_addr_.host(), /*port=*/ 0);
- RETURN_NOT_OK(StartOnAddrs(rpc_bind_addr_, web_bind_addr, &opts));
- return master_->WaitForCatalogManagerInit();
+void MiniMaster::SetMasterAddresses(vector<HostPort> master_addrs) {
+ CHECK(!master_);
+ opts_.master_addresses = std::move(master_addrs);
}
-Status MiniMaster::StartDistributedMaster(vector<HostPort> peer_addrs) {
- HostPort web_bind_addr(rpc_bind_addr_.host(), /*port=*/ 0);
- return StartDistributedMasterOnAddrs(rpc_bind_addr_, web_bind_addr,
- std::move(peer_addrs));
+Status MiniMaster::Start() {
+ CHECK(!master_);
+ if (opts_.master_addresses.empty()) {
+ FLAGS_rpc_server_allow_ephemeral_ports = true;
+ }
+ // In case the wal dir and data dirs are subdirectories of the root directory,
+ // ensure the root directory exists.
+ RETURN_NOT_OK(env_util::CreateDirIfMissing(Env::Default(), fs_root_));
+ unique_ptr<Master> master(new Master(opts_));
+ RETURN_NOT_OK(master->Init());
+ RETURN_NOT_OK(master->StartAsync());
+ master_.swap(master);
+
+ // Wait for the catalog manager to be ready if we only have a single master.
+ if (opts_.master_addresses.empty()) {
+ return master_->WaitForCatalogManagerInit();
+ }
+ return Status::OK();
}
Status MiniMaster::Restart() {
- MasterOptions opts;
- RETURN_NOT_OK(StartOnAddrs(HostPort(bound_rpc_), HostPort(bound_http_), &opts));
- return WaitForCatalogManagerInit();
+ CHECK(!master_);
+ opts_.rpc_opts.rpc_bind_addresses = bound_rpc_.ToString();
+ opts_.webserver_opts.bind_interface = bound_http_.host();
+ opts_.webserver_opts.port = bound_http_.port();
+ Shutdown();
+ return Start();
}
void MiniMaster::Shutdown() {
@@ -102,32 +132,5 @@ std::string MiniMaster::bound_rpc_addr_str() const {
return bound_rpc_addr().ToString();
}
-Status MiniMaster::StartOnAddrs(const HostPort& rpc_bind_addr,
- const HostPort& web_bind_addr,
- MasterOptions* opts) {
- CHECK(!master_);
-
- opts->rpc_opts.rpc_bind_addresses = rpc_bind_addr.ToString();
- opts->webserver_opts.bind_interface = web_bind_addr.host();
- opts->webserver_opts.port = web_bind_addr.port();
- opts->fs_opts.wal_path = fs_root_;
- opts->fs_opts.data_paths = { fs_root_ };
-
- unique_ptr<Master> server(new Master(*opts));
- RETURN_NOT_OK(server->Init());
- RETURN_NOT_OK(server->StartAsync());
- master_.swap(server);
-
- return Status::OK();
-}
-
-Status MiniMaster::StartDistributedMasterOnAddrs(const HostPort& rpc_bind_addr,
- const HostPort& web_bind_addr,
- std::vector<HostPort> peer_addrs) {
- MasterOptions opts;
- opts.master_addresses = std::move(peer_addrs);
- return StartOnAddrs(rpc_bind_addr, web_bind_addr, &opts);
-}
-
} // namespace master
} // namespace kudu
http://git-wip-us.apache.org/repos/asf/kudu/blob/af39a2aa/src/kudu/master/mini_master.h
----------------------------------------------------------------------
diff --git a/src/kudu/master/mini_master.h b/src/kudu/master/mini_master.h
index 77f80b2..e7dca14 100644
--- a/src/kudu/master/mini_master.h
+++ b/src/kudu/master/mini_master.h
@@ -21,9 +21,9 @@
#include <string>
#include <vector>
-#include "kudu/gutil/gscoped_ptr.h"
#include "kudu/gutil/macros.h"
#include "kudu/gutil/port.h"
+#include "kudu/master/master.h"
#include "kudu/util/env.h"
#include "kudu/util/net/net_util.h"
#include "kudu/util/net/sockaddr.h"
@@ -33,16 +33,10 @@ namespace kudu {
namespace master {
-class Master;
-struct MasterOptions;
-
// An in-process Master meant for use in test cases.
-//
-// TODO: Store the distributed cluster configuration in the object, to avoid
-// having multiple Start methods.
class MiniMaster {
public:
- MiniMaster(std::string fs_root, HostPort rpc_bind_addr);
+ MiniMaster(std::string fs_root, HostPort rpc_bind_addr, int num_data_dirs = 1);
~MiniMaster();
// Start a master running on the address specified to the constructor.
@@ -50,12 +44,13 @@ class MiniMaster {
// MiniMaster::bound_addr()
Status Start();
- Status StartDistributedMaster(std::vector<HostPort> peer_addrs);
-
// Restart the master on the same ports as it was previously bound.
- // Requires that the master is currently started.
+ // Requires that Shutdown() has already been called.
Status Restart();
+ // Set the the addresses for distributed masters.
+ void SetMasterAddresses(std::vector<HostPort> master_addrs);
+
void Shutdown();
Status WaitForCatalogManagerInit() const;
@@ -74,18 +69,11 @@ class MiniMaster {
std::string bound_rpc_addr_str() const;
private:
- Status StartOnAddrs(const HostPort& rpc_bind_addr,
- const HostPort& web_bind_addr,
- MasterOptions* opts);
-
- Status StartDistributedMasterOnAddrs(const HostPort& rpc_bind_addr,
- const HostPort& web_bind_addr,
- std::vector<HostPort> peer_addrs);
-
- const HostPort rpc_bind_addr_;
const std::string fs_root_;
+ const HostPort rpc_bind_addr_;
Sockaddr bound_rpc_;
Sockaddr bound_http_;
+ MasterOptions opts_;
std::unique_ptr<Master> master_;
};
http://git-wip-us.apache.org/repos/asf/kudu/blob/af39a2aa/src/kudu/tserver/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/src/kudu/tserver/CMakeLists.txt b/src/kudu/tserver/CMakeLists.txt
index 512988e..a64d027 100644
--- a/src/kudu/tserver/CMakeLists.txt
+++ b/src/kudu/tserver/CMakeLists.txt
@@ -167,6 +167,7 @@ set(KUDU_TEST_LINK_LIBS
tserver
tserver_test_util
${KUDU_MIN_TEST_LIBS})
+ADD_KUDU_TEST(mini_tablet_server-test)
ADD_KUDU_TEST(tablet_copy_client-test)
ADD_KUDU_TEST(tablet_copy_source_session-test)
ADD_KUDU_TEST(tablet_copy_service-test)
http://git-wip-us.apache.org/repos/asf/kudu/blob/af39a2aa/src/kudu/tserver/mini_tablet_server-test.cc
----------------------------------------------------------------------
diff --git a/src/kudu/tserver/mini_tablet_server-test.cc b/src/kudu/tserver/mini_tablet_server-test.cc
new file mode 100644
index 0000000..7405830
--- /dev/null
+++ b/src/kudu/tserver/mini_tablet_server-test.cc
@@ -0,0 +1,48 @@
+// 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 <gtest/gtest.h>
+
+#include "kudu/fs/fs_manager.h"
+#include "kudu/tserver/mini_tablet_server.h"
+#include "kudu/tserver/tablet_server.h"
+#include "kudu/util/path_util.h"
+#include "kudu/util/test_util.h"
+
+namespace kudu {
+namespace tserver {
+
+using std::unique_ptr;
+
+class MiniTabletServerTest : public KuduTest {};
+
+TEST_F(MiniTabletServerTest, TestMultiDirServer) {
+ // Specifying the number of data directories will create subdirectories under the test root.
+ unique_ptr<MiniTabletServer> mini_server;
+ FsManager* fs_manager;
+
+ int kNumDataDirs = 3;
+ mini_server.reset(new MiniTabletServer(GetTestPath("TServer"),
+ HostPort("127.0.0.1", 0), kNumDataDirs));
+ ASSERT_OK(mini_server->Start());
+ fs_manager = mini_server->server()->fs_manager();
+ ASSERT_STR_CONTAINS(DirName(fs_manager->GetWalsRootDir()), "wal");
+ ASSERT_EQ(kNumDataDirs, fs_manager->GetDataRootDirs().size());
+}
+
+} // namespace tserver
+} // namespace kudu
http://git-wip-us.apache.org/repos/asf/kudu/blob/af39a2aa/src/kudu/tserver/mini_tablet_server.cc
----------------------------------------------------------------------
diff --git a/src/kudu/tserver/mini_tablet_server.cc b/src/kudu/tserver/mini_tablet_server.cc
index b13484d..1c77082 100644
--- a/src/kudu/tserver/mini_tablet_server.cc
+++ b/src/kudu/tserver/mini_tablet_server.cc
@@ -19,6 +19,7 @@
#include <string>
#include <utility>
+#include <vector>
#include <gflags/gflags_declare.h>
@@ -27,7 +28,9 @@
#include "kudu/tablet/tablet-test-util.h"
#include "kudu/tserver/tablet_server.h"
#include "kudu/tserver/ts_tablet_manager.h"
+#include "kudu/util/env_util.h"
#include "kudu/util/net/sockaddr.h"
+#include "kudu/util/path_util.h"
#include "kudu/util/status.h"
DECLARE_bool(enable_minidumps);
@@ -38,13 +41,16 @@ using kudu::consensus::RaftPeerPB;
using std::pair;
using std::string;
using std::unique_ptr;
+using std::vector;
using strings::Substitute;
namespace kudu {
namespace tserver {
-MiniTabletServer::MiniTabletServer(const string& fs_root,
- const HostPort& rpc_bind_addr) {
+MiniTabletServer::MiniTabletServer(string fs_root,
+ const HostPort& rpc_bind_addr,
+ int num_data_dirs)
+ : fs_root_(std::move(fs_root)) {
// Disable minidump handler (we allow only one per process).
FLAGS_enable_minidumps = false;
// Start RPC server on loopback.
@@ -52,8 +58,17 @@ MiniTabletServer::MiniTabletServer(const string& fs_root,
opts_.rpc_opts.rpc_bind_addresses = rpc_bind_addr.ToString();
opts_.webserver_opts.bind_interface = rpc_bind_addr.host();
opts_.webserver_opts.port = 0;
- opts_.fs_opts.wal_path = fs_root;
- opts_.fs_opts.data_paths = { fs_root };
+ if (num_data_dirs == 1) {
+ opts_.fs_opts.wal_path = fs_root_;
+ opts_.fs_opts.data_paths = { fs_root_ };
+ } else {
+ vector<string> fs_data_dirs;
+ for (int dir = 0; dir < num_data_dirs; dir++) {
+ fs_data_dirs.emplace_back(JoinPathSegments(fs_root_, Substitute("data-$0", dir)));
+ }
+ opts_.fs_opts.wal_path = JoinPathSegments(fs_root_, "wal");
+ opts_.fs_opts.data_paths = fs_data_dirs;
+ }
}
MiniTabletServer::~MiniTabletServer() {
@@ -62,7 +77,9 @@ MiniTabletServer::~MiniTabletServer() {
Status MiniTabletServer::Start() {
CHECK(!server_);
-
+ // In case the wal dir and data dirs are subdirectories of the root directory,
+ // ensure the root directory exists.
+ RETURN_NOT_OK(env_util::CreateDirIfMissing(Env::Default(), fs_root_));
unique_ptr<TabletServer> server(new TabletServer(opts_));
RETURN_NOT_OK(server->Init());
RETURN_NOT_OK(server->Start());
http://git-wip-us.apache.org/repos/asf/kudu/blob/af39a2aa/src/kudu/tserver/mini_tablet_server.h
----------------------------------------------------------------------
diff --git a/src/kudu/tserver/mini_tablet_server.h b/src/kudu/tserver/mini_tablet_server.h
index 88d1289..f2f0231 100644
--- a/src/kudu/tserver/mini_tablet_server.h
+++ b/src/kudu/tserver/mini_tablet_server.h
@@ -42,7 +42,9 @@ class TabletServer;
class MiniTabletServer {
public:
// Note: The host portion of 'rpc_bind_addr' is also used for the http service.
- MiniTabletServer(const std::string& fs_root, const HostPort& rpc_bind_addr);
+ MiniTabletServer(std::string fs_root,
+ const HostPort& rpc_bind_addr,
+ int num_data_dirs = 1);
~MiniTabletServer();
// Return the options which will be used to start the tablet server.
@@ -97,6 +99,7 @@ class MiniTabletServer {
void FailHeartbeats();
private:
+ const std::string fs_root_;
TabletServerOptions opts_;
std::unique_ptr<TabletServer> server_;
};
http://git-wip-us.apache.org/repos/asf/kudu/blob/af39a2aa/src/kudu/tserver/tablet_copy-test-base.h
----------------------------------------------------------------------
diff --git a/src/kudu/tserver/tablet_copy-test-base.h b/src/kudu/tserver/tablet_copy-test-base.h
index 6e14d30..83cd554 100644
--- a/src/kudu/tserver/tablet_copy-test-base.h
+++ b/src/kudu/tserver/tablet_copy-test-base.h
@@ -42,7 +42,7 @@ class TabletCopyTest : public TabletServerTestBase {
public:
virtual void SetUp() OVERRIDE {
NO_FATALS(TabletServerTestBase::SetUp());
- NO_FATALS(StartTabletServer());
+ NO_FATALS(StartTabletServer(/* num_data_dirs */ 1));
// Prevent logs from being deleted out from under us until / unless we want
// to test that we are anchoring correctly. Since GenerateTestData() does a
// Flush(), Log GC is allowed to eat the logs before we get around to
http://git-wip-us.apache.org/repos/asf/kudu/blob/af39a2aa/src/kudu/tserver/tablet_server-stress-test.cc
----------------------------------------------------------------------
diff --git a/src/kudu/tserver/tablet_server-stress-test.cc b/src/kudu/tserver/tablet_server-stress-test.cc
index 761c62b..96ab39b 100644
--- a/src/kudu/tserver/tablet_server-stress-test.cc
+++ b/src/kudu/tserver/tablet_server-stress-test.cc
@@ -61,7 +61,7 @@ class TSStressTest : public TabletServerTestBase {
virtual void SetUp() OVERRIDE {
TabletServerTestBase::SetUp();
- NO_FATALS(StartTabletServer());
+ NO_FATALS(StartTabletServer(/* num_data_dirs */ 1));
histogram_ = METRIC_insert_latency.Instantiate(ts_test_metric_entity_);
}
http://git-wip-us.apache.org/repos/asf/kudu/blob/af39a2aa/src/kudu/tserver/tablet_server-test-base.h
----------------------------------------------------------------------
diff --git a/src/kudu/tserver/tablet_server-test-base.h b/src/kudu/tserver/tablet_server-test-base.h
index 2ea9de0..e174e4a 100644
--- a/src/kudu/tserver/tablet_server-test-base.h
+++ b/src/kudu/tserver/tablet_server-test-base.h
@@ -97,11 +97,13 @@ class TabletServerTestBase : public KuduTest {
ASSERT_OK(bld.Build(&client_messenger_));
}
- virtual void StartTabletServer() {
+ virtual void StartTabletServer(int num_data_dirs) {
+ CHECK(!mini_server_);
+
// Start server with an invalid master address, so it never successfully
// heartbeats, even if there happens to be a master running on this machine.
mini_server_.reset(new MiniTabletServer(GetTestPath("TabletServerTest-fsroot"),
- HostPort("127.0.0.1", 0)));
+ HostPort("127.0.0.1", 0), num_data_dirs));
mini_server_->options()->master_addresses.clear();
mini_server_->options()->master_addresses.emplace_back("255.255.255.255", 1);
ASSERT_OK(mini_server_->Start());
@@ -340,12 +342,12 @@ class TabletServerTestBase : public KuduTest {
}
}
- Status ShutdownAndRebuildTablet() {
+ Status ShutdownAndRebuildTablet(int num_data_dirs = 1) {
ShutdownTablet();
// Start server.
mini_server_.reset(new MiniTabletServer(GetTestPath("TabletServerTest-fsroot"),
- HostPort("127.0.0.1", 0)));
+ HostPort("127.0.0.1", 0), num_data_dirs));
mini_server_->options()->master_addresses.clear();
mini_server_->options()->master_addresses.emplace_back("255.255.255.255", 1);
// this should open the tablet created on StartTabletServer()
http://git-wip-us.apache.org/repos/asf/kudu/blob/af39a2aa/src/kudu/tserver/tablet_server-test.cc
----------------------------------------------------------------------
diff --git a/src/kudu/tserver/tablet_server-test.cc b/src/kudu/tserver/tablet_server-test.cc
index 1cedc97..0ae9c4f 100644
--- a/src/kudu/tserver/tablet_server-test.cc
+++ b/src/kudu/tserver/tablet_server-test.cc
@@ -78,7 +78,7 @@ class TabletServerTest : public TabletServerTestBase {
// Starts the tablet server, override to start it later.
virtual void SetUp() OVERRIDE {
NO_FATALS(TabletServerTestBase::SetUp());
- NO_FATALS(StartTabletServer());
+ NO_FATALS(StartTabletServer(/* num_data_dirs */ 1));
}
void DoOrderedScanTest(const Schema& projection, const string& expected_rows_as_string);