/src/rocksdb/util/duplicate_detector.h
Line | Count | Source (jump to first uncovered line) |
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 | | #include <cstdint> |
9 | | |
10 | | #include "db/db_impl/db_impl.h" |
11 | | #include "logging/logging.h" |
12 | | #include "util/set_comparator.h" |
13 | | |
14 | | namespace ROCKSDB_NAMESPACE { |
15 | | // During recovery if the memtable is flushed we cannot rely on its help on |
16 | | // duplicate key detection and as key insert will not be attempted. This class |
17 | | // will be used as a emulator of memtable to tell if insertion of a key/seq |
18 | | // would have resulted in duplication. |
19 | | class DuplicateDetector { |
20 | | public: |
21 | 0 | explicit DuplicateDetector(DBImpl* db) : db_(db) {} |
22 | 0 | bool IsDuplicateKeySeq(uint32_t cf, const Slice& key, SequenceNumber seq) { |
23 | 0 | assert(seq >= batch_seq_); |
24 | 0 | if (batch_seq_ != seq) { // it is a new batch |
25 | 0 | keys_.clear(); |
26 | 0 | } |
27 | 0 | batch_seq_ = seq; |
28 | 0 | CFKeys& cf_keys = keys_[cf]; |
29 | 0 | if (cf_keys.size() == 0) { // just inserted |
30 | 0 | InitWithComp(cf); |
31 | 0 | } |
32 | 0 | auto it = cf_keys.insert(key); |
33 | 0 | if (it.second == false) { // second is false if a element already existed. |
34 | 0 | keys_.clear(); |
35 | 0 | InitWithComp(cf); |
36 | 0 | keys_[cf].insert(key); |
37 | 0 | return true; |
38 | 0 | } |
39 | 0 | return false; |
40 | 0 | } |
41 | | |
42 | | private: |
43 | | SequenceNumber batch_seq_ = 0; |
44 | | DBImpl* db_; |
45 | | using CFKeys = std::set<Slice, SetComparator>; |
46 | | std::map<uint32_t, CFKeys> keys_; |
47 | 0 | void InitWithComp(const uint32_t cf) { |
48 | 0 | auto h = db_->GetColumnFamilyHandle(cf); |
49 | 0 | if (!h) { |
50 | | // TODO(myabandeh): This is not a concern in MyRocks as drop cf is not |
51 | | // implemented yet. When it does, we should return proper error instead |
52 | | // of throwing exception. |
53 | 0 | ROCKS_LOG_FATAL( |
54 | 0 | db_->immutable_db_options().info_log, |
55 | 0 | "Recovering an entry from the dropped column family %" PRIu32 |
56 | 0 | ". WAL must must have been emptied before dropping the column " |
57 | 0 | "family", |
58 | 0 | cf); |
59 | 0 | throw std::runtime_error( |
60 | 0 | "Recovering an entry from a dropped column family. " |
61 | 0 | "WAL must must have been flushed before dropping the column " |
62 | 0 | "family"); |
63 | 0 | return; |
64 | 0 | } |
65 | 0 | auto cmp = h->GetComparator(); |
66 | 0 | keys_[cf] = CFKeys(SetComparator(cmp)); |
67 | 0 | } |
68 | | }; |
69 | | } // namespace ROCKSDB_NAMESPACE |