1 //  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2 //  This source code is licensed under both the GPLv2 (found in the
3 //  COPYING file in the root directory) and Apache 2.0 License
4 //  (found in the LICENSE.Apache file in the root directory).
5 
6 #pragma once
7 #ifndef ROCKSDB_LITE
8 
9 #include <mutex>
10 #include <vector>
11 #include <algorithm>
12 
13 #include "rocksdb/db.h"
14 #include "rocksdb/options.h"
15 #include "rocksdb/utilities/optimistic_transaction_db.h"
16 
17 namespace ROCKSDB_NAMESPACE {
18 
19 class OptimisticTransactionDBImpl : public OptimisticTransactionDB {
20  public:
21   explicit OptimisticTransactionDBImpl(
22       DB* db, const OptimisticTransactionDBOptions& occ_options,
23       bool take_ownership = true)
OptimisticTransactionDB(db)24       : OptimisticTransactionDB(db),
25         db_owner_(take_ownership),
26         validate_policy_(occ_options.validate_policy) {
27     if (validate_policy_ == OccValidationPolicy::kValidateParallel) {
28       uint32_t bucket_size = std::max(16u, occ_options.occ_lock_buckets);
29       bucketed_locks_.reserve(bucket_size);
30       for (size_t i = 0; i < bucket_size; ++i) {
31         bucketed_locks_.emplace_back(
32             std::unique_ptr<std::mutex>(new std::mutex));
33       }
34     }
35   }
36 
~OptimisticTransactionDBImpl()37   ~OptimisticTransactionDBImpl() {
38     // Prevent this stackable from destroying
39     // base db
40     if (!db_owner_) {
41       db_ = nullptr;
42     }
43   }
44 
45   Transaction* BeginTransaction(const WriteOptions& write_options,
46                                 const OptimisticTransactionOptions& txn_options,
47                                 Transaction* old_txn) override;
48 
GetLockBucketsSize()49   size_t GetLockBucketsSize() const { return bucketed_locks_.size(); }
50 
GetValidatePolicy()51   OccValidationPolicy GetValidatePolicy() const { return validate_policy_; }
52 
53   std::unique_lock<std::mutex> LockBucket(size_t idx);
54 
55  private:
56   // NOTE: used in validation phase. Each key is hashed into some
57   // bucket. We then take the lock in the hash value order to avoid deadlock.
58   std::vector<std::unique_ptr<std::mutex>> bucketed_locks_;
59 
60   bool db_owner_;
61 
62   const OccValidationPolicy validate_policy_;
63 
64   void ReinitializeTransaction(Transaction* txn,
65                                const WriteOptions& write_options,
66                                const OptimisticTransactionOptions& txn_options =
67                                    OptimisticTransactionOptions());
68 };
69 
70 }  // namespace ROCKSDB_NAMESPACE
71 #endif  // ROCKSDB_LITE
72