blob: 501f46720453dc9e42ed6945191916473c080257 [file] [log] [blame]
// 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 <cstdint>
#include <functional>
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <gtest/gtest.h>
#include "kudu/gutil/map-util.h"
#include "kudu/integration-tests/external_mini_cluster-itest-base.h"
#include "kudu/integration-tests/test_workload.h"
#include "kudu/mini-cluster/external_mini_cluster.h"
#include "kudu/util/env_util.h"
#include "kudu/util/path_util.h"
#include "kudu/util/test_macros.h"
#include "kudu/util/test_util.h"
namespace kudu {
using cluster::ExternalMiniClusterOptions;
using cluster::ExternalTabletServer;
using env_util::ListFilesInDir;
using std::map;
using std::string;
using std::vector;
class MultiDirClusterITest : public ExternalMiniClusterITestBase {};
TEST_F(MultiDirClusterITest, TestBasicMultiDirCluster) {
const uint32_t kNumDataDirs = 3;
vector<string> ts_flags = {
// Flush frequently to trigger writes.
"--flush_threshold_mb=1",
"--flush_threshold_secs=1",
// Spread tablet data across all data dirs.
"--fs_target_data_dirs_per_tablet=0"
};
ExternalMiniClusterOptions opts;
opts.extra_tserver_flags = std::move(ts_flags);
opts.num_tablet_servers = 1;
opts.num_data_dirs = kNumDataDirs;
NO_FATALS(StartClusterWithOpts(opts));
ExternalTabletServer* ts = cluster_->tablet_server(0);
TestWorkload work(cluster_.get());
work.set_num_replicas(1);
work.Setup();
// Check that all daemons have the expected number of directories.
ASSERT_EQ(kNumDataDirs, cluster_->master()->data_dirs().size());
ASSERT_EQ(kNumDataDirs, ts->data_dirs().size());
// Take an initial snapshot of the number of files in each directory.
map<string, int> num_files_in_each_dir;
for (const string& data_dir : ts->data_dirs()) {
string data_path = JoinPathSegments(data_dir, "data");
vector<string> files;
ASSERT_OK(ListFilesInDir(env_, data_path, &files));
InsertOrDie(&num_files_in_each_dir, data_dir, files.size());
}
work.Start();
ASSERT_EVENTUALLY([&] {
// Check that files are being written to more than one directory.
int num_dirs_added_to = 0;
for (const string& data_dir : ts->data_dirs()) {
string data_path = JoinPathSegments(data_dir, "data");
vector<string> files;
ListFilesInDir(env_, data_path, &files);
int* num_files_before_insert = FindOrNull(num_files_in_each_dir, data_dir);
ASSERT_NE(nullptr, num_files_before_insert);
if (*num_files_before_insert < files.size()) {
num_dirs_added_to++;
}
}
// Block placement should guarantee that more than one data dir will have
// data written to it.
ASSERT_GT(num_dirs_added_to, 1);
vector<string> wal_files;
ASSERT_OK(ListFilesInDir(env_, JoinPathSegments(ts->wal_dir(), "wals"), &wal_files));
ASSERT_FALSE(wal_files.empty());
});
work.StopAndJoin();
}
} // namespace kudu