]> git-server-git.apps.pok.os.sepia.ceph.com Git - rocksdb.git/commitdiff
Made merge_oprator a shared_ptr; and added TTL unit tests
authorDeon Nicholas <dnicholas@fb.com>
Tue, 20 Aug 2013 20:35:28 +0000 (13:35 -0700)
committerDeon Nicholas <dnicholas@fb.com>
Tue, 20 Aug 2013 20:35:28 +0000 (13:35 -0700)
Test Plan:
- make all check;
- make release;
- make stringappend_test; ./stringappend_test

Reviewers: haobo, emayanke

Reviewed By: haobo

CC: leveldb, kailiu
Differential Revision: https://reviews.facebook.net/D12381

13 files changed:
db/builder.cc
db/db_bench.cc
db/db_impl.cc
db/db_iter.cc
db/db_test.cc
db/memtable.cc
db/merge_test.cc
db/version_set.cc
include/leveldb/options.h
tools/db_stress.cc
utilities/merge_operators/string_append/stringappend_test.cc
utilities/ttl/db_ttl.cc
utilities/ttl/db_ttl.h

index 27643ddd9ab3336f52f705f7fc16e7232b3b5ca2..03e7030007a0212cbb4888930bae8ee01eb28212 100644 (file)
@@ -54,7 +54,7 @@ Status BuildTable(const std::string& dbname,
     meta->smallest_seqno = GetInternalKeySeqno(key);
     meta->largest_seqno = meta->smallest_seqno;
 
-    MergeHelper merge(user_comparator, options.merge_operator,
+    MergeHelper merge(user_comparator, options.merge_operator.get(),
                       options.info_log.get(),
                       true /* internal key corruption is not ok */);
 
index 805ac552f53adbd9b1346b9fd65346016b6f6cce..56ddd23561b21d876106ba53052b5b0ca8ea1633 100644 (file)
@@ -637,7 +637,6 @@ class Benchmark {
   int key_size_;
   int entries_per_batch_;
   WriteOptions write_options_;
-  std::shared_ptr<MergeOperator> merge_operator_;
   long reads_;
   long writes_;
   long readwrites_;
@@ -779,7 +778,6 @@ class Benchmark {
     value_size_(FLAGS_value_size),
     key_size_(FLAGS_key_size),
     entries_per_batch_(1),
-    merge_operator_(nullptr),
     reads_(FLAGS_reads < 0 ? FLAGS_num : FLAGS_reads),
     writes_(FLAGS_writes < 0 ? FLAGS_num : FLAGS_writes),
     readwrites_((FLAGS_writes < 0  && FLAGS_reads < 0)? FLAGS_num :
@@ -1212,13 +1210,13 @@ class Benchmark {
     options.bytes_per_sync = FLAGS_bytes_per_sync;
 
     // merge operator options
-    merge_operator_ = MergeOperators::CreateFromStringId(FLAGS_merge_operator);
-    if (merge_operator_ == nullptr && !FLAGS_merge_operator.empty()) {
+    options.merge_operator = MergeOperators::CreateFromStringId(
+        FLAGS_merge_operator);
+    if (options.merge_operator == nullptr && !FLAGS_merge_operator.empty()) {
       fprintf(stderr, "invalid merge operator: %s\n",
               FLAGS_merge_operator.c_str());
       exit(1);
     }
-    options.merge_operator = merge_operator_.get();
 
     Status s;
     if(FLAGS_read_only) {
index 1326148bb729daf958094081131154563b0b3a0b..5ea8ef33e74ef933dbb30f3d953a1afcb8dd9b54 100644 (file)
@@ -1777,7 +1777,7 @@ Status DBImpl::DoCompactionWork(CompactionState* compact) {
   SequenceNumber visible_in_snapshot = kMaxSequenceNumber;
   std::string compaction_filter_value;
   std::vector<char> delete_key; // for compaction filter
-  MergeHelper merge(user_comparator(), options_.merge_operator,
+  MergeHelper merge(user_comparator(), options_.merge_operator.get(),
                     options_.info_log.get(),
                     false /* internal key corruption is expected */);
   auto compaction_filter = options_.compaction_filter;
index 5051b355393bcb1155be985ee83e9602a6324ef4..b0c8e078ede5489adeb5c1af29860613721cfa2b 100644 (file)
@@ -57,7 +57,7 @@ class DBIter: public Iterator {
         env_(env),
         logger_(options.info_log),
         user_comparator_(cmp),
-        user_merge_operator_(options.merge_operator),
+        user_merge_operator_(options.merge_operator.get()),
         iter_(iter),
         sequence_(s),
         direction_(kForward),
index a087edf2c83ebcbd4797f02b3ccf6f93a0f83ecc..870f9fd9861ba71d1251ab883983baec74f4b0d8 100644 (file)
@@ -224,8 +224,6 @@ class DBTest {
   };
   int option_config_;
 
-  std::shared_ptr<MergeOperator> merge_operator_;
-
  public:
   std::string dbname_;
   SpecialEnv* env_;
@@ -242,7 +240,6 @@ class DBTest {
   };
 
   DBTest() : option_config_(kDefault),
-             merge_operator_(MergeOperators::CreatePutOperator()),
              env_(new SpecialEnv(Env::Default())) {
     filter_policy_ = NewBloomFilterPolicy(10);
     dbname_ = test::TmpDir() + "/db_test";
@@ -297,7 +294,7 @@ class DBTest {
     Options options;
     switch (option_config_) {
       case kMergePut:
-        options.merge_operator = merge_operator_.get();
+        options.merge_operator = MergeOperators::CreatePutOperator();
         break;
       case kFilter:
         options.filter_policy = filter_policy_;
index 37ab558521255bb1c51125b0a7bcc5fe93d96865..e2fa482f01330fd02911fa108a9e192634dc6bb7 100644 (file)
@@ -139,7 +139,7 @@ bool MemTable::Get(const LookupKey& key, std::string* value, Status* s,
   assert(operands != nullptr);
 
   bool merge_in_progress = s->IsMergeInProgress();
-  auto merge_operator = options.merge_operator;
+  auto merge_operator = options.merge_operator.get();
   auto logger = options.info_log;
   std::string merge_result;
 
index 837faec3a477a82eee8af6d1407490c0ceb7a368..61e090838cba5f57086421068c2f8d6d6b97a502 100644 (file)
 using namespace std;
 using namespace leveldb;
 
-auto mergeOperator = MergeOperators::CreateUInt64AddOperator();
 
 std::shared_ptr<DB> OpenDb(const string& dbname, const bool ttl = false) {
   DB* db;
   StackableDB* sdb;
   Options options;
   options.create_if_missing = true;
-  options.merge_operator = mergeOperator.get();
+  options.merge_operator = MergeOperators::CreateUInt64AddOperator();
   Status s;
   DestroyDB(dbname, Options());
   if (ttl) {
index 609965224ea7d696806f847c7f866f51d6b9b41a..c22349bea332ebeb9eca3d46b792f9df92331e07 100644 (file)
@@ -381,7 +381,7 @@ void Version::Get(const ReadOptions& options,
   Slice user_key = k.user_key();
   const Comparator* ucmp = vset_->icmp_.user_comparator();
 
-  auto merge_operator = db_options.merge_operator;
+  auto merge_operator = db_options.merge_operator.get();
   auto logger = db_options.info_log;
 
   assert(status->ok() || status->IsMergeInProgress());
index 8e3c64e4a80e5c94e996effe15413a67aafe9740..b34042a00d56950ea3cdc17d1a1a767574cca5fc 100644 (file)
@@ -85,7 +85,7 @@ struct Options {
   // for the first time. It's necessary to specify a merge operator when
   // openning the DB in this case.
   // Default: nullptr
-  const MergeOperator* merge_operator;
+  shared_ptr<MergeOperator> merge_operator;
 
   // The client must provide compaction_filter_factory if it requires a new
   // compaction filter to be used for different compaction processes
index 45cf99f01619186a5d54a2e29d0ad874134a8d54..b8a251e2f3c1f8ae35188fc8d9ada02c2e69a08f 100644 (file)
@@ -537,7 +537,6 @@ class StressTest {
                           FLAGS_test_batches_snapshots ?
                           sizeof(long) : sizeof(long)-1)),
         db_(nullptr),
-        merge_operator_(MergeOperators::CreatePutOperator()),
         num_times_reopened_(0) {
     if (FLAGS_destroy_db_initially) {
       std::vector<std::string> files;
@@ -553,7 +552,6 @@ class StressTest {
 
   ~StressTest() {
     delete db_;
-    merge_operator_ = nullptr;
     delete filter_policy_;
     delete prefix_extractor_;
   }
@@ -1140,7 +1138,7 @@ class StressTest {
     }
 
     if (FLAGS_use_merge_put) {
-      options.merge_operator = merge_operator_.get();
+      options.merge_operator = MergeOperators::CreatePutOperator();
     }
 
     fprintf(stdout, "DB path: [%s]\n", FLAGS_db);
@@ -1188,7 +1186,6 @@ class StressTest {
   const SliceTransform* prefix_extractor_;
   DB* db_;
   StackableDB* sdb_;
-  std::shared_ptr<MergeOperator> merge_operator_;
   int num_times_reopened_;
 };
 
index 5ec30a4c40c95c016c58b2e140bba88d77b6e553..50e3f7779790ab26d75c07d4846e3a2289715995 100644 (file)
@@ -13,6 +13,8 @@
 #include "leveldb/merge_operator.h"
 #include "utilities/merge_operators.h"
 #include "utilities/merge_operators/string_append/stringappend.h"
+#include "utilities/merge_operators/string_append/stringappend2.h"
+#include "utilities/ttl/db_ttl.h"
 #include "util/testharness.h"
 #include "util/random.h"
 
@@ -24,21 +26,29 @@ namespace leveldb {
 const std::string kDbName = "/tmp/mergetestdb";
 
 // OpenDb opens a (possibly new) rocksdb database with a StringAppendOperator
-std::shared_ptr<DB> OpenDb(StringAppendOperator* append_op) {
-    DB* db;
-    Options options;
-    options.create_if_missing = true;
-    options.merge_operator = append_op;
-    Status s = DB::Open(options, kDbName,  &db);
-    if (!s.ok()) {
-      std::cerr << s.ToString() << std::endl;
-      assert(false);
-    }
-    return std::shared_ptr<DB>(db);
+std::shared_ptr<DB> OpenNormalDb(char delim_char) {
+  DB* db;
+  Options options;
+  options.create_if_missing = true;
+  options.merge_operator.reset(new StringAppendOperator(delim_char));
+  ASSERT_OK(DB::Open(options, kDbName,  &db));
+  return std::shared_ptr<DB>(db);
+}
+
+// Open a TtlDB with a non-associative StringAppendTESTOperator
+std::shared_ptr<DB> OpenTtlDb(char delim_char) {
+  StackableDB* db;
+  Options options;
+  options.create_if_missing = true;
+  options.merge_operator.reset(new StringAppendTESTOperator(delim_char));
+  Status s;
+  db = new DBWithTTL(123456, options, kDbName, s, false);
+  ASSERT_OK(s);
+  return std::shared_ptr<DB>(db);
 }
 
 /// StringLists represents a set of string-lists, each with a key-index.
-/// Supports Append(list,string) and Get(list)
+/// Supports Append(list, string) and Get(list)
 class StringLists {
  public:
 
@@ -52,8 +62,8 @@ class StringLists {
 
   // Append string val onto the list defined by key; return true on success
   bool Append(const std::string& key, const std::string& val){
-    Slice valSlice(val.data(),val.size());
-    auto s = db_->Merge(merge_option_,key,valSlice);
+    Slice valSlice(val.data(), val.size());
+    auto s = db_->Merge(merge_option_, key, valSlice);
 
     if (s.ok()) {
       return true;
@@ -66,7 +76,6 @@ class StringLists {
   // Returns the list of strings associated with key (or "" if does not exist)
   bool Get(const std::string& key, std::string* const result){
     assert(result != NULL); // we should have a place to store the result
-
     auto s = db_->Get(get_option_, key, result);
 
     if (s.ok()) {
@@ -86,6 +95,7 @@ class StringLists {
     return false;
   }
 
+
  private:
   std::shared_ptr<DB> db_;
   WriteOptions merge_option_;
@@ -93,23 +103,40 @@ class StringLists {
 
 };
 
+
+// The class for unit-testing
+class StringAppendOperatorTest {
+ public:
+  StringAppendOperatorTest() {
+    DestroyDB(kDbName, Options());    // Start each test with a fresh DB
+  }
+
+  typedef std::shared_ptr<DB> (* OpenFuncPtr)(char);
+
+  // Allows user to open databases with different configurations.
+  // e.g.: Can open a DB or a TtlDB, etc.
+  static void SetOpenDbFunction(OpenFuncPtr func) {
+    OpenDb = func;
+  }
+
+ protected:
+  static OpenFuncPtr OpenDb;
+};
+StringAppendOperatorTest::OpenFuncPtr StringAppendOperatorTest::OpenDb = nullptr;
+
 // THE TEST CASES BEGIN HERE
 
-class StringAppendOperatorTest { };
 TEST(StringAppendOperatorTest, IteratorTest) {
-  DestroyDB(kDbName, Options());    // Start this test with a fresh DB
-
-  StringAppendOperator append_op(',');
-  auto db_ = OpenDb(&append_op);
+  auto db_ = OpenDb(',');
   StringLists slists(db_);
 
-  slists.Append("k1","v1");
-  slists.Append("k1","v2");
-  slists.Append("k1","v3");
+  slists.Append("k1", "v1");
+  slists.Append("k1", "v2");
+  slists.Append("k1", "v3");
 
-  slists.Append("k2","a1");
-  slists.Append("k2","a2");
-  slists.Append("k2","a3");
+  slists.Append("k2", "a1");
+  slists.Append("k2", "a2");
+  slists.Append("k2", "a3");
 
   std::string res;
   std::unique_ptr<leveldb::Iterator> it(db_->NewIterator(ReadOptions()));
@@ -165,7 +192,7 @@ TEST(StringAppendOperatorTest, IteratorTest) {
     }
   }
 
-  slists.Append("k3","g1");
+  slists.Append("k3", "g1");
 
   it.reset(db_->NewIterator(ReadOptions()));
   first = true;
@@ -192,101 +219,86 @@ TEST(StringAppendOperatorTest, IteratorTest) {
 
 }
 
-TEST(StringAppendOperatorTest,SimpleTest) {
-  DestroyDB(kDbName, Options());    // Start this test with a fresh DB
-
-  StringAppendOperator append_op(',');
-  auto db = OpenDb(&append_op);
+TEST(StringAppendOperatorTest, SimpleTest) {
+  auto db = OpenDb(',');
   StringLists slists(db);
 
-  slists.Append("k1","v1");
-  slists.Append("k1","v2");
-  slists.Append("k1","v3");
+  slists.Append("k1", "v1");
+  slists.Append("k1", "v2");
+  slists.Append("k1", "v3");
 
   std::string res;
-  bool status = slists.Get("k1",&res);
+  bool status = slists.Get("k1", &res);
 
   ASSERT_TRUE(status);
-  ASSERT_EQ(res,"v1,v2,v3");
+  ASSERT_EQ(res, "v1,v2,v3");
 }
 
-TEST(StringAppendOperatorTest,SimpleDelimiterTest) {
-  DestroyDB(kDbName, Options());    // Start this test with a fresh DB
-
-  StringAppendOperator append_op('|');
-  auto db = OpenDb(&append_op);
+TEST(StringAppendOperatorTest, SimpleDelimiterTest) {
+  auto db = OpenDb('|');
   StringLists slists(db);
 
-  slists.Append("k1","v1");
-  slists.Append("k1","v2");
-  slists.Append("k1","v3");
+  slists.Append("k1", "v1");
+  slists.Append("k1", "v2");
+  slists.Append("k1", "v3");
 
   std::string res;
-  slists.Get("k1",&res);
-  ASSERT_EQ(res,"v1|v2|v3");
+  slists.Get("k1", &res);
+  ASSERT_EQ(res, "v1|v2|v3");
 }
 
-TEST(StringAppendOperatorTest,OneValueNoDelimiterTest) {
-  DestroyDB(kDbName, Options());    // Start this test with a fresh DB
-
-  StringAppendOperator append_op('!');
-  auto db = OpenDb(&append_op);
+TEST(StringAppendOperatorTest, OneValueNoDelimiterTest) {
+  auto db = OpenDb('!');
   StringLists slists(db);
 
-  slists.Append("random_key","single_val");
+  slists.Append("random_key", "single_val");
 
   std::string res;
-  slists.Get("random_key",&res);
-  ASSERT_EQ(res,"single_val");
+  slists.Get("random_key", &res);
+  ASSERT_EQ(res, "single_val");
 }
 
-TEST(StringAppendOperatorTest,VariousKeys) {
-  DestroyDB(kDbName, Options());    // Start this test with a fresh DB
-
-  StringAppendOperator append_op('\n');
-  auto db = OpenDb(&append_op);
+TEST(StringAppendOperatorTest, VariousKeys) {
+  auto db = OpenDb('\n');
   StringLists slists(db);
 
-  slists.Append("c","asdasd");
-  slists.Append("a","x");
-  slists.Append("b","y");
-  slists.Append("a","t");
-  slists.Append("a","r");
-  slists.Append("b","2");
-  slists.Append("c","asdasd");
+  slists.Append("c", "asdasd");
+  slists.Append("a", "x");
+  slists.Append("b", "y");
+  slists.Append("a", "t");
+  slists.Append("a", "r");
+  slists.Append("b", "2");
+  slists.Append("c", "asdasd");
 
-  std::string a,b,c;
-  bool sa,sb,sc;
-  sa = slists.Get("a",&a);
-  sb = slists.Get("b",&b);
-  sc = slists.Get("c",&c);
+  std::string a, b, c;
+  bool sa, sb, sc;
+  sa = slists.Get("a", &a);
+  sb = slists.Get("b", &b);
+  sc = slists.Get("c", &c);
 
   ASSERT_TRUE(sa && sb && sc); // All three keys should have been found
 
-  ASSERT_EQ(a,"x\nt\nr");
-  ASSERT_EQ(b,"y\n2");
-  ASSERT_EQ(c,"asdasd\nasdasd");
+  ASSERT_EQ(a, "x\nt\nr");
+  ASSERT_EQ(b, "y\n2");
+  ASSERT_EQ(c, "asdasd\nasdasd");
 }
 
 // Generate semi random keys/words from a small distribution.
-TEST(StringAppendOperatorTest,RandomMixGetAppend) {
-  DestroyDB(kDbName, Options());    // Start this test with a fresh DB
-
-  StringAppendOperator append_op(' ');
-  auto db = OpenDb(&append_op);
+TEST(StringAppendOperatorTest, RandomMixGetAppend) {
+  auto db = OpenDb(' ');
   StringLists slists(db);
 
   // Generate a list of random keys and values
   const int kWordCount = 15;
-  std::string words[] = {"sdasd","triejf","fnjsdfn","dfjisdfsf","342839",
-                         "dsuha","mabuais","sadajsid","jf9834hf","2d9j89",
-                         "dj9823jd","a","dk02ed2dh","$(jd4h984$(*", "mabz"};
+  std::string words[] = {"sdasd", "triejf", "fnjsdfn", "dfjisdfsf", "342839",
+                         "dsuha", "mabuais", "sadajsid", "jf9834hf", "2d9j89",
+                         "dj9823jd", "a", "dk02ed2dh", "$(jd4h984$(*", "mabz"};
   const int kKeyCount = 6;
-  std::string keys[] = {"dhaiusdhu","denidw","daisda","keykey","muki",
+  std::string keys[] = {"dhaiusdhu", "denidw", "daisda", "keykey", "muki",
                         "shzassdianmd"};
 
   // Will store a local copy of all data in order to verify correctness
-  std::map<std::string,std::string> parallel_copy;
+  std::map<std::string, std::string> parallel_copy;
 
   // Generate a bunch of random queries (Append and Get)!
   enum query_t  { APPEND_OP, GET_OP, NUM_OPS };
@@ -299,14 +311,11 @@ TEST(StringAppendOperatorTest,RandomMixGetAppend) {
     std::string key = keys[randomGen.Uniform((int)kKeyCount)];
     std::string word = words[randomGen.Uniform((int)kWordCount)];
 
-    // Debug message.
-    //std::cout << (int)query << " " << key << " " << word << std::endl;
-
     // Apply the query and any checks.
     if (query == APPEND_OP) {
 
       // Apply the rocksdb test-harness Append defined above
-      slists.Append(key,word);  //apply the rocksdb append
+      slists.Append(key, word);  //apply the rocksdb append
 
       // Apply the similar "Append" to the parallel copy
       if (parallel_copy[key].size() > 0) {
@@ -318,32 +327,29 @@ TEST(StringAppendOperatorTest,RandomMixGetAppend) {
     } else if (query == GET_OP) {
       // Assumes that a non-existent key just returns <empty>
       std::string res;
-      slists.Get(key,&res);
-      ASSERT_EQ(res,parallel_copy[key]);
+      slists.Get(key, &res);
+      ASSERT_EQ(res, parallel_copy[key]);
     }
 
   }
 
 }
 
-TEST(StringAppendOperatorTest,BIGRandomMixGetAppend) {
-  DestroyDB(kDbName, Options());    // Start this test with a fresh DB
-
-  StringAppendOperator append_op(' ');
-  auto db = OpenDb(&append_op);
+TEST(StringAppendOperatorTest, BIGRandomMixGetAppend) {
+  auto db = OpenDb(' ');
   StringLists slists(db);
 
   // Generate a list of random keys and values
   const int kWordCount = 15;
-  std::string words[] = {"sdasd","triejf","fnjsdfn","dfjisdfsf","342839",
-                         "dsuha","mabuais","sadajsid","jf9834hf","2d9j89",
-                         "dj9823jd","a","dk02ed2dh","$(jd4h984$(*", "mabz"};
+  std::string words[] = {"sdasd", "triejf", "fnjsdfn", "dfjisdfsf", "342839",
+                         "dsuha", "mabuais", "sadajsid", "jf9834hf", "2d9j89",
+                         "dj9823jd", "a", "dk02ed2dh", "$(jd4h984$(*", "mabz"};
   const int kKeyCount = 6;
-  std::string keys[] = {"dhaiusdhu","denidw","daisda","keykey","muki",
+  std::string keys[] = {"dhaiusdhu", "denidw", "daisda", "keykey", "muki",
                         "shzassdianmd"};
 
   // Will store a local copy of all data in order to verify correctness
-  std::map<std::string,std::string> parallel_copy;
+  std::map<std::string, std::string> parallel_copy;
 
   // Generate a bunch of random queries (Append and Get)!
   enum query_t  { APPEND_OP, GET_OP, NUM_OPS };
@@ -356,14 +362,11 @@ TEST(StringAppendOperatorTest,BIGRandomMixGetAppend) {
     std::string key = keys[randomGen.Uniform((int)kKeyCount)];
     std::string word = words[randomGen.Uniform((int)kWordCount)];
 
-    // Debug message.
-    //std::cout << (int)query << " " << key << " " << word << std::endl;
-
     //Apply the query and any checks.
     if (query == APPEND_OP) {
 
       // Apply the rocksdb test-harness Append defined above
-      slists.Append(key,word);  //apply the rocksdb append
+      slists.Append(key, word);  //apply the rocksdb append
 
       // Apply the similar "Append" to the parallel copy
       if (parallel_copy[key].size() > 0) {
@@ -375,8 +378,8 @@ TEST(StringAppendOperatorTest,BIGRandomMixGetAppend) {
     } else if (query == GET_OP) {
       // Assumes that a non-existent key just returns <empty>
       std::string res;
-      slists.Get(key,&res);
-      ASSERT_EQ(res,parallel_copy[key]);
+      slists.Get(key, &res);
+      ASSERT_EQ(res, parallel_copy[key]);
     }
 
   }
@@ -384,191 +387,179 @@ TEST(StringAppendOperatorTest,BIGRandomMixGetAppend) {
 }
 
 
-TEST(StringAppendOperatorTest,PersistentVariousKeys) {
-  DestroyDB(kDbName, Options());    // Start this test with a fresh DB
-
+TEST(StringAppendOperatorTest, PersistentVariousKeys) {
   // Perform the following operations in limited scope
   {
-    StringAppendOperator append_op('\n');
-    auto db = OpenDb(&append_op);
+    auto db = OpenDb('\n');
     StringLists slists(db);
 
-    slists.Append("c","asdasd");
-    slists.Append("a","x");
-    slists.Append("b","y");
-    slists.Append("a","t");
-    slists.Append("a","r");
-    slists.Append("b","2");
-    slists.Append("c","asdasd");
-
-    std::string a,b,c;
-    slists.Get("a",&a);
-    slists.Get("b",&b);
-    slists.Get("c",&c);
-
-    ASSERT_EQ(a,"x\nt\nr");
-    ASSERT_EQ(b,"y\n2");
-    ASSERT_EQ(c,"asdasd\nasdasd");
+    slists.Append("c", "asdasd");
+    slists.Append("a", "x");
+    slists.Append("b", "y");
+    slists.Append("a", "t");
+    slists.Append("a", "r");
+    slists.Append("b", "2");
+    slists.Append("c", "asdasd");
+
+    std::string a, b, c;
+    slists.Get("a", &a);
+    slists.Get("b", &b);
+    slists.Get("c", &c);
+
+    ASSERT_EQ(a, "x\nt\nr");
+    ASSERT_EQ(b, "y\n2");
+    ASSERT_EQ(c, "asdasd\nasdasd");
   }
 
   // Reopen the database (the previous changes should persist / be remembered)
   {
-    StringAppendOperator append_op('\n');
-    auto db = OpenDb(&append_op);
+    auto db = OpenDb('\n');
     StringLists slists(db);
 
-    slists.Append("c","bbnagnagsx");
-    slists.Append("a","sa");
-    slists.Append("b","df");
-    slists.Append("a","gh");
-    slists.Append("a","jk");
-    slists.Append("b","l;");
-    slists.Append("c","rogosh");
+    slists.Append("c", "bbnagnagsx");
+    slists.Append("a", "sa");
+    slists.Append("b", "df");
+    slists.Append("a", "gh");
+    slists.Append("a", "jk");
+    slists.Append("b", "l;");
+    slists.Append("c", "rogosh");
 
     // The previous changes should be on disk (L0)
     // The most recent changes should be in memory (MemTable)
     // Hence, this will test both Get() paths.
-    std::string a,b,c;
-    slists.Get("a",&a);
-    slists.Get("b",&b);
-    slists.Get("c",&c);
-
-    ASSERT_EQ(a,"x\nt\nr\nsa\ngh\njk");
-    ASSERT_EQ(b,"y\n2\ndf\nl;");
-    ASSERT_EQ(c,"asdasd\nasdasd\nbbnagnagsx\nrogosh");
+    std::string a, b, c;
+    slists.Get("a", &a);
+    slists.Get("b", &b);
+    slists.Get("c", &c);
+
+    ASSERT_EQ(a, "x\nt\nr\nsa\ngh\njk");
+    ASSERT_EQ(b, "y\n2\ndf\nl;");
+    ASSERT_EQ(c, "asdasd\nasdasd\nbbnagnagsx\nrogosh");
   }
 
   // Reopen the database (the previous changes should persist / be remembered)
   {
-    StringAppendOperator append_op('\n');
-    auto db = OpenDb(&append_op);
+    auto db = OpenDb('\n');
     StringLists slists(db);
 
     // All changes should be on disk. This will test VersionSet Get()
-    std::string a,b,c;
-    slists.Get("a",&a);
-    slists.Get("b",&b);
-    slists.Get("c",&c);
-
-    ASSERT_EQ(a,"x\nt\nr\nsa\ngh\njk");
-    ASSERT_EQ(b,"y\n2\ndf\nl;");
-    ASSERT_EQ(c,"asdasd\nasdasd\nbbnagnagsx\nrogosh");
+    std::string a, b, c;
+    slists.Get("a", &a);
+    slists.Get("b", &b);
+    slists.Get("c", &c);
+
+    ASSERT_EQ(a, "x\nt\nr\nsa\ngh\njk");
+    ASSERT_EQ(b, "y\n2\ndf\nl;");
+    ASSERT_EQ(c, "asdasd\nasdasd\nbbnagnagsx\nrogosh");
   }
 }
 
-TEST(StringAppendOperatorTest,PersistentFlushAndCompaction) {
-  DestroyDB(kDbName, Options());    // Start this test with a fresh DB
-
-  StringAppendOperator append_op('\n');
-
+TEST(StringAppendOperatorTest, PersistentFlushAndCompaction) {
   // Perform the following operations in limited scope
   {
-    auto db = OpenDb(&append_op);
+    auto db = OpenDb('\n');
     StringLists slists(db);
-    std::string a,b,c;
+    std::string a, b, c;
     bool success;
 
     // Append, Flush, Get
-    slists.Append("c","asdasd");
+    slists.Append("c", "asdasd");
     db->Flush(leveldb::FlushOptions());
-    success = slists.Get("c",&c);
+    success = slists.Get("c", &c);
     ASSERT_TRUE(success);
-    ASSERT_EQ(c,"asdasd");
+    ASSERT_EQ(c, "asdasd");
 
     // Append, Flush, Append, Get
-    slists.Append("a","x");
-    slists.Append("b","y");
+    slists.Append("a", "x");
+    slists.Append("b", "y");
     db->Flush(leveldb::FlushOptions());
-    slists.Append("a","t");
-    slists.Append("a","r");
-    slists.Append("b","2");
+    slists.Append("a", "t");
+    slists.Append("a", "r");
+    slists.Append("b", "2");
 
-    success = slists.Get("a",&a);
+    success = slists.Get("a", &a);
     assert(success == true);
-    ASSERT_EQ(a,"x\nt\nr");
+    ASSERT_EQ(a, "x\nt\nr");
 
-    success = slists.Get("b",&b);
+    success = slists.Get("b", &b);
     assert(success == true);
-    ASSERT_EQ(b,"y\n2");
+    ASSERT_EQ(b, "y\n2");
 
     // Append, Get
-    success = slists.Append("c","asdasd");
+    success = slists.Append("c", "asdasd");
     assert(success);
-    success = slists.Append("b","monkey");
+    success = slists.Append("b", "monkey");
     assert(success);
 
     // I omit the "assert(success)" checks here.
-    slists.Get("a",&a);
-    slists.Get("b",&b);
-    slists.Get("c",&c);
+    slists.Get("a", &a);
+    slists.Get("b", &b);
+    slists.Get("c", &c);
 
-    ASSERT_EQ(a,"x\nt\nr");
-    ASSERT_EQ(b,"y\n2\nmonkey");
-    ASSERT_EQ(c,"asdasd\nasdasd");
+    ASSERT_EQ(a, "x\nt\nr");
+    ASSERT_EQ(b, "y\n2\nmonkey");
+    ASSERT_EQ(c, "asdasd\nasdasd");
   }
 
   // Reopen the database (the previous changes should persist / be remembered)
   {
-    auto db = OpenDb(&append_op);
+    auto db = OpenDb('\n');
     StringLists slists(db);
-    std::string a,b,c;
+    std::string a, b, c;
 
     // Get (Quick check for persistence of previous database)
-    slists.Get("a",&a);
-    ASSERT_EQ(a,"x\nt\nr");
+    slists.Get("a", &a);
+    ASSERT_EQ(a, "x\nt\nr");
 
     //Append, Compact, Get
-    slists.Append("c","bbnagnagsx");
-    slists.Append("a","sa");
-    slists.Append("b","df");
-    db->CompactRange(nullptr,nullptr);
-    slists.Get("a",&a);
-    slists.Get("b",&b);
-    slists.Get("c",&c);
-    ASSERT_EQ(a,"x\nt\nr\nsa");
-    ASSERT_EQ(b,"y\n2\nmonkey\ndf");
-    ASSERT_EQ(c,"asdasd\nasdasd\nbbnagnagsx");
+    slists.Append("c", "bbnagnagsx");
+    slists.Append("a", "sa");
+    slists.Append("b", "df");
+    db->CompactRange(nullptr, nullptr);
+    slists.Get("a", &a);
+    slists.Get("b", &b);
+    slists.Get("c", &c);
+    ASSERT_EQ(a, "x\nt\nr\nsa");
+    ASSERT_EQ(b, "y\n2\nmonkey\ndf");
+    ASSERT_EQ(c, "asdasd\nasdasd\nbbnagnagsx");
 
     // Append, Get
-    slists.Append("a","gh");
-    slists.Append("a","jk");
-    slists.Append("b","l;");
-    slists.Append("c","rogosh");
-    slists.Get("a",&a);
-    slists.Get("b",&b);
-    slists.Get("c",&c);
-    ASSERT_EQ(a,"x\nt\nr\nsa\ngh\njk");
-    ASSERT_EQ(b,"y\n2\nmonkey\ndf\nl;");
-    ASSERT_EQ(c,"asdasd\nasdasd\nbbnagnagsx\nrogosh");
+    slists.Append("a", "gh");
+    slists.Append("a", "jk");
+    slists.Append("b", "l;");
+    slists.Append("c", "rogosh");
+    slists.Get("a", &a);
+    slists.Get("b", &b);
+    slists.Get("c", &c);
+    ASSERT_EQ(a, "x\nt\nr\nsa\ngh\njk");
+    ASSERT_EQ(b, "y\n2\nmonkey\ndf\nl;");
+    ASSERT_EQ(c, "asdasd\nasdasd\nbbnagnagsx\nrogosh");
 
     // Compact, Get
-    db->CompactRange(nullptr,nullptr);
-    ASSERT_EQ(a,"x\nt\nr\nsa\ngh\njk");
-    ASSERT_EQ(b,"y\n2\nmonkey\ndf\nl;");
-    ASSERT_EQ(c,"asdasd\nasdasd\nbbnagnagsx\nrogosh");
+    db->CompactRange(nullptr, nullptr);
+    ASSERT_EQ(a, "x\nt\nr\nsa\ngh\njk");
+    ASSERT_EQ(b, "y\n2\nmonkey\ndf\nl;");
+    ASSERT_EQ(c, "asdasd\nasdasd\nbbnagnagsx\nrogosh");
 
     // Append, Flush, Compact, Get
-    slists.Append("b","afcg");
+    slists.Append("b", "afcg");
     db->Flush(leveldb::FlushOptions());
-    db->CompactRange(nullptr,nullptr);
-    slists.Get("b",&b);
-    ASSERT_EQ(b,"y\n2\nmonkey\ndf\nl;\nafcg");
+    db->CompactRange(nullptr, nullptr);
+    slists.Get("b", &b);
+    ASSERT_EQ(b, "y\n2\nmonkey\ndf\nl;\nafcg");
   }
 }
 
-TEST(StringAppendOperatorTest,SimpleTestNullDelimiter) {
-  DestroyDB(kDbName, Options());    // Start this test with a fresh DB
-
-  StringAppendOperator append_op('\0');
-  auto db = OpenDb(&append_op);
+TEST(StringAppendOperatorTest, SimpleTestNullDelimiter) {
+  auto db = OpenDb('\0');
   StringLists slists(db);
 
-  slists.Append("k1","v1");
-  slists.Append("k1","v2");
-  slists.Append("k1","v3");
+  slists.Append("k1", "v1");
+  slists.Append("k1", "v2");
+  slists.Append("k1", "v3");
 
   std::string res;
-  bool status = slists.Get("k1",&res);
+  bool status = slists.Get("k1", &res);
   ASSERT_TRUE(status);
 
   // Construct the desired string. Default constructor doesn't like '\0' chars.
@@ -579,13 +570,25 @@ TEST(StringAppendOperatorTest,SimpleTestNullDelimiter) {
 
   // Check that the leveldb result string matches the desired string
   assert(res.size() == checker.size());
-  ASSERT_EQ(res,checker);
+  ASSERT_EQ(res, checker);
 }
 
-
 } // namespace leveldb
 
 int main(int arc, char** argv) {
-  leveldb::test::RunAllTests();
+  // Run with regular database
+  {
+    fprintf(stderr, "Running tests with regular db and operator.\n");
+    StringAppendOperatorTest::SetOpenDbFunction(&OpenNormalDb);
+    leveldb::test::RunAllTests();
+  }
+
+  // Run with TTL
+  {
+    fprintf(stderr, "Running tests with ttl db and generic operator.\n");
+    StringAppendOperatorTest::SetOpenDbFunction(&OpenTtlDb);
+    leveldb::test::RunAllTests();
+  }
+
   return 0;
 }
index 9babecd0fab25230eeccc5aef54846e711ca112b..a7e6b938af8504d20cbad1f881fe5384da8b5d72 100644 (file)
@@ -32,8 +32,8 @@ DBWithTTL::DBWithTTL(const int32_t ttl,
   }
 
   if (options.merge_operator) {
-    ttl_merge_op_.reset(new TtlMergeOperator(options.merge_operator));
-    options_to_open.merge_operator = ttl_merge_op_.get();
+    options_to_open.merge_operator.reset(
+      new TtlMergeOperator(options.merge_operator));
   }
 
   if (read_only) {
index dbba5c63ae4a91c19818108914374eb4e5893ac8..3a6103ac2912ff50f17b70dee6683c67ba50cc17 100644 (file)
@@ -112,7 +112,6 @@ class DBWithTTL : public StackableDB {
  private:
   DB* db_;
   int32_t ttl_;
-  unique_ptr<MergeOperator> ttl_merge_op_;
   unique_ptr<CompactionFilter> ttl_comp_filter_;
 };
 
@@ -258,7 +257,7 @@ class TtlCompactionFilterFactory : public CompactionFilterFactory {
 class TtlMergeOperator : public MergeOperator {
 
  public:
-  explicit TtlMergeOperator(const MergeOperator* merge_op)
+  explicit TtlMergeOperator(const std::shared_ptr<MergeOperator> merge_op)
     : user_merge_op_(merge_op) {
     assert(merge_op);
   }
@@ -356,7 +355,7 @@ class TtlMergeOperator : public MergeOperator {
   }
 
  private:
-  const MergeOperator* user_merge_op_;
+  std::shared_ptr<MergeOperator> user_merge_op_;
 };
 
 }