]> git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/utilities/ttl/ttl_test.cc
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / rocksdb / utilities / ttl / ttl_test.cc
1 // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. See the AUTHORS file for names of contributors.
4
5 #ifndef ROCKSDB_LITE
6
7 #include <map>
8 #include <memory>
9 #include "rocksdb/compaction_filter.h"
10 #include "rocksdb/utilities/db_ttl.h"
11 #include "util/string_util.h"
12 #include "util/testharness.h"
13 #ifndef OS_WIN
14 #include <unistd.h>
15 #endif
16
17 namespace rocksdb {
18
19 namespace {
20
21 typedef std::map<std::string, std::string> KVMap;
22
23 enum BatchOperation { OP_PUT = 0, OP_DELETE = 1 };
24 }
25
26 class SpecialTimeEnv : public EnvWrapper {
27 public:
28 explicit SpecialTimeEnv(Env* base) : EnvWrapper(base) {
29 base->GetCurrentTime(&current_time_);
30 }
31
32 void Sleep(int64_t sleep_time) { current_time_ += sleep_time; }
33 virtual Status GetCurrentTime(int64_t* current_time) override {
34 *current_time = current_time_;
35 return Status::OK();
36 }
37
38 private:
39 int64_t current_time_ = 0;
40 };
41
42 class TtlTest : public testing::Test {
43 public:
44 TtlTest() {
45 env_.reset(new SpecialTimeEnv(Env::Default()));
46 dbname_ = test::PerThreadDBPath("db_ttl");
47 options_.create_if_missing = true;
48 options_.env = env_.get();
49 // ensure that compaction is kicked in to always strip timestamp from kvs
50 options_.max_compaction_bytes = 1;
51 // compaction should take place always from level0 for determinism
52 db_ttl_ = nullptr;
53 DestroyDB(dbname_, Options());
54 }
55
56 ~TtlTest() {
57 CloseTtl();
58 DestroyDB(dbname_, Options());
59 }
60
61 // Open database with TTL support when TTL not provided with db_ttl_ pointer
62 void OpenTtl() {
63 ASSERT_TRUE(db_ttl_ ==
64 nullptr); // db should be closed before opening again
65 ASSERT_OK(DBWithTTL::Open(options_, dbname_, &db_ttl_));
66 }
67
68 // Open database with TTL support when TTL provided with db_ttl_ pointer
69 void OpenTtl(int32_t ttl) {
70 ASSERT_TRUE(db_ttl_ == nullptr);
71 ASSERT_OK(DBWithTTL::Open(options_, dbname_, &db_ttl_, ttl));
72 }
73
74 // Open with TestFilter compaction filter
75 void OpenTtlWithTestCompaction(int32_t ttl) {
76 options_.compaction_filter_factory =
77 std::shared_ptr<CompactionFilterFactory>(
78 new TestFilterFactory(kSampleSize_, kNewValue_));
79 OpenTtl(ttl);
80 }
81
82 // Open database with TTL support in read_only mode
83 void OpenReadOnlyTtl(int32_t ttl) {
84 ASSERT_TRUE(db_ttl_ == nullptr);
85 ASSERT_OK(DBWithTTL::Open(options_, dbname_, &db_ttl_, ttl, true));
86 }
87
88 void CloseTtl() {
89 delete db_ttl_;
90 db_ttl_ = nullptr;
91 }
92
93 // Populates and returns a kv-map
94 void MakeKVMap(int64_t num_entries) {
95 kvmap_.clear();
96 int digits = 1;
97 for (int64_t dummy = num_entries; dummy /= 10; ++digits) {
98 }
99 int digits_in_i = 1;
100 for (int64_t i = 0; i < num_entries; i++) {
101 std::string key = "key";
102 std::string value = "value";
103 if (i % 10 == 0) {
104 digits_in_i++;
105 }
106 for(int j = digits_in_i; j < digits; j++) {
107 key.append("0");
108 value.append("0");
109 }
110 AppendNumberTo(&key, i);
111 AppendNumberTo(&value, i);
112 kvmap_[key] = value;
113 }
114 ASSERT_EQ(static_cast<int64_t>(kvmap_.size()),
115 num_entries); // check all insertions done
116 }
117
118 // Makes a write-batch with key-vals from kvmap_ and 'Write''s it
119 void MakePutWriteBatch(const BatchOperation* batch_ops, int64_t num_ops) {
120 ASSERT_LE(num_ops, static_cast<int64_t>(kvmap_.size()));
121 static WriteOptions wopts;
122 static FlushOptions flush_opts;
123 WriteBatch batch;
124 kv_it_ = kvmap_.begin();
125 for (int64_t i = 0; i < num_ops && kv_it_ != kvmap_.end(); i++, ++kv_it_) {
126 switch (batch_ops[i]) {
127 case OP_PUT:
128 batch.Put(kv_it_->first, kv_it_->second);
129 break;
130 case OP_DELETE:
131 batch.Delete(kv_it_->first);
132 break;
133 default:
134 FAIL();
135 }
136 }
137 db_ttl_->Write(wopts, &batch);
138 db_ttl_->Flush(flush_opts);
139 }
140
141 // Puts num_entries starting from start_pos_map from kvmap_ into the database
142 void PutValues(int64_t start_pos_map, int64_t num_entries, bool flush = true,
143 ColumnFamilyHandle* cf = nullptr) {
144 ASSERT_TRUE(db_ttl_);
145 ASSERT_LE(start_pos_map + num_entries, static_cast<int64_t>(kvmap_.size()));
146 static WriteOptions wopts;
147 static FlushOptions flush_opts;
148 kv_it_ = kvmap_.begin();
149 advance(kv_it_, start_pos_map);
150 for (int64_t i = 0; kv_it_ != kvmap_.end() && i < num_entries;
151 i++, ++kv_it_) {
152 ASSERT_OK(cf == nullptr
153 ? db_ttl_->Put(wopts, kv_it_->first, kv_it_->second)
154 : db_ttl_->Put(wopts, cf, kv_it_->first, kv_it_->second));
155 }
156 // Put a mock kv at the end because CompactionFilter doesn't delete last key
157 ASSERT_OK(cf == nullptr ? db_ttl_->Put(wopts, "keymock", "valuemock")
158 : db_ttl_->Put(wopts, cf, "keymock", "valuemock"));
159 if (flush) {
160 if (cf == nullptr) {
161 db_ttl_->Flush(flush_opts);
162 } else {
163 db_ttl_->Flush(flush_opts, cf);
164 }
165 }
166 }
167
168 // Runs a manual compaction
169 void ManualCompact(ColumnFamilyHandle* cf = nullptr) {
170 if (cf == nullptr) {
171 db_ttl_->CompactRange(CompactRangeOptions(), nullptr, nullptr);
172 } else {
173 db_ttl_->CompactRange(CompactRangeOptions(), cf, nullptr, nullptr);
174 }
175 }
176
177 // checks the whole kvmap_ to return correct values using KeyMayExist
178 void SimpleKeyMayExistCheck() {
179 static ReadOptions ropts;
180 bool value_found;
181 std::string val;
182 for(auto &kv : kvmap_) {
183 bool ret = db_ttl_->KeyMayExist(ropts, kv.first, &val, &value_found);
184 if (ret == false || value_found == false) {
185 fprintf(stderr, "KeyMayExist could not find key=%s in the database but"
186 " should have\n", kv.first.c_str());
187 FAIL();
188 } else if (val.compare(kv.second) != 0) {
189 fprintf(stderr, " value for key=%s present in database is %s but"
190 " should be %s\n", kv.first.c_str(), val.c_str(),
191 kv.second.c_str());
192 FAIL();
193 }
194 }
195 }
196
197 // checks the whole kvmap_ to return correct values using MultiGet
198 void SimpleMultiGetTest() {
199 static ReadOptions ropts;
200 std::vector<Slice> keys;
201 std::vector<std::string> values;
202
203 for (auto& kv : kvmap_) {
204 keys.emplace_back(kv.first);
205 }
206
207 auto statuses = db_ttl_->MultiGet(ropts, keys, &values);
208 size_t i = 0;
209 for (auto& kv : kvmap_) {
210 ASSERT_OK(statuses[i]);
211 ASSERT_EQ(values[i], kv.second);
212 ++i;
213 }
214 }
215
216 // Sleeps for slp_tim then runs a manual compaction
217 // Checks span starting from st_pos from kvmap_ in the db and
218 // Gets should return true if check is true and false otherwise
219 // Also checks that value that we got is the same as inserted; and =kNewValue
220 // if test_compaction_change is true
221 void SleepCompactCheck(int slp_tim, int64_t st_pos, int64_t span,
222 bool check = true, bool test_compaction_change = false,
223 ColumnFamilyHandle* cf = nullptr) {
224 ASSERT_TRUE(db_ttl_);
225
226 env_->Sleep(slp_tim);
227 ManualCompact(cf);
228 static ReadOptions ropts;
229 kv_it_ = kvmap_.begin();
230 advance(kv_it_, st_pos);
231 std::string v;
232 for (int64_t i = 0; kv_it_ != kvmap_.end() && i < span; i++, ++kv_it_) {
233 Status s = (cf == nullptr) ? db_ttl_->Get(ropts, kv_it_->first, &v)
234 : db_ttl_->Get(ropts, cf, kv_it_->first, &v);
235 if (s.ok() != check) {
236 fprintf(stderr, "key=%s ", kv_it_->first.c_str());
237 if (!s.ok()) {
238 fprintf(stderr, "is absent from db but was expected to be present\n");
239 } else {
240 fprintf(stderr, "is present in db but was expected to be absent\n");
241 }
242 FAIL();
243 } else if (s.ok()) {
244 if (test_compaction_change && v.compare(kNewValue_) != 0) {
245 fprintf(stderr, " value for key=%s present in database is %s but "
246 " should be %s\n", kv_it_->first.c_str(), v.c_str(),
247 kNewValue_.c_str());
248 FAIL();
249 } else if (!test_compaction_change && v.compare(kv_it_->second) !=0) {
250 fprintf(stderr, " value for key=%s present in database is %s but "
251 " should be %s\n", kv_it_->first.c_str(), v.c_str(),
252 kv_it_->second.c_str());
253 FAIL();
254 }
255 }
256 }
257 }
258
259 // Similar as SleepCompactCheck but uses TtlIterator to read from db
260 void SleepCompactCheckIter(int slp, int st_pos, int64_t span,
261 bool check = true) {
262 ASSERT_TRUE(db_ttl_);
263 env_->Sleep(slp);
264 ManualCompact();
265 static ReadOptions ropts;
266 Iterator *dbiter = db_ttl_->NewIterator(ropts);
267 kv_it_ = kvmap_.begin();
268 advance(kv_it_, st_pos);
269
270 dbiter->Seek(kv_it_->first);
271 if (!check) {
272 if (dbiter->Valid()) {
273 ASSERT_NE(dbiter->value().compare(kv_it_->second), 0);
274 }
275 } else { // dbiter should have found out kvmap_[st_pos]
276 for (int64_t i = st_pos; kv_it_ != kvmap_.end() && i < st_pos + span;
277 i++, ++kv_it_) {
278 ASSERT_TRUE(dbiter->Valid());
279 ASSERT_EQ(dbiter->value().compare(kv_it_->second), 0);
280 dbiter->Next();
281 }
282 }
283 delete dbiter;
284 }
285
286 // Set ttl on open db
287 void SetTtl(int32_t ttl, ColumnFamilyHandle* cf = nullptr) {
288 ASSERT_TRUE(db_ttl_);
289 cf == nullptr ? db_ttl_->SetTtl(ttl) : db_ttl_->SetTtl(cf, ttl);
290 }
291
292 class TestFilter : public CompactionFilter {
293 public:
294 TestFilter(const int64_t kSampleSize, const std::string& kNewValue)
295 : kSampleSize_(kSampleSize),
296 kNewValue_(kNewValue) {
297 }
298
299 // Works on keys of the form "key<number>"
300 // Drops key if number at the end of key is in [0, kSampleSize_/3),
301 // Keeps key if it is in [kSampleSize_/3, 2*kSampleSize_/3),
302 // Change value if it is in [2*kSampleSize_/3, kSampleSize_)
303 // Eg. kSampleSize_=6. Drop:key0-1...Keep:key2-3...Change:key4-5...
304 virtual bool Filter(int /*level*/, const Slice& key, const Slice& /*value*/,
305 std::string* new_value,
306 bool* value_changed) const override {
307 assert(new_value != nullptr);
308
309 std::string search_str = "0123456789";
310 std::string key_string = key.ToString();
311 size_t pos = key_string.find_first_of(search_str);
312 int num_key_end;
313 if (pos != std::string::npos) {
314 auto key_substr = key_string.substr(pos, key.size() - pos);
315 #ifndef CYGWIN
316 num_key_end = std::stoi(key_substr);
317 #else
318 num_key_end = std::strtol(key_substr.c_str(), 0, 10);
319 #endif
320
321 } else {
322 return false; // Keep keys not matching the format "key<NUMBER>"
323 }
324
325 int64_t partition = kSampleSize_ / 3;
326 if (num_key_end < partition) {
327 return true;
328 } else if (num_key_end < partition * 2) {
329 return false;
330 } else {
331 *new_value = kNewValue_;
332 *value_changed = true;
333 return false;
334 }
335 }
336
337 virtual const char* Name() const override {
338 return "TestFilter";
339 }
340
341 private:
342 const int64_t kSampleSize_;
343 const std::string kNewValue_;
344 };
345
346 class TestFilterFactory : public CompactionFilterFactory {
347 public:
348 TestFilterFactory(const int64_t kSampleSize, const std::string& kNewValue)
349 : kSampleSize_(kSampleSize),
350 kNewValue_(kNewValue) {
351 }
352
353 virtual std::unique_ptr<CompactionFilter> CreateCompactionFilter(
354 const CompactionFilter::Context& /*context*/) override {
355 return std::unique_ptr<CompactionFilter>(
356 new TestFilter(kSampleSize_, kNewValue_));
357 }
358
359 virtual const char* Name() const override {
360 return "TestFilterFactory";
361 }
362
363 private:
364 const int64_t kSampleSize_;
365 const std::string kNewValue_;
366 };
367
368
369 // Choose carefully so that Put, Gets & Compaction complete in 1 second buffer
370 static const int64_t kSampleSize_ = 100;
371 std::string dbname_;
372 DBWithTTL* db_ttl_;
373 unique_ptr<SpecialTimeEnv> env_;
374
375 private:
376 Options options_;
377 KVMap kvmap_;
378 KVMap::iterator kv_it_;
379 const std::string kNewValue_ = "new_value";
380 unique_ptr<CompactionFilter> test_comp_filter_;
381 }; // class TtlTest
382
383 // If TTL is non positive or not provided, the behaviour is TTL = infinity
384 // This test opens the db 3 times with such default behavior and inserts a
385 // bunch of kvs each time. All kvs should accumulate in the db till the end
386 // Partitions the sample-size provided into 3 sets over boundary1 and boundary2
387 TEST_F(TtlTest, NoEffect) {
388 MakeKVMap(kSampleSize_);
389 int64_t boundary1 = kSampleSize_ / 3;
390 int64_t boundary2 = 2 * boundary1;
391
392 OpenTtl();
393 PutValues(0, boundary1); //T=0: Set1 never deleted
394 SleepCompactCheck(1, 0, boundary1); //T=1: Set1 still there
395 CloseTtl();
396
397 OpenTtl(0);
398 PutValues(boundary1, boundary2 - boundary1); //T=1: Set2 never deleted
399 SleepCompactCheck(1, 0, boundary2); //T=2: Sets1 & 2 still there
400 CloseTtl();
401
402 OpenTtl(-1);
403 PutValues(boundary2, kSampleSize_ - boundary2); //T=3: Set3 never deleted
404 SleepCompactCheck(1, 0, kSampleSize_, true); //T=4: Sets 1,2,3 still there
405 CloseTtl();
406 }
407
408 // Puts a set of values and checks its presence using Get during ttl
409 TEST_F(TtlTest, PresentDuringTTL) {
410 MakeKVMap(kSampleSize_);
411
412 OpenTtl(2); // T=0:Open the db with ttl = 2
413 PutValues(0, kSampleSize_); // T=0:Insert Set1. Delete at t=2
414 SleepCompactCheck(1, 0, kSampleSize_, true); // T=1:Set1 should still be there
415 CloseTtl();
416 }
417
418 // Puts a set of values and checks its absence using Get after ttl
419 TEST_F(TtlTest, AbsentAfterTTL) {
420 MakeKVMap(kSampleSize_);
421
422 OpenTtl(1); // T=0:Open the db with ttl = 2
423 PutValues(0, kSampleSize_); // T=0:Insert Set1. Delete at t=2
424 SleepCompactCheck(2, 0, kSampleSize_, false); // T=2:Set1 should not be there
425 CloseTtl();
426 }
427
428 // Resets the timestamp of a set of kvs by updating them and checks that they
429 // are not deleted according to the old timestamp
430 TEST_F(TtlTest, ResetTimestamp) {
431 MakeKVMap(kSampleSize_);
432
433 OpenTtl(3);
434 PutValues(0, kSampleSize_); // T=0: Insert Set1. Delete at t=3
435 env_->Sleep(2); // T=2
436 PutValues(0, kSampleSize_); // T=2: Insert Set1. Delete at t=5
437 SleepCompactCheck(2, 0, kSampleSize_); // T=4: Set1 should still be there
438 CloseTtl();
439 }
440
441 // Similar to PresentDuringTTL but uses Iterator
442 TEST_F(TtlTest, IterPresentDuringTTL) {
443 MakeKVMap(kSampleSize_);
444
445 OpenTtl(2);
446 PutValues(0, kSampleSize_); // T=0: Insert. Delete at t=2
447 SleepCompactCheckIter(1, 0, kSampleSize_); // T=1: Set should be there
448 CloseTtl();
449 }
450
451 // Similar to AbsentAfterTTL but uses Iterator
452 TEST_F(TtlTest, IterAbsentAfterTTL) {
453 MakeKVMap(kSampleSize_);
454
455 OpenTtl(1);
456 PutValues(0, kSampleSize_); // T=0: Insert. Delete at t=1
457 SleepCompactCheckIter(2, 0, kSampleSize_, false); // T=2: Should not be there
458 CloseTtl();
459 }
460
461 // Checks presence while opening the same db more than once with the same ttl
462 // Note: The second open will open the same db
463 TEST_F(TtlTest, MultiOpenSamePresent) {
464 MakeKVMap(kSampleSize_);
465
466 OpenTtl(2);
467 PutValues(0, kSampleSize_); // T=0: Insert. Delete at t=2
468 CloseTtl();
469
470 OpenTtl(2); // T=0. Delete at t=2
471 SleepCompactCheck(1, 0, kSampleSize_); // T=1: Set should be there
472 CloseTtl();
473 }
474
475 // Checks absence while opening the same db more than once with the same ttl
476 // Note: The second open will open the same db
477 TEST_F(TtlTest, MultiOpenSameAbsent) {
478 MakeKVMap(kSampleSize_);
479
480 OpenTtl(1);
481 PutValues(0, kSampleSize_); // T=0: Insert. Delete at t=1
482 CloseTtl();
483
484 OpenTtl(1); // T=0.Delete at t=1
485 SleepCompactCheck(2, 0, kSampleSize_, false); // T=2: Set should not be there
486 CloseTtl();
487 }
488
489 // Checks presence while opening the same db more than once with bigger ttl
490 TEST_F(TtlTest, MultiOpenDifferent) {
491 MakeKVMap(kSampleSize_);
492
493 OpenTtl(1);
494 PutValues(0, kSampleSize_); // T=0: Insert. Delete at t=1
495 CloseTtl();
496
497 OpenTtl(3); // T=0: Set deleted at t=3
498 SleepCompactCheck(2, 0, kSampleSize_); // T=2: Set should be there
499 CloseTtl();
500 }
501
502 // Checks presence during ttl in read_only mode
503 TEST_F(TtlTest, ReadOnlyPresentForever) {
504 MakeKVMap(kSampleSize_);
505
506 OpenTtl(1); // T=0:Open the db normally
507 PutValues(0, kSampleSize_); // T=0:Insert Set1. Delete at t=1
508 CloseTtl();
509
510 OpenReadOnlyTtl(1);
511 SleepCompactCheck(2, 0, kSampleSize_); // T=2:Set1 should still be there
512 CloseTtl();
513 }
514
515 // Checks whether WriteBatch works well with TTL
516 // Puts all kvs in kvmap_ in a batch and writes first, then deletes first half
517 TEST_F(TtlTest, WriteBatchTest) {
518 MakeKVMap(kSampleSize_);
519 BatchOperation batch_ops[kSampleSize_];
520 for (int i = 0; i < kSampleSize_; i++) {
521 batch_ops[i] = OP_PUT;
522 }
523
524 OpenTtl(2);
525 MakePutWriteBatch(batch_ops, kSampleSize_);
526 for (int i = 0; i < kSampleSize_ / 2; i++) {
527 batch_ops[i] = OP_DELETE;
528 }
529 MakePutWriteBatch(batch_ops, kSampleSize_ / 2);
530 SleepCompactCheck(0, 0, kSampleSize_ / 2, false);
531 SleepCompactCheck(0, kSampleSize_ / 2, kSampleSize_ - kSampleSize_ / 2);
532 CloseTtl();
533 }
534
535 // Checks user's compaction filter for correctness with TTL logic
536 TEST_F(TtlTest, CompactionFilter) {
537 MakeKVMap(kSampleSize_);
538
539 OpenTtlWithTestCompaction(1);
540 PutValues(0, kSampleSize_); // T=0:Insert Set1. Delete at t=1
541 // T=2: TTL logic takes precedence over TestFilter:-Set1 should not be there
542 SleepCompactCheck(2, 0, kSampleSize_, false);
543 CloseTtl();
544
545 OpenTtlWithTestCompaction(3);
546 PutValues(0, kSampleSize_); // T=0:Insert Set1.
547 int64_t partition = kSampleSize_ / 3;
548 SleepCompactCheck(1, 0, partition, false); // Part dropped
549 SleepCompactCheck(0, partition, partition); // Part kept
550 SleepCompactCheck(0, 2 * partition, partition, true, true); // Part changed
551 CloseTtl();
552 }
553
554 // Insert some key-values which KeyMayExist should be able to get and check that
555 // values returned are fine
556 TEST_F(TtlTest, KeyMayExist) {
557 MakeKVMap(kSampleSize_);
558
559 OpenTtl();
560 PutValues(0, kSampleSize_, false);
561
562 SimpleKeyMayExistCheck();
563
564 CloseTtl();
565 }
566
567 TEST_F(TtlTest, MultiGetTest) {
568 MakeKVMap(kSampleSize_);
569
570 OpenTtl();
571 PutValues(0, kSampleSize_, false);
572
573 SimpleMultiGetTest();
574
575 CloseTtl();
576 }
577
578 TEST_F(TtlTest, ColumnFamiliesTest) {
579 DB* db;
580 Options options;
581 options.create_if_missing = true;
582 options.env = env_.get();
583
584 DB::Open(options, dbname_, &db);
585 ColumnFamilyHandle* handle;
586 ASSERT_OK(db->CreateColumnFamily(ColumnFamilyOptions(options),
587 "ttl_column_family", &handle));
588
589 delete handle;
590 delete db;
591
592 std::vector<ColumnFamilyDescriptor> column_families;
593 column_families.push_back(ColumnFamilyDescriptor(
594 kDefaultColumnFamilyName, ColumnFamilyOptions(options)));
595 column_families.push_back(ColumnFamilyDescriptor(
596 "ttl_column_family", ColumnFamilyOptions(options)));
597
598 std::vector<ColumnFamilyHandle*> handles;
599
600 ASSERT_OK(DBWithTTL::Open(DBOptions(options), dbname_, column_families,
601 &handles, &db_ttl_, {3, 5}, false));
602 ASSERT_EQ(handles.size(), 2U);
603 ColumnFamilyHandle* new_handle;
604 ASSERT_OK(db_ttl_->CreateColumnFamilyWithTtl(options, "ttl_column_family_2",
605 &new_handle, 2));
606 handles.push_back(new_handle);
607
608 MakeKVMap(kSampleSize_);
609 PutValues(0, kSampleSize_, false, handles[0]);
610 PutValues(0, kSampleSize_, false, handles[1]);
611 PutValues(0, kSampleSize_, false, handles[2]);
612
613 // everything should be there after 1 second
614 SleepCompactCheck(1, 0, kSampleSize_, true, false, handles[0]);
615 SleepCompactCheck(0, 0, kSampleSize_, true, false, handles[1]);
616 SleepCompactCheck(0, 0, kSampleSize_, true, false, handles[2]);
617
618 // only column family 1 should be alive after 4 seconds
619 SleepCompactCheck(3, 0, kSampleSize_, false, false, handles[0]);
620 SleepCompactCheck(0, 0, kSampleSize_, true, false, handles[1]);
621 SleepCompactCheck(0, 0, kSampleSize_, false, false, handles[2]);
622
623 // nothing should be there after 6 seconds
624 SleepCompactCheck(2, 0, kSampleSize_, false, false, handles[0]);
625 SleepCompactCheck(0, 0, kSampleSize_, false, false, handles[1]);
626 SleepCompactCheck(0, 0, kSampleSize_, false, false, handles[2]);
627
628 for (auto h : handles) {
629 delete h;
630 }
631 delete db_ttl_;
632 db_ttl_ = nullptr;
633 }
634
635 // Puts a set of values and checks its absence using Get after ttl
636 TEST_F(TtlTest, ChangeTtlOnOpenDb) {
637 MakeKVMap(kSampleSize_);
638
639 OpenTtl(1); // T=0:Open the db with ttl = 2
640 SetTtl(3);
641 // @lint-ignore TXT2 T25377293 Grandfathered in
642 PutValues(0, kSampleSize_); // T=0:Insert Set1. Delete at t=2
643 SleepCompactCheck(2, 0, kSampleSize_, true); // T=2:Set1 should be there
644 CloseTtl();
645 }
646
647 } // namespace rocksdb
648
649 // A black-box test for the ttl wrapper around rocksdb
650 int main(int argc, char** argv) {
651 ::testing::InitGoogleTest(&argc, argv);
652 return RUN_ALL_TESTS();
653 }
654
655 #else
656 #include <stdio.h>
657
658 int main(int /*argc*/, char** /*argv*/) {
659 fprintf(stderr, "SKIPPED as DBWithTTL is not supported in ROCKSDB_LITE\n");
660 return 0;
661 }
662
663 #endif // !ROCKSDB_LITE