blob: 3b6d2882085b216aa087aff215d481f8e97aa3e0 [file] [log] [blame]
// Copyright 2015 Cloudera, Inc.
//
// Licensed 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 <gflags/gflags.h>
#include <gtest/gtest.h>
#include <string>
#include <tr1/memory>
#include "kudu/client/client-test-util.h"
#include "kudu/common/wire_protocol-test-util.h"
#include "kudu/integration-tests/external_mini_cluster-itest-base.h"
#include "kudu/util/metrics.h"
using std::string;
using std::vector;
METRIC_DECLARE_entity(server);
METRIC_DECLARE_histogram(handler_latency_kudu_tserver_TabletServerAdminService_CreateTablet);
namespace kudu {
const char* const kTableName = "test-table";
class CreateTableITest : public ExternalMiniClusterITestBase {
};
// Regression test for an issue seen when we fail to create a majority of the
// replicas in a tablet. Previously, we'd still consider the tablet "RUNNING"
// on the master and finish the table creation, even though that tablet would
// be stuck forever with its minority never able to elect a leader.
TEST_F(CreateTableITest, TestCreateWhenMajorityOfReplicasFailCreation) {
const int kNumReplicas = 3;
vector<string> ts_flags;
vector<string> master_flags;
master_flags.push_back("--tablet_creation_timeout_ms=1000");
NO_FATALS(StartCluster(ts_flags, master_flags, kNumReplicas));
// Shut down 2/3 of the tablet servers.
cluster_->tablet_server(1)->Shutdown();
cluster_->tablet_server(2)->Shutdown();
// Try to create a single-tablet table.
// This won't succeed because we can't create enough replicas to get
// a quorum.
gscoped_ptr<client::KuduTableCreator> table_creator(client_->NewTableCreator());
client::KuduSchema client_schema(client::KuduSchemaFromSchema(GetSimpleTestSchema()));
ASSERT_OK(table_creator->table_name(kTableName)
.schema(&client_schema)
.num_replicas(3)
.wait(false)
.Create());
// Sleep until we've seen a couple retries on our live server.
int64_t num_create_attempts = 0;
while (num_create_attempts < 3) {
SleepFor(MonoDelta::FromMilliseconds(100));
ASSERT_OK(cluster_->tablet_server(0)->GetInt64Metric(
&METRIC_ENTITY_server,
"kudu.tabletserver",
&METRIC_handler_latency_kudu_tserver_TabletServerAdminService_CreateTablet,
"total_count",
&num_create_attempts));
LOG(INFO) << "Waiting for the master to retry creating the tablet 3 times... "
<< num_create_attempts << " RPCs seen so far";
// The CreateTable operation should still be considered in progress, even though
// we'll be successful at creating a single replica.
bool in_progress = false;
ASSERT_OK(client_->IsCreateTableInProgress(kTableName, &in_progress));
ASSERT_TRUE(in_progress);
}
// Once we restart the servers, we should succeed at creating a healthy
// replicated tablet.
ASSERT_OK(cluster_->tablet_server(1)->Restart());
ASSERT_OK(cluster_->tablet_server(2)->Restart());
// We should eventually finish the table creation we started earlier.
bool in_progress = false;
while (in_progress) {
LOG(INFO) << "Waiting for the master to successfully create the table...";
ASSERT_OK(client_->IsCreateTableInProgress(kTableName, &in_progress));
SleepFor(MonoDelta::FromMilliseconds(100));
}
}
} // namespace kudu