| // 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 <string> |
| |
| #include <gtest/gtest.h> |
| |
| #include "kudu/consensus/log_index.h" |
| #include "kudu/consensus/opid.pb.h" |
| #include "kudu/consensus/opid_util.h" |
| #include "kudu/gutil/port.h" |
| #include "kudu/gutil/ref_counted.h" |
| #include "kudu/util/file_cache.h" |
| #include "kudu/util/metrics.h" |
| #include "kudu/util/status.h" |
| #include "kudu/util/test_macros.h" |
| #include "kudu/util/test_util.h" |
| |
| namespace kudu { |
| namespace log { |
| |
| using consensus::MakeOpId; |
| using consensus::OpId; |
| |
| class LogIndexTest : public KuduTest { |
| public: |
| LogIndexTest() |
| : file_cache_("test", env_, 1, /*metric_entity*/ nullptr), |
| index_(new LogIndex(env_, &file_cache_, test_dir_)) { |
| } |
| |
| virtual void SetUp() OVERRIDE { |
| KuduTest::SetUp(); |
| ASSERT_OK(file_cache_.Init()); |
| } |
| |
| protected: |
| Status AddEntry(const OpId& op_id, int64_t segment, int64_t offset) { |
| LogIndexEntry entry; |
| entry.op_id = op_id; |
| entry.segment_sequence_number = segment; |
| entry.offset_in_segment = offset; |
| return index_->AddEntry(entry); |
| } |
| |
| void VerifyEntry(const OpId& op_id, int64_t segment, int64_t offset) { |
| SCOPED_TRACE(op_id); |
| LogIndexEntry result; |
| EXPECT_OK(index_->GetEntry(op_id.index(), &result)); |
| EXPECT_EQ(op_id.term(), result.op_id.term()); |
| EXPECT_EQ(op_id.index(), result.op_id.index()); |
| EXPECT_EQ(segment, result.segment_sequence_number); |
| EXPECT_EQ(offset, result.offset_in_segment); |
| } |
| |
| void VerifyNotFound(int64_t index) { |
| SCOPED_TRACE(index); |
| LogIndexEntry result; |
| Status s = index_->GetEntry(index, &result); |
| EXPECT_TRUE(s.IsNotFound()) << s.ToString(); |
| } |
| |
| FileCache file_cache_; |
| scoped_refptr<LogIndex> index_; |
| }; |
| |
| |
| TEST_F(LogIndexTest, TestBasic) { |
| // Insert three entries. |
| ASSERT_OK(AddEntry(MakeOpId(1, 1), 1, 12345)); |
| ASSERT_OK(AddEntry(MakeOpId(1, 999999), 1, 999)); |
| ASSERT_OK(AddEntry(MakeOpId(1, 1500000), 1, 54321)); |
| VerifyEntry(MakeOpId(1, 1), 1, 12345); |
| VerifyEntry(MakeOpId(1, 999999), 1, 999); |
| VerifyEntry(MakeOpId(1, 1500000), 1, 54321); |
| |
| // Overwrite one. |
| ASSERT_OK(AddEntry(MakeOpId(5, 1), 1, 50000)); |
| VerifyEntry(MakeOpId(5, 1), 1, 50000); |
| } |
| |
| TEST_F(LogIndexTest, TestMultiSegmentWithGC) { |
| ASSERT_OK(AddEntry(MakeOpId(1, 1), 1, 12345)); |
| ASSERT_OK(AddEntry(MakeOpId(1, 1000000), 1, 54321)); |
| ASSERT_OK(AddEntry(MakeOpId(1, 1500000), 1, 54321)); |
| ASSERT_OK(AddEntry(MakeOpId(1, 2500000), 1, 12345)); |
| |
| // GCing indexes < 1,000,000 shouldn't have any effect, because we can't remove any whole segment. |
| for (int gc = 0; gc < 1000000; gc += 100000) { |
| SCOPED_TRACE(gc); |
| index_->GC(gc); |
| VerifyEntry(MakeOpId(1, 1), 1, 12345); |
| VerifyEntry(MakeOpId(1, 1000000), 1, 54321); |
| VerifyEntry(MakeOpId(1, 1500000), 1, 54321); |
| VerifyEntry(MakeOpId(1, 2500000), 1, 12345); |
| } |
| |
| // If we GC index 1000000, we should lose the first op. |
| index_->GC(1000000); |
| VerifyNotFound(1); |
| VerifyEntry(MakeOpId(1, 1000000), 1, 54321); |
| VerifyEntry(MakeOpId(1, 1500000), 1, 54321); |
| VerifyEntry(MakeOpId(1, 2500000), 1, 12345); |
| |
| // GC everything |
| index_->GC(9000000); |
| VerifyNotFound(1); |
| VerifyNotFound(1000000); |
| VerifyNotFound(1500000); |
| VerifyNotFound(2500000); |
| } |
| |
| } // namespace log |
| } // namespace kudu |