blob: 7e00a7b0d0b6d795b61a8d51a6790a2a39d9b93e [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 <ostream>
#include <string>
#include <vector>
#include <glog/logging.h>
#include <gtest/gtest.h>
#include "kudu/common/common.pb.h"
#include "kudu/gutil/ref_counted.h"
#include "kudu/gutil/strings/substitute.h"
#include "kudu/master/catalog_manager.h"
#include "kudu/master/master.pb.h"
#include "kudu/master/ts_descriptor.h"
#include "kudu/util/cow_object.h"
#include "kudu/util/monotime.h"
#include "kudu/util/test_macros.h"
#include "kudu/util/test_util.h"
using std::string;
using std::vector;
using strings::Substitute;
namespace kudu {
namespace master {
// Test of the tablet assignment algo for splits done at table creation time.
// This tests that when we define a split, the tablet lands on the expected
// side of the split, i.e. it's a closed interval on the start key and an open
// interval on the end key (non-inclusive).
TEST(TableInfoTest, TestAssignmentRanges) {
const string table_id = CURRENT_TEST_NAME();
scoped_refptr<TableInfo> table(new TableInfo(table_id));
vector<scoped_refptr<TabletInfo>> tablets;
// Define & create the splits.
const int kNumSplits = 3;
string split_keys[kNumSplits] = { "a", "b", "c" }; // The keys we split on.
for (int i = 0; i <= kNumSplits; i++) {
const string& start_key = (i == 0) ? "" : split_keys[i - 1];
const string& end_key = (i == kNumSplits) ? "" : split_keys[i];
string tablet_id = Substitute("tablet-$0-$1", start_key, end_key);
scoped_refptr<TabletInfo> tablet = new TabletInfo(table, tablet_id);
{
TabletMetadataLock meta_lock(tablet.get(), LockMode::WRITE);
PartitionPB* partition = meta_lock.mutable_data()->pb.mutable_partition();
partition->set_partition_key_start(start_key);
partition->set_partition_key_end(end_key);
meta_lock.mutable_data()->pb.set_state(SysTabletsEntryPB::RUNNING);
meta_lock.Commit();
}
TabletMetadataLock meta_lock(tablet.get(), LockMode::READ);
table->AddRemoveTablets({ tablet }, {});
tablets.push_back(tablet);
}
// Ensure they give us what we are expecting.
for (int i = 0; i <= kNumSplits; i++) {
// Calculate the tablet id and start key.
const string& start_key = (i == 0) ? "" : split_keys[i - 1];
const string& end_key = (i == kNumSplits) ? "" : split_keys[i];
string tablet_id = Substitute("tablet-$0-$1", start_key, end_key);
// Query using the start key.
GetTableLocationsRequestPB req;
req.set_max_returned_locations(1);
req.mutable_table()->mutable_table_name()->assign(table_id);
req.mutable_partition_key_start()->assign(start_key);
vector<scoped_refptr<TabletInfo>> tablets_in_range;
table->GetTabletsInRange(&req, &tablets_in_range);
// Only one tablet should own this key.
ASSERT_EQ(1, tablets_in_range.size());
// The tablet with range start key matching 'start_key' should be the owner.
ASSERT_EQ(tablet_id, (*tablets_in_range.begin())->id());
LOG(INFO) << "Key " << start_key << " found in tablet " << tablet_id;
}
}
TEST(TestTSDescriptor, TestReplicaCreationsDecay) {
TSDescriptor ts("test");
ASSERT_EQ(0, ts.RecentReplicaCreations());
ts.IncrementRecentReplicaCreations();
// The load should start at close to 1.0.
double val_a = ts.RecentReplicaCreations();
ASSERT_NEAR(1.0, val_a, 0.05);
// After 10ms it should have dropped a bit, but still be close to 1.0.
SleepFor(MonoDelta::FromMilliseconds(10));
double val_b = ts.RecentReplicaCreations();
ASSERT_LT(val_b, val_a);
ASSERT_NEAR(0.99, val_a, 0.05);
if (AllowSlowTests()) {
// After 10 seconds, we should have dropped to 0.5^(10/60) = 0.891
SleepFor(MonoDelta::FromSeconds(10));
ASSERT_NEAR(0.891, ts.RecentReplicaCreations(), 0.05);
}
}
} // namespace master
} // namespace kudu