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 8 #ifndef ROCKSDB_LITE 9 10 #include <string> 11 #include <unordered_map> 12 13 #include "db/dbformat.h" 14 #include "db/read_callback.h" 15 16 #include "rocksdb/db.h" 17 #include "rocksdb/slice.h" 18 #include "rocksdb/status.h" 19 #include "rocksdb/types.h" 20 21 namespace ROCKSDB_NAMESPACE { 22 23 struct TransactionKeyMapInfo { 24 // Earliest sequence number that is relevant to this transaction for this key 25 SequenceNumber seq; 26 27 uint32_t num_writes; 28 uint32_t num_reads; 29 30 bool exclusive; 31 TransactionKeyMapInfoTransactionKeyMapInfo32 explicit TransactionKeyMapInfo(SequenceNumber seq_no) 33 : seq(seq_no), num_writes(0), num_reads(0), exclusive(false) {} 34 35 // Used in PopSavePoint to collapse two savepoints together. MergeTransactionKeyMapInfo36 void Merge(const TransactionKeyMapInfo& info) { 37 assert(seq <= info.seq); 38 num_reads += info.num_reads; 39 num_writes += info.num_writes; 40 exclusive |= info.exclusive; 41 } 42 }; 43 44 using TransactionKeyMap = 45 std::unordered_map<uint32_t, 46 std::unordered_map<std::string, TransactionKeyMapInfo>>; 47 48 class DBImpl; 49 struct SuperVersion; 50 class WriteBatchWithIndex; 51 52 class TransactionUtil { 53 public: 54 // Verifies there have been no commits to this key in the db since this 55 // sequence number. 56 // 57 // If cache_only is true, then this function will not attempt to read any 58 // SST files. This will make it more likely this function will 59 // return an error if it is unable to determine if there are any conflicts. 60 // 61 // See comment of CheckKey() for explanation of `snap_seq`, `snap_checker` 62 // and `min_uncommitted`. 63 // 64 // Returns OK on success, BUSY if there is a conflicting write, or other error 65 // status for any unexpected errors. 66 static Status CheckKeyForConflicts( 67 DBImpl* db_impl, ColumnFamilyHandle* column_family, 68 const std::string& key, SequenceNumber snap_seq, bool cache_only, 69 ReadCallback* snap_checker = nullptr, 70 SequenceNumber min_uncommitted = kMaxSequenceNumber); 71 72 // For each key,SequenceNumber pair in the TransactionKeyMap, this function 73 // will verify there have been no writes to the key in the db since that 74 // sequence number. 75 // 76 // Returns OK on success, BUSY if there is a conflicting write, or other error 77 // status for any unexpected errors. 78 // 79 // REQUIRED: this function should only be called on the write thread or if the 80 // mutex is held. 81 static Status CheckKeysForConflicts(DBImpl* db_impl, 82 const TransactionKeyMap& keys, 83 bool cache_only); 84 85 private: 86 // If `snap_checker` == nullptr, writes are always commited in sequence number 87 // order. All sequence number <= `snap_seq` will not conflict with any 88 // write, and all keys > `snap_seq` of `key` will trigger conflict. 89 // If `snap_checker` != nullptr, writes may not commit in sequence number 90 // order. In this case `min_uncommitted` is a lower bound. 91 // seq < `min_uncommitted`: no conflict 92 // seq > `snap_seq`: applicable to conflict 93 // `min_uncommitted` <= seq <= `snap_seq`: call `snap_checker` to determine. 94 static Status CheckKey(DBImpl* db_impl, SuperVersion* sv, 95 SequenceNumber earliest_seq, SequenceNumber snap_seq, 96 const std::string& key, bool cache_only, 97 ReadCallback* snap_checker = nullptr, 98 SequenceNumber min_uncommitted = kMaxSequenceNumber); 99 }; 100 101 } // namespace ROCKSDB_NAMESPACE 102 103 #endif // ROCKSDB_LITE 104