]> git-server-git.apps.pok.os.sepia.ceph.com Git - rocksdb.git/commitdiff
optimistic transactions support for reinitialization
authoragiardullo <agiardullo@fb.com>
Fri, 4 Mar 2016 00:33:26 +0000 (16:33 -0800)
committeragiardullo <agiardullo@fb.com>
Tue, 8 Mar 2016 03:03:09 +0000 (19:03 -0800)
Summary: Extend optimization in D53835 to optimistic transactions for completeness.

Test Plan: added test

Reviewers: sdong, IslamAbdelRahman, horuff, jkedgar

Reviewed By: horuff

Subscribers: dhruba, leveldb

Differential Revision: https://reviews.facebook.net/D55059

include/rocksdb/utilities/optimistic_transaction_db.h
utilities/transactions/optimistic_transaction_db_impl.cc
utilities/transactions/optimistic_transaction_db_impl.h
utilities/transactions/optimistic_transaction_impl.cc
utilities/transactions/optimistic_transaction_impl.h
utilities/transactions/optimistic_transaction_test.cc

index 42ebe191fa24daa1845c1c4230f7c20a2c05daa7..b2c2f99a878f548fa4294dbaf95f8369117d49ab 100644 (file)
@@ -43,15 +43,19 @@ class OptimisticTransactionDB {
 
   virtual ~OptimisticTransactionDB() {}
 
-  // Starts a new Transaction.  Passing set_snapshot=true has the same effect
-  // as calling SetSnapshot().
+  // Starts a new Transaction.
   //
-  // Caller should delete the returned transaction after calling
-  // Commit() or Rollback().
+  // Caller is responsible for deleting the returned transaction when no
+  // longer needed.
+  //
+  // If old_txn is not null, BeginTransaction will reuse this Transaction
+  // handle instead of allocating a new one.  This is an optimization to avoid
+  // extra allocations when repeatedly creating transactions.
   virtual Transaction* BeginTransaction(
       const WriteOptions& write_options,
-      const OptimisticTransactionOptions&
-          txn_options = OptimisticTransactionOptions()) = 0;
+      const OptimisticTransactionOptions& txn_options =
+          OptimisticTransactionOptions(),
+      Transaction* old_txn = nullptr) = 0;
 
   // Return the underlying Database that was opened
   virtual DB* GetBaseDB() = 0;
index d54173d3d6599e660fe7d9827acc513e3506e23b..190440242a3b984b6c19204fab65ce30dbbeb1e9 100644 (file)
@@ -5,11 +5,11 @@
 
 #ifndef ROCKSDB_LITE
 
+#include "utilities/transactions/optimistic_transaction_db_impl.h"
+
 #include <string>
 #include <vector>
 
-#include "utilities/transactions/optimistic_transaction_db_impl.h"
-
 #include "db/db_impl.h"
 #include "rocksdb/db.h"
 #include "rocksdb/options.h"
@@ -20,11 +20,13 @@ namespace rocksdb {
 
 Transaction* OptimisticTransactionDBImpl::BeginTransaction(
     const WriteOptions& write_options,
-    const OptimisticTransactionOptions& txn_options) {
-  Transaction* txn =
-      new OptimisticTransactionImpl(this, write_options, txn_options);
-
-  return txn;
+    const OptimisticTransactionOptions& txn_options, Transaction* old_txn) {
+  if (old_txn != nullptr) {
+    ReinitializeTransaction(old_txn, write_options, txn_options);
+    return old_txn;
+  } else {
+    return new OptimisticTransactionImpl(this, write_options, txn_options);
+  }
 }
 
 Status OptimisticTransactionDB::Open(const Options& options,
@@ -76,5 +78,14 @@ Status OptimisticTransactionDB::Open(
   return s;
 }
 
+void OptimisticTransactionDBImpl::ReinitializeTransaction(
+    Transaction* txn, const WriteOptions& write_options,
+    const OptimisticTransactionOptions& txn_options) {
+  assert(dynamic_cast<OptimisticTransactionImpl*>(txn) != nullptr);
+  auto txn_impl = reinterpret_cast<OptimisticTransactionImpl*>(txn);
+
+  txn_impl->Reinitialize(this, write_options, txn_options);
+}
+
 }  //  namespace rocksdb
 #endif  // ROCKSDB_LITE
index 72f18618873921f499a2faf3e7d11eed681246de..e426a21bec294eb25fdb4941c89c2e4537fdd4b5 100644 (file)
@@ -19,14 +19,19 @@ class OptimisticTransactionDBImpl : public OptimisticTransactionDB {
 
   ~OptimisticTransactionDBImpl() {}
 
-  Transaction* BeginTransaction(
-      const WriteOptions& write_options,
-      const OptimisticTransactionOptions& txn_options) override;
+  Transaction* BeginTransaction(const WriteOptions& write_options,
+                                const OptimisticTransactionOptions& txn_options,
+                                Transaction* old_txn) override;
 
   DB* GetBaseDB() override { return db_.get(); }
 
  private:
   std::unique_ptr<DB> db_;
+
+  void ReinitializeTransaction(Transaction* txn,
+                               const WriteOptions& write_options,
+                               const OptimisticTransactionOptions& txn_options =
+                                   OptimisticTransactionOptions());
 };
 
 }  //  namespace rocksdb
index 5cb1a8f8d6419a23818f37c1f38495475c62f7eb..2647b3dd7193c32196fd97bfc7816df9cd5b8aec 100644 (file)
@@ -28,11 +28,23 @@ OptimisticTransactionImpl::OptimisticTransactionImpl(
     OptimisticTransactionDB* txn_db, const WriteOptions& write_options,
     const OptimisticTransactionOptions& txn_options)
     : TransactionBaseImpl(txn_db->GetBaseDB(), write_options), txn_db_(txn_db) {
+  Initialize(txn_options);
+}
+
+void OptimisticTransactionImpl::Initialize(
+    const OptimisticTransactionOptions& txn_options) {
   if (txn_options.set_snapshot) {
     SetSnapshot();
   }
 }
 
+void OptimisticTransactionImpl::Reinitialize(
+    OptimisticTransactionDB* txn_db, const WriteOptions& write_options,
+    const OptimisticTransactionOptions& txn_options) {
+  TransactionBaseImpl::Reinitialize(txn_db->GetBaseDB(), write_options);
+  Initialize(txn_options);
+}
+
 OptimisticTransactionImpl::~OptimisticTransactionImpl() {
 }
 
index cbd16750524d3842061353d5032de3e5cc2c1844..4876a100d56db5a3783e5ce3c6b269cfbe822ee4 100644 (file)
@@ -34,6 +34,10 @@ class OptimisticTransactionImpl : public TransactionBaseImpl {
 
   virtual ~OptimisticTransactionImpl();
 
+  void Reinitialize(OptimisticTransactionDB* txn_db,
+                    const WriteOptions& write_options,
+                    const OptimisticTransactionOptions& txn_options);
+
   Status Commit() override;
 
   void Rollback() override;
@@ -47,6 +51,8 @@ class OptimisticTransactionImpl : public TransactionBaseImpl {
 
   friend class OptimisticTransactionCallback;
 
+  void Initialize(const OptimisticTransactionOptions& txn_options);
+
   // Returns OK if it is safe to commit this transaction.  Returns Status::Busy
   // if there are read or write conflicts that would prevent us from committing
   // OR if we can not determine whether there would be any such conflicts.
index 9917717577237f72765890f21a693ece352d9683..b672b8722ae131a1b3a77c6b22751a7c8daa0432 100644 (file)
@@ -1267,6 +1267,90 @@ TEST_F(OptimisticTransactionTest, UndoGetForUpdateTest) {
   delete txn1;
 }
 
+TEST_F(OptimisticTransactionTest, ReinitializeTest) {
+  WriteOptions write_options;
+  ReadOptions read_options;
+  OptimisticTransactionOptions txn_options;
+  string value;
+  Status s;
+
+  Transaction* txn1 = txn_db->BeginTransaction(write_options, txn_options);
+
+  txn1 = txn_db->BeginTransaction(write_options, txn_options, txn1);
+
+  s = txn1->Put("Z", "z");
+  ASSERT_OK(s);
+
+  s = txn1->Commit();
+  ASSERT_OK(s);
+
+  txn1 = txn_db->BeginTransaction(write_options, txn_options, txn1);
+
+  s = txn1->Put("Z", "zz");
+  ASSERT_OK(s);
+
+  // Reinitilize txn1 and verify that zz is not written
+  txn1 = txn_db->BeginTransaction(write_options, txn_options, txn1);
+
+  s = txn1->Commit();
+  ASSERT_OK(s);
+  s = db->Get(read_options, "Z", &value);
+  ASSERT_OK(s);
+  ASSERT_EQ(value, "z");
+
+  // Verify snapshots get reinitialized correctly
+  txn1->SetSnapshot();
+  s = txn1->Put("Z", "zzzz");
+  ASSERT_OK(s);
+
+  s = txn1->Commit();
+  ASSERT_OK(s);
+
+  s = db->Get(read_options, "Z", &value);
+  ASSERT_OK(s);
+  ASSERT_EQ(value, "zzzz");
+
+  const Snapshot* snapshot = txn1->GetSnapshot();
+  ASSERT_TRUE(snapshot);
+
+  txn1 = txn_db->BeginTransaction(write_options, txn_options, txn1);
+  snapshot = txn1->GetSnapshot();
+  ASSERT_FALSE(snapshot);
+
+  txn_options.set_snapshot = true;
+  txn1 = txn_db->BeginTransaction(write_options, txn_options, txn1);
+  snapshot = txn1->GetSnapshot();
+  ASSERT_TRUE(snapshot);
+
+  s = txn1->Put("Z", "a");
+  ASSERT_OK(s);
+
+  txn1->Rollback();
+
+  s = txn1->Put("Y", "y");
+  ASSERT_OK(s);
+
+  txn_options.set_snapshot = false;
+  txn1 = txn_db->BeginTransaction(write_options, txn_options, txn1);
+  snapshot = txn1->GetSnapshot();
+  ASSERT_FALSE(snapshot);
+
+  s = txn1->Put("X", "x");
+  ASSERT_OK(s);
+
+  s = txn1->Commit();
+  ASSERT_OK(s);
+
+  s = db->Get(read_options, "Z", &value);
+  ASSERT_OK(s);
+  ASSERT_EQ(value, "zzzz");
+
+  s = db->Get(read_options, "Y", &value);
+  ASSERT_TRUE(s.IsNotFound());
+
+  delete txn1;
+}
+
 }  // namespace rocksdb
 
 int main(int argc, char** argv) {