blob: 8792c95c105ff4c9830e2b25f8f0f3c9f1dab31f [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.
#ifndef KUDU_TSERVER_REMOTE_BOOTSTRAP_TEST_BASE_H_
#define KUDU_TSERVER_REMOTE_BOOTSTRAP_TEST_BASE_H_
#include "kudu/tserver/tablet_server-test-base.h"
#include <string>
#include "kudu/consensus/log_anchor_registry.h"
#include "kudu/consensus/opid_util.h"
#include "kudu/fs/block_manager.h"
#include "kudu/gutil/strings/fastmem.h"
#include "kudu/tablet/metadata.pb.h"
#include "kudu/tserver/remote_bootstrap.pb.h"
#include "kudu/util/crc.h"
#include "kudu/util/stopwatch.h"
#include "kudu/util/test_util.h"
namespace kudu {
namespace tserver {
using consensus::MinimumOpId;
// Number of times to roll the log.
static const int kNumLogRolls = 2;
class RemoteBootstrapTest : public TabletServerTestBase {
public:
virtual void SetUp() OVERRIDE {
TabletServerTestBase::SetUp();
StartTabletServer();
// 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
// starting a remote bootstrap session.
tablet_peer_->log_anchor_registry()->Register(
MinimumOpId().index(), CURRENT_TEST_NAME(), &anchor_);
ASSERT_NO_FATAL_FAILURE(GenerateTestData());
}
virtual void TearDown() OVERRIDE {
ASSERT_OK(tablet_peer_->log_anchor_registry()->Unregister(&anchor_));
TabletServerTestBase::TearDown();
}
protected:
// Grab the first column block we find in the SuperBlock.
static BlockId FirstColumnBlockId(const tablet::TabletSuperBlockPB& superblock) {
const tablet::RowSetDataPB& rowset = superblock.rowsets(0);
const tablet::ColumnDataPB& column = rowset.columns(0);
const BlockIdPB& block_id_pb = column.block();
return BlockId::FromPB(block_id_pb);
}
// Check that the contents and CRC32C of a DataChunkPB are equal to a local buffer.
static void AssertDataEqual(const uint8_t* local, int64_t size, const DataChunkPB& remote) {
ASSERT_EQ(size, remote.data().size());
ASSERT_TRUE(strings::memeq(local, remote.data().data(), size));
uint32_t crc32 = crc::Crc32c(local, size);
ASSERT_EQ(crc32, remote.crc32());
}
// Generate the test data for the tablet and do the flushing we assume will be
// done in the unit tests for remote bootstrap.
void GenerateTestData() {
const int kIncr = 50;
LOG_TIMING(INFO, "Loading test data") {
for (int row_id = 0; row_id < kNumLogRolls * kIncr; row_id += kIncr) {
InsertTestRowsRemote(0, row_id, kIncr);
ASSERT_OK(tablet_peer_->tablet()->Flush());
ASSERT_OK(tablet_peer_->log()->AllocateSegmentAndRollOver());
}
}
}
// Return the permananent_uuid of the local service.
const std::string GetLocalUUID() const {
return tablet_peer_->permanent_uuid();
}
const std::string& GetTabletId() const {
return tablet_peer_->tablet()->tablet_id();
}
// Read a block file from the file system fully into memory and return a
// Slice pointing to it.
Status ReadLocalBlockFile(FsManager* fs_manager, const BlockId& block_id,
faststring* scratch, Slice* slice) {
gscoped_ptr<fs::ReadableBlock> block;
RETURN_NOT_OK(fs_manager->OpenBlock(block_id, &block));
uint64_t size = 0;
RETURN_NOT_OK(block->Size(&size));
scratch->resize(size);
RETURN_NOT_OK(block->Read(0, size, slice, scratch->data()));
// Since the mmap will go away on return, copy the data into scratch.
if (slice->data() != scratch->data()) {
memcpy(scratch->data(), slice->data(), slice->size());
*slice = Slice(scratch->data(), slice->size());
}
return Status::OK();
}
log::LogAnchor anchor_;
};
} // namespace tserver
} // namespace kudu
#endif // KUDU_TSERVER_REMOTE_BOOTSTRAP_TEST_BASE_H_