YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/rocksdb/db/manual_compaction_test.cc
Line
Count
Source
1
//  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2
//  This source code is licensed under the BSD-style license found in the
3
//  LICENSE file in the root directory of this source tree. An additional grant
4
//  of patent rights can be found in the PATENTS file in the same directory.
5
//
6
// The following only applies to changes made to this file as part of YugaByte development.
7
//
8
// Portions Copyright (c) YugaByte, Inc.
9
//
10
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
11
// in compliance with the License.  You may obtain a copy of the License at
12
//
13
// http://www.apache.org/licenses/LICENSE-2.0
14
//
15
// Unless required by applicable law or agreed to in writing, software distributed under the License
16
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
17
// or implied.  See the License for the specific language governing permissions and limitations
18
// under the License.
19
//
20
// Test for issue 178: a manual compaction causes deleted data to reappear.
21
22
#include <sstream>
23
24
#include <gtest/gtest.h>
25
26
#include "yb/rocksdb/compaction_filter.h"
27
#include "yb/rocksdb/db.h"
28
#include "yb/rocksdb/util/testharness.h"
29
30
#include "yb/util/test_macros.h"
31
#include "yb/rocksdb/util/testutil.h"
32
#include "yb/util/tsan_util.h"
33
34
using namespace rocksdb;  // NOLINT
35
36
namespace {
37
38
const int kNumKeys = yb::NonTsanVsTsan(1100000, 100000);
39
40
3.30M
std::string Key1(int i) {
41
3.30M
  char buf[100];
42
3.30M
  snprintf(buf, sizeof(buf), "my_key_%d", i);
43
3.30M
  return buf;
44
3.30M
}
45
46
2.20M
std::string Key2(int i) {
47
2.20M
  return Key1(i) + "_xxx";
48
2.20M
}
49
50
class ManualCompactionTest : public RocksDBTest {
51
 public:
52
2
  ManualCompactionTest() {
53
    // Get rid of any state from an old run.
54
2
    dbname_ = rocksdb::test::TmpDir() + "/rocksdb_cbug_test";
55
2
    CHECK_OK(DestroyDB(dbname_, rocksdb::Options()));
56
2
    LOG(INFO) << "Starting test with " << kNumKeys;
57
2
  }
58
59
  std::string dbname_;
60
};
61
62
class DestroyAllCompactionFilter : public CompactionFilter {
63
 public:
64
2
  DestroyAllCompactionFilter() {}
65
66
  FilterDecision Filter(int level, const Slice& key, const Slice& existing_value,
67
8
                        std::string* new_value, bool* value_changed) override {
68
6
    return existing_value.ToBuffer() == "destroy" ? FilterDecision::kDiscard
69
2
                                                  : FilterDecision::kKeep;
70
8
  }
71
72
6
  const char* Name() const override {
73
6
    return "DestroyAllCompactionFilter";
74
6
  }
75
};
76
77
1
TEST_F(ManualCompactionTest, CompactTouchesAllKeys) {
78
3
  for (int iter = 0; iter < 2; ++iter) {
79
2
    DB* db;
80
2
    Options options;
81
2
    if (iter == 0) { // level compaction
82
1
      options.num_levels = 3;
83
1
      options.compaction_style = kCompactionStyleLevel;
84
1
    } else { // universal compaction
85
1
      options.compaction_style = kCompactionStyleUniversal;
86
1
    }
87
2
    options.create_if_missing = true;
88
2
    options.compression = rocksdb::kNoCompression;
89
2
    options.compaction_filter = new DestroyAllCompactionFilter();
90
2
    ASSERT_OK(DB::Open(options, dbname_, &db));
91
92
2
    ASSERT_OK(db->Put(WriteOptions(), Slice("key1"), Slice("destroy")));
93
2
    ASSERT_OK(db->Put(WriteOptions(), Slice("key2"), Slice("destroy")));
94
2
    ASSERT_OK(db->Put(WriteOptions(), Slice("key3"), Slice("value3")));
95
2
    ASSERT_OK(db->Put(WriteOptions(), Slice("key4"), Slice("destroy")));
96
97
2
    Slice key4("key4");
98
2
    ASSERT_OK(db->CompactRange(CompactRangeOptions(), nullptr, &key4));
99
2
    Iterator* itr = db->NewIterator(ReadOptions());
100
2
    itr->SeekToFirst();
101
2
    ASSERT_TRUE(itr->Valid());
102
2
    ASSERT_EQ("key3", itr->key().ToString());
103
2
    itr->Next();
104
2
    ASSERT_TRUE(!itr->Valid());
105
2
    delete itr;
106
107
2
    delete options.compaction_filter;
108
2
    delete db;
109
2
    ASSERT_OK(DestroyDB(dbname_, options));
110
2
  }
111
1
}
112
113
1
TEST_F(ManualCompactionTest, Test) {
114
  // Open database.  Disable compression since it affects the creation
115
  // of layers and the code below is trying to test against a very
116
  // specific scenario.
117
1
  rocksdb::DB* db;
118
1
  rocksdb::Options db_options;
119
1
  db_options.create_if_missing = true;
120
1
  db_options.compression = rocksdb::kNoCompression;
121
1
  ASSERT_OK(rocksdb::DB::Open(db_options, dbname_, &db));
122
123
  // create first key range
124
1
  rocksdb::WriteBatch batch;
125
1.10M
  for (int i = 0; i < kNumKeys; i++) {
126
1.10M
    batch.Put(Key1(i), "value for range 1 key");
127
1.10M
  }
128
1
  ASSERT_OK(db->Write(rocksdb::WriteOptions(), &batch));
129
130
  // create second key range
131
1
  batch.Clear();
132
1.10M
  for (int i = 0; i < kNumKeys; i++) {
133
1.10M
    batch.Put(Key2(i), "value for range 2 key");
134
1.10M
  }
135
1
  ASSERT_OK(db->Write(rocksdb::WriteOptions(), &batch));
136
137
  // delete second key range
138
1
  batch.Clear();
139
1.10M
  for (int i = 0; i < kNumKeys; i++) {
140
1.10M
    batch.Delete(Key2(i));
141
1.10M
  }
142
1
  ASSERT_OK(db->Write(rocksdb::WriteOptions(), &batch));
143
144
  // compact database
145
1
  std::string start_key = Key1(0);
146
1
  std::string end_key = Key1(kNumKeys - 1);
147
1
  rocksdb::Slice least(start_key.data(), start_key.size());
148
1
  rocksdb::Slice greatest(end_key.data(), end_key.size());
149
150
  // commenting out the line below causes the example to work correctly
151
1
  ASSERT_OK(db->CompactRange(CompactRangeOptions(), &least, &greatest));
152
153
  // count the keys
154
1
  rocksdb::Iterator* iter = db->NewIterator(rocksdb::ReadOptions());
155
1
  int num_keys = 0;
156
1.10M
  for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
157
1.10M
    num_keys++;
158
1.10M
  }
159
1
  delete iter;
160
2
  ASSERT_EQ(kNumKeys, num_keys) << "Bad number of keys";
161
162
  // close database
163
1
  delete db;
164
1
  ASSERT_OK(DestroyDB(dbname_, rocksdb::Options()));
165
1
}
166
167
}  // anonymous namespace
168
169
13.2k
int main(int argc, char** argv) {
170
13.2k
  ::testing::InitGoogleTest(&argc, argv);
171
13.2k
  return RUN_ALL_TESTS();
172
13.2k
}